--- var.c 2002/02/28 20:28:14 1.70
+++ var.c 2002/03/01 20:28:33 1.71
@@ -79,9 +79,14 @@
};
/* the internal expansion context structure */
-typedef struct {
- int force_expand;
-} var_parse_t;
+struct var_parse_st {
+ struct var_parse_st *lower;
+ int force_expand;
+ int rel_lookup_flag;
+ int rel_lookup_cnt;
+ int index_this;
+};
+typedef struct var_parse_st var_parse_t;
/* the default syntax configuration */
static const var_syntax_t var_syntax_default = {
@@ -97,6 +102,32 @@
/*
**
+** ==== PARSE CONTEXT FUNCTIONS ====
+**
+*/
+
+static var_parse_t *
+var_parse_push(
+ var_parse_t *lower, var_parse_t *upper)
+{
+ if (upper == NULL)
+ return NULL;
+ memcpy(upper, lower, sizeof(var_parse_t));
+ upper->lower = lower;
+ return upper;
+}
+
+static var_parse_t *
+var_parse_pop(
+ var_parse_t *upper)
+{
+ if (upper == NULL)
+ return NULL;
+ return upper->lower;
+}
+
+/*
+**
** ==== TOKEN BUFFER FUNCTIONS ====
**
*/
@@ -228,6 +259,7 @@
class[(int)a] = 1;
}
while (++a <= b);
+ return;
}
static var_rc_t expand_character_class(const char *desc, char_class_t class)
@@ -366,9 +398,9 @@
*/
/* forward declarations */
-static int parse_variable(var_t *var, var_parse_t *ctx, const char *begin, const char *end, int force_expand, tokenbuf_t *result, int index_this, int* rel_lookup_flag);
-static int parse_command (var_t *var, var_parse_t *ctx, const char *begin, const char *end, int force_expand, tokenbuf_t *data, int index_this, int* rel_lookup_flag);
-static int parse_num_exp (var_t *var, var_parse_t *ctx, const char *begin, const char *end, int index_this, int* result, int* failed, int* rel_lookup_flag);
+static int parse_variable(var_t *var, var_parse_t *ctx, const char *begin, const char *end, tokenbuf_t *result);
+static int parse_command (var_t *var, var_parse_t *ctx, const char *begin, const char *end, tokenbuf_t *data);
+static int parse_num_exp (var_t *var, var_parse_t *ctx, const char *begin, const char *end, int *result, int *failed);
/* parse plain text */
static int
@@ -484,11 +516,13 @@
parse_num_exp_operand(
var_t *var, var_parse_t *ctx,
const char *begin, const char *end,
- int index_this, int *result, int *failed, int *rel_lookup_flag)
+ int *result,
+ int *failed)
{
const char *p;
tokenbuf_t tmp;
int rc;
+ var_parse_t myctx;
p = begin;
tokenbuf_init(&tmp);
@@ -497,8 +531,7 @@
return VAR_ERR_INCOMPLETE_INDEX_SPEC;
if (*p == '(') {
- rc = parse_num_exp(var, ctx, ++p, end, index_this, result, failed,
- rel_lookup_flag);
+ rc = parse_num_exp(var, ctx, ++p, end, result, failed);
if (rc < 0)
return rc;
p += rc;
@@ -509,12 +542,16 @@
++p;
}
else if (*p == var->syntax.delim_init) {
- rc = parse_variable(var, ctx, p, end,
- 1, &tmp, index_this, rel_lookup_flag);
+ ctx = var_parse_push(ctx, &myctx);
+ ctx->force_expand = 1;
+ rc = parse_variable(var, ctx, p, end, &tmp);
+ ctx = var_parse_pop(ctx);
if (rc == VAR_ERR_UNDEFINED_VARIABLE) {
*failed = 1;
- rc = parse_variable(var, ctx, p, end,
- 0, &tmp, index_this, rel_lookup_flag);
+ ctx = var_parse_push(ctx, &myctx);
+ ctx->force_expand = 0;
+ rc = parse_variable(var, ctx, p, end, &tmp);
+ ctx = var_parse_pop(ctx);
if (rc < 0)
return rc;
p += rc;
@@ -524,8 +561,7 @@
if (rc < 0)
return rc;
p += rc;
- rc = parse_num_exp(var, ctx, tmp.begin, tmp.end, index_this, result,
- failed, rel_lookup_flag );
+ rc = parse_num_exp(var, ctx, tmp.begin, tmp.end, result, failed);
tokenbuf_free(&tmp);
if (rc < 0)
return rc;
@@ -533,8 +569,9 @@
}
else if (var->syntax.index_mark && *p == var->syntax.index_mark) {
p++;
- *result = index_this;
- (*rel_lookup_flag)++;
+ *result = ctx->index_this;
+ if (ctx->rel_lookup_flag)
+ ctx->rel_lookup_cnt++;
}
else if (isdigit(*p)) {
*result = convert_num_exp_read_int(&p, end);
@@ -566,8 +603,7 @@
parse_num_exp(
var_t *var, var_parse_t *ctx,
const char *begin, const char *end,
- int index_this,
- int *result, int *failed, int *rel_lookup_flag)
+ int *result, int *failed)
{
const char *p = begin;
char operator;
@@ -577,8 +613,7 @@
if (begin == end)
return VAR_ERR_INCOMPLETE_INDEX_SPEC;
- rc = parse_num_exp_operand(var, ctx, p, end, index_this, result,
- failed, rel_lookup_flag);
+ rc = parse_num_exp_operand(var, ctx, p, end, result, failed);
if (rc < 0)
return rc;
p += rc;
@@ -586,8 +621,7 @@
while (p != end) {
if (*p == '+' || *p == '-') {
operator = *p++;
- rc = parse_num_exp(var, ctx, p, end, index_this, &right, failed,
- rel_lookup_flag);
+ rc = parse_num_exp(var, ctx, p, end, &right, failed);
if (rc < 0)
return rc;
p += rc;
@@ -598,8 +632,7 @@
}
else if (*p == '*' || *p == '/' || *p == '%') {
operator = *p++;
- rc = parse_num_exp_operand(var, ctx, p, end, index_this, &right, failed,
- rel_lookup_flag);
+ rc = parse_num_exp_operand(var, ctx, p, end, &right, failed);
if (rc < 0)
return rc;
p += rc;
@@ -633,12 +666,39 @@
return p - begin;
}
+/* callback wrapper function */
+static int
+lookup_value(
+ var_t *var, var_parse_t *ctx,
+ const char *var_ptr, size_t var_len, int var_idx,
+ const char **val_ptr, size_t *val_len, size_t *val_size)
+{
+ char buf[1];
+ int rc;
+
+ /* pass through to original callback */
+ rc = (*var->cb_value_fct)(var, var->cb_value_ctx,
+ var_ptr, var_len, var_idx,
+ val_ptr, val_len, val_size);
+
+ /* convert undefined variable into empty variable */
+ if (ctx->rel_lookup_flag && rc == VAR_ERR_UNDEFINED_VARIABLE) {
+ ctx->rel_lookup_cnt--;
+ buf[0] = NUL;
+ *val_ptr = buf;
+ *val_len = 0;
+ *val_size = 0;
+ return VAR_OK;
+ }
+
+ return rc;
+}
+
static int
parse_expression(
var_t *var, var_parse_t *ctx,
const char *begin, const char *end,
- int force_expand,
- tokenbuf_t *result, int index_this, int *rel_lookup_flag)
+ tokenbuf_t *result)
{
const char *p = begin;
const char *data;
@@ -678,8 +738,7 @@
p += rc;
}
- rc = parse_variable(var, ctx, p, end,
- force_expand, &tmp, index_this, rel_lookup_flag);
+ rc = parse_variable(var, ctx, p, end, &tmp);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -695,7 +754,7 @@
do. */
if (name.begin == name.end) {
- if (force_expand) {
+ if (ctx->force_expand) {
rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
goto error_return;
}
@@ -715,8 +774,7 @@
/* If the next token is START-INDEX, read the index specification. */
if (var->syntax.index_open && *p == var->syntax.index_open) {
- rc = parse_num_exp(var, ctx, ++p, end, index_this, &idx, &failed,
- rel_lookup_flag);
+ rc = parse_num_exp(var, ctx, ++p, end, &idx, &failed);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -753,12 +811,12 @@
result->buffer_size = 0;
}
else {
- rc = (*var->cb_value_fct) (var, var->cb_value_ctx, name.begin, name.end - name.begin, idx,
- &data, &len, &buffer_size);
+ rc = lookup_value(var, ctx, name.begin, name.end - name.begin, idx,
+ &data, &len, &buffer_size);
if (rc == VAR_ERR_UNDEFINED_VARIABLE) {
/* The variable is undefined. What we'll do now depends on the
force_expand flag. */
- if (force_expand)
+ if (ctx->force_expand)
goto error_return;
/* Initialize result to point back to the original text in
@@ -789,13 +847,9 @@
while (p != end && *p == ':') {
p++;
if (!failed)
- rc = parse_command(var, ctx, p, end,
- force_expand, result,
- index_this, rel_lookup_flag);
+ rc = parse_command(var, ctx, p, end, result);
else
- rc = parse_command(var, ctx, p, end,
- force_expand, &tmp,
- index_this, rel_lookup_flag);
+ rc = parse_command(var, ctx, p, end, &tmp);
if (rc < 0)
goto error_return;
p += rc;
@@ -832,8 +886,7 @@
var_t *var,
var_parse_t *ctx,
const char *begin, const char *end,
- int force_expand, tokenbuf_t *result, int index_this,
- int *rel_lookup_flag)
+ tokenbuf_t *result)
{
const char *p = begin;
const char *data;
@@ -860,8 +913,8 @@
if (rc < 0)
return rc;
if (rc > 0) {
- rc2 = (*var->cb_value_fct)(var, var->cb_value_ctx, p, rc, 0, &data, &len, &buffer_size);
- if (rc2 == VAR_ERR_UNDEFINED_VARIABLE && !force_expand) {
+ rc2 = lookup_value(var, ctx, p, rc, 0, &data, &len, &buffer_size);
+ if (rc2 == VAR_ERR_UNDEFINED_VARIABLE && !ctx->force_expand) {
result->begin = begin;
result->end = begin + 1 + rc;
result->buffer_size = 0;
@@ -877,8 +930,7 @@
/* OK, we're dealing with a complex expression here. */
- rc = parse_expression(var, ctx, p, end,
- force_expand, result, index_this, rel_lookup_flag);
+ rc = parse_expression(var, ctx, p, end, result);
if (rc > 0)
rc++;
return rc;
@@ -888,9 +940,7 @@
parse_exptext_or_variable(
var_t *var, var_parse_t *ctx,
const char *begin, const char *end,
- int force_expand,
- tokenbuf_t *result, int index_this,
- int *rel_lookup_flag)
+ tokenbuf_t *result)
{
const char *p = begin;
tokenbuf_t tmp;
@@ -914,8 +964,7 @@
p += rc;
}
- rc = parse_variable(var, ctx, p, end,
- force_expand, &tmp, index_this, rel_lookup_flag);
+ rc = parse_variable(var, ctx, p, end, &tmp);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -941,9 +990,7 @@
parse_substext_or_variable(
var_t *var, var_parse_t *ctx,
const char *begin, const char *end,
- int force_expand,
- tokenbuf_t *result, int index_this,
- int *rel_lookup_flag)
+ tokenbuf_t *result)
{
const char *p = begin;
tokenbuf_t tmp;
@@ -967,8 +1014,7 @@
p += rc;
}
- rc = parse_variable(var, ctx, p, end,
- force_expand, &tmp, index_this, rel_lookup_flag);
+ rc = parse_variable(var, ctx, p, end, &tmp);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -990,7 +1036,8 @@
return rc;
}
-static int parse_class_description(tokenbuf_t *src, tokenbuf_t *dst)
+static int
+parse_class_description(tokenbuf_t *src, tokenbuf_t *dst)
{
unsigned char c, d;
const char *p = src->begin;
@@ -1013,8 +1060,11 @@
return VAR_OK;
}
-static int transpose(tokenbuf_t *data, tokenbuf_t *search,
- tokenbuf_t *replace)
+static int
+op_transpose(
+ tokenbuf_t *data,
+ tokenbuf_t *search,
+ tokenbuf_t *replace)
{
tokenbuf_t srcclass, dstclass;
const char *p;
@@ -1050,7 +1100,7 @@
for (p = data->begin; p != data->end; ++p) {
for (i = 0; i <= (srcclass.end - srcclass.begin); ++i) {
if (*p == srcclass.begin[i]) {
- *((char *) p) = dstclass.begin[i];
+ *((char *)p) = dstclass.begin[i];
break;
}
}
@@ -1068,8 +1118,12 @@
return rc;
}
-static int cut_out_offset(tokenbuf_t *data, tokenbuf_t *number1,
- tokenbuf_t *number2, int isrange)
+static int
+op_cut_out_offset(
+ tokenbuf_t *data,
+ tokenbuf_t *number1,
+ tokenbuf_t *number2,
+ int isrange)
{
tokenbuf_t res;
const char *p;
@@ -1112,8 +1166,12 @@
return VAR_OK;
}
-static int parse_regex_replace(const char *data, tokenbuf_t *orig,
- regmatch_t *pmatch, tokenbuf_t *expanded)
+static int
+parse_regex_replace(
+ const char *data,
+ tokenbuf_t *orig,
+ regmatch_t *pmatch,
+ tokenbuf_t *expanded)
{
const char *p = orig->begin;
size_t i;
@@ -1162,8 +1220,12 @@
return VAR_OK;
}
-static int search_and_replace(tokenbuf_t *data, tokenbuf_t *search,
- tokenbuf_t *replace, tokenbuf_t *flags)
+static int
+op_search_and_replace(
+ tokenbuf_t *data,
+ tokenbuf_t *search,
+ tokenbuf_t *replace,
+ tokenbuf_t *flags)
{
const char *p;
int case_insensitive = 0;
@@ -1316,8 +1378,12 @@
return VAR_OK;
}
-static int padding(tokenbuf_t *data, tokenbuf_t *widthstr, tokenbuf_t *fill,
- char position)
+static int
+op_padding(
+ tokenbuf_t *data,
+ tokenbuf_t *widthstr,
+ tokenbuf_t *fill,
+ char position)
{
tokenbuf_t result;
size_t width = tokenbuf_toint(widthstr);
@@ -1428,8 +1494,7 @@
parse_command(
var_t *var, var_parse_t *ctx,
const char *begin, const char *end,
- int force_expand,
- tokenbuf_t *data, int index_this, int *rel_lookup_flag)
+ tokenbuf_t *data)
{
const char *p = begin;
tokenbuf_t tmptokbuf;
@@ -1449,281 +1514,272 @@
return 0;
switch (tolower(*p)) {
- case 'l': /* Turn data to lowercase. */
- if (data->begin) {
- char *ptr;
- /* If the buffer does not live in an allocated buffer,
- we have to copy it before modifying the contents. */
+ case 'l': /* Turn data to lowercase. */
+ if (data->begin) {
+ char *ptr;
+ /* If the buffer does not live in an allocated buffer,
+ we have to copy it before modifying the contents. */
+
+ if (data->buffer_size == 0) {
+ if (!tokenbuf_assign(data, data->begin, data->end - data->begin)) {
+ rc = VAR_ERR_OUT_OF_MEMORY;
+ goto error_return;
+ }
+ }
+ for (ptr = (char *)data->begin; ptr != data->end; ++ptr)
+ *ptr = tolower(*ptr);
+ }
+ p++;
+ break;
- if (data->buffer_size == 0) {
- if (!tokenbuf_assign(data, data->begin, data->end - data->begin)) {
- rc = VAR_ERR_OUT_OF_MEMORY;
- goto error_return;
+ case 'u': /* Turn data to uppercase. */
+ if (data->begin) {
+ char *ptr;
+ if (data->buffer_size == 0) {
+ if (!tokenbuf_assign
+ (data, data->begin, data->end - data->begin)) {
+ rc = VAR_ERR_OUT_OF_MEMORY;
+ goto error_return;
+ }
}
+ for (ptr = (char *) data->begin; ptr != data->end; ++ptr)
+ *ptr = toupper(*ptr);
}
- for (ptr = (char *)data->begin; ptr != data->end; ++ptr)
- *ptr = tolower(*ptr);
- }
- p++;
- break;
+ ++p;
+ break;
- case 'u': /* Turn data to uppercase. */
- if (data->begin) {
- char *ptr;
- if (data->buffer_size == 0) {
- if (!tokenbuf_assign
- (data, data->begin, data->end - data->begin)) {
+ case 'o': /* Cut out substrings. */
+ ++p;
+ rc = parse_number(var, ctx, p, end);
+ if (rc == 0) {
+ rc = VAR_ERR_MISSING_START_OFFSET;
+ goto error_return;
+ }
+ number1.begin = p;
+ number1.end = p + rc;
+ number1.buffer_size = 0;
+ p += rc;
+
+ if (*p == ',') {
+ isrange = 0;
+ ++p;
+ } else if (*p == '-') {
+ isrange = 1;
+ ++p;
+ } else {
+ rc = VAR_ERR_INVALID_OFFSET_DELIMITER;
+ goto error_return;
+ }
+
+ rc = parse_number(var, ctx, p, end);
+ number2.begin = p;
+ number2.end = p + rc;
+ number2.buffer_size = 0;
+ p += rc;
+ if (data->begin) {
+ rc = op_cut_out_offset(data, &number1, &number2, isrange);
+ if (rc < 0)
+ goto error_return;
+ }
+ break;
+
+ case '#': /* Substitute length of the string. */
+ if (data->begin) {
+ char buf[((sizeof(int)*8)/3)+10]; /* sufficient size: <#bits> x log_10(2) + safety */
+ sprintf(buf, "%d", (int)(data->end - data->begin));
+ tokenbuf_free(data);
+ if (!tokenbuf_assign(data, buf, strlen(buf))) {
rc = VAR_ERR_OUT_OF_MEMORY;
goto error_return;
}
}
- for (ptr = (char *) data->begin; ptr != data->end; ++ptr)
- *ptr = toupper(*ptr);
- }
- ++p;
- break;
-
- case 'o': /* Cut out substrings. */
- ++p;
- rc = parse_number(var, ctx, p, end);
- if (rc == 0) {
- rc = VAR_ERR_MISSING_START_OFFSET;
- goto error_return;
- }
- number1.begin = p;
- number1.end = p + rc;
- number1.buffer_size = 0;
- p += rc;
-
- if (*p == ',') {
- isrange = 0;
- ++p;
- } else if (*p == '-') {
- isrange = 1;
++p;
- } else {
- rc = VAR_ERR_INVALID_OFFSET_DELIMITER;
- goto error_return;
- }
+ break;
- rc = parse_number(var, ctx, p, end);
- number2.begin = p;
- number2.end = p + rc;
- number2.buffer_size = 0;
- p += rc;
- if (data->begin) {
- rc = cut_out_offset(data, &number1, &number2, isrange);
+ case '-': /* Substitute parameter if data is empty. */
+ p++;
+ rc = parse_exptext_or_variable(var, ctx, p, end, &tmptokbuf);
if (rc < 0)
goto error_return;
- }
- break;
-
- case '#': /* Substitute length of the string. */
- if (data->begin) {
- char buf[((sizeof(int)*8)/3)+10]; /* sufficient size: <#bits> x log_10(2) + safety */
- sprintf(buf, "%d", (int)(data->end - data->begin));
- tokenbuf_free(data);
- if (!tokenbuf_assign(data, buf, strlen(buf))) {
- rc = VAR_ERR_OUT_OF_MEMORY;
+ if (rc == 0) {
+ rc = VAR_ERR_MISSING_PARAMETER_IN_COMMAND;
goto error_return;
}
- }
- ++p;
- break;
-
- case '-': /* Substitute parameter if data is empty. */
- p++;
- rc = parse_exptext_or_variable(var, ctx, p, end,
- force_expand, &tmptokbuf,
- index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- if (rc == 0) {
- rc = VAR_ERR_MISSING_PARAMETER_IN_COMMAND;
- goto error_return;
- }
- p += rc;
- if (data->begin != NULL && data->begin == data->end) {
- tokenbuf_free(data);
- tokenbuf_move(&tmptokbuf, data);
- }
- break;
-
- case '*': /* Return "" if data is not empty, parameter otherwise. */
- p++;
- rc = parse_exptext_or_variable(var, ctx, p, end,
- force_expand, &tmptokbuf, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- if (rc == 0) {
- rc = VAR_ERR_MISSING_PARAMETER_IN_COMMAND;
- goto error_return;
- }
- p += rc;
- if (data->begin != NULL) {
- if (data->begin == data->end) {
+ p += rc;
+ if (data->begin != NULL && data->begin == data->end) {
tokenbuf_free(data);
tokenbuf_move(&tmptokbuf, data);
- } else {
- tokenbuf_free(data);
- data->begin = data->end = "";
- data->buffer_size = 0;
}
- }
- break;
+ break;
- case '+': /* Substitute parameter if data is not empty. */
- p++;
- rc = parse_exptext_or_variable(var, ctx, p, end,
- force_expand, &tmptokbuf, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- if (rc == 0) {
- rc = VAR_ERR_MISSING_PARAMETER_IN_COMMAND;
- goto error_return;
- }
- p += rc;
- if (data->begin != NULL && data->begin != data->end) {
- tokenbuf_free(data);
- tokenbuf_move(&tmptokbuf, data);
- }
- break;
+ case '*': /* Return "" if data is not empty, parameter otherwise. */
+ p++;
+ rc = parse_exptext_or_variable(var, ctx, p, end, &tmptokbuf);
+ if (rc < 0)
+ goto error_return;
+ if (rc == 0) {
+ rc = VAR_ERR_MISSING_PARAMETER_IN_COMMAND;
+ goto error_return;
+ }
+ p += rc;
+ if (data->begin != NULL) {
+ if (data->begin == data->end) {
+ tokenbuf_free(data);
+ tokenbuf_move(&tmptokbuf, data);
+ } else {
+ tokenbuf_free(data);
+ data->begin = data->end = "";
+ data->buffer_size = 0;
+ }
+ }
+ break;
- case 's': /* Search and replace. */
- p++;
+ case '+': /* Substitute parameter if data is not empty. */
+ p++;
+ rc = parse_exptext_or_variable(var, ctx, p, end, &tmptokbuf);
+ if (rc < 0)
+ goto error_return;
+ if (rc == 0) {
+ rc = VAR_ERR_MISSING_PARAMETER_IN_COMMAND;
+ goto error_return;
+ }
+ p += rc;
+ if (data->begin != NULL && data->begin != data->end) {
+ tokenbuf_free(data);
+ tokenbuf_move(&tmptokbuf, data);
+ }
+ break;
- if (*p != '/')
- return VAR_ERR_MALFORMATTED_REPLACE;
- p++;
+ case 's': /* Search and replace. */
+ p++;
- rc = parse_substext_or_variable(var, ctx, p, end,
- force_expand, &search, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- p += rc;
+ if (*p != '/')
+ return VAR_ERR_MALFORMATTED_REPLACE;
+ p++;
- if (*p != '/') {
- rc = VAR_ERR_MALFORMATTED_REPLACE;
- goto error_return;
- }
- p++;
+ rc = parse_substext_or_variable(var, ctx, p, end, &search);
+ if (rc < 0)
+ goto error_return;
+ p += rc;
- rc = parse_substext_or_variable(var, ctx, p, end,
- force_expand, &replace, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- p += rc;
+ if (*p != '/') {
+ rc = VAR_ERR_MALFORMATTED_REPLACE;
+ goto error_return;
+ }
+ p++;
- if (*p != '/') {
- rc = VAR_ERR_MALFORMATTED_REPLACE;
- goto error_return;
- }
- p++;
+ rc = parse_substext_or_variable(var, ctx, p, end, &replace);
+ if (rc < 0)
+ goto error_return;
+ p += rc;
- rc = parse_exptext(var, ctx, p, end);
- if (rc < 0)
- goto error_return;
- flags.begin = p;
- flags.end = p + rc;
- flags.buffer_size = 0;
- p += rc;
+ if (*p != '/') {
+ rc = VAR_ERR_MALFORMATTED_REPLACE;
+ goto error_return;
+ }
+ p++;
- if (data->begin) {
- rc = search_and_replace(data, &search, &replace, &flags);
+ rc = parse_exptext(var, ctx, p, end);
if (rc < 0)
goto error_return;
- }
- break;
-
- case 'y': /* Transpose characters from class A to class B. */
- p++;
+ flags.begin = p;
+ flags.end = p + rc;
+ flags.buffer_size = 0;
+ p += rc;
- if (*p != '/')
- return VAR_ERR_MALFORMATTED_TRANSPOSE;
- p++;
+ if (data->begin) {
+ rc = op_search_and_replace(data, &search, &replace, &flags);
+ if (rc < 0)
+ goto error_return;
+ }
+ break;
- rc = parse_substext_or_variable(var, ctx, p, end,
- force_expand, &search, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- p += rc;
+ case 'y': /* Transpose characters from class A to class B. */
+ p++;
- if (*p != '/') {
- rc = VAR_ERR_MALFORMATTED_TRANSPOSE;
- goto error_return;
- }
- p++;
+ if (*p != '/')
+ return VAR_ERR_MALFORMATTED_TRANSPOSE;
+ p++;
- rc = parse_substext_or_variable(var, ctx, p, end,
- force_expand, &replace, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- p += rc;
+ rc = parse_substext_or_variable(var, ctx, p, end, &search);
+ if (rc < 0)
+ goto error_return;
+ p += rc;
- if (*p != '/') {
- rc = VAR_ERR_MALFORMATTED_TRANSPOSE;
- goto error_return;
- } else
- ++p;
+ if (*p != '/') {
+ rc = VAR_ERR_MALFORMATTED_TRANSPOSE;
+ goto error_return;
+ }
+ p++;
- if (data->begin) {
- rc = transpose(data, &search, &replace);
+ rc = parse_substext_or_variable(var, ctx, p, end, &replace);
if (rc < 0)
goto error_return;
- }
- break;
-
+ p += rc;
- case 'p': /* Padding. */
- p++;
+ if (*p != '/') {
+ rc = VAR_ERR_MALFORMATTED_TRANSPOSE;
+ goto error_return;
+ } else
+ ++p;
- if (*p != '/')
- return VAR_ERR_MALFORMATTED_PADDING;
- p++;
+ if (data->begin) {
+ rc = op_transpose(data, &search, &replace);
+ if (rc < 0)
+ goto error_return;
+ }
+ break;
- rc = parse_number(var, ctx, p, end);
- if (rc == 0) {
- rc = VAR_ERR_MISSING_PADDING_WIDTH;
- goto error_return;
- }
- number1.begin = p;
- number1.end = p + rc;
- number1.buffer_size = 0;
- p += rc;
- if (*p != '/') {
- rc = VAR_ERR_MALFORMATTED_PADDING;
- goto error_return;
- }
- p++;
+ case 'p': /* Padding. */
+ p++;
- rc = parse_substext_or_variable(var, ctx, p, end,
- force_expand, &replace, index_this, rel_lookup_flag);
- if (rc < 0)
- goto error_return;
- p += rc;
+ if (*p != '/')
+ return VAR_ERR_MALFORMATTED_PADDING;
+ p++;
- if (*p != '/') {
- rc = VAR_ERR_MALFORMATTED_PADDING;
- goto error_return;
- }
- p++;
+ rc = parse_number(var, ctx, p, end);
+ if (rc == 0) {
+ rc = VAR_ERR_MISSING_PADDING_WIDTH;
+ goto error_return;
+ }
+ number1.begin = p;
+ number1.end = p + rc;
+ number1.buffer_size = 0;
+ p += rc;
- if (*p != 'l' && *p != 'c' && *p != 'r') {
- rc = VAR_ERR_MALFORMATTED_PADDING;
- goto error_return;
- }
- p++;
+ if (*p != '/') {
+ rc = VAR_ERR_MALFORMATTED_PADDING;
+ goto error_return;
+ }
+ p++;
- if (data->begin) {
- rc = padding(data, &number1, &replace, p[-1]);
+ rc = parse_substext_or_variable(var, ctx, p, end, &replace);
if (rc < 0)
goto error_return;
- }
- break;
+ p += rc;
- default:
- return VAR_ERR_UNKNOWN_COMMAND_CHAR;
+ if (*p != '/') {
+ rc = VAR_ERR_MALFORMATTED_PADDING;
+ goto error_return;
+ }
+ p++;
+
+ if (*p != 'l' && *p != 'c' && *p != 'r') {
+ rc = VAR_ERR_MALFORMATTED_PADDING;
+ goto error_return;
+ }
+ p++;
+
+ if (data->begin) {
+ rc = op_padding(data, &number1, &replace, p[-1]);
+ if (rc < 0)
+ goto error_return;
+ }
+ break;
+
+ default:
+ return VAR_ERR_UNKNOWN_COMMAND_CHAR;
}
/* Exit gracefully. */
@@ -1753,12 +1809,12 @@
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_end)
{
const char *p;
int rc;
int failed;
- int dummy;
p = begin;
if (begin == end)
@@ -1770,7 +1826,7 @@
/* Read start value for the loop. */
failed = 0;
- rc = parse_num_exp(var, ctx, p, end, 0, start, &failed, &dummy);
+ rc = parse_num_exp(var, ctx, p, end, start, &failed);
if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
*start = 0; /* use default */
else if (rc < 0)
@@ -1787,7 +1843,7 @@
/* Read step value for the loop. */
failed = 0;
- rc = parse_num_exp(var, ctx, p, end, 0, step, &failed, &dummy);
+ rc = parse_num_exp(var, ctx, p, end, step, &failed);
if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
*step = 1; /* use default */
else if (rc < 0)
@@ -1815,7 +1871,7 @@
/* Read stop value for the loop. */
failed = 0;
- rc = parse_num_exp(var, ctx, p, end, 0, stop, &failed, &dummy);
+ 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;
@@ -1834,51 +1890,14 @@
return ++p - begin;
}
-/* callback wrapper context */
-typedef struct {
- var_cb_value_t cb_value_fct;
- void *cb_value_ctx;
- int *rel_lookup_flag;
-} var_wrapper_t;
-
-/* callback wrapper function */
-static int
-lookup_wrapper(
- var_t *var, void *ctx,
- const char *var_ptr, size_t var_len, int var_idx,
- const char **val_ptr, size_t *val_len, size_t *val_size)
-{
- char buf[1];
- var_wrapper_t *wcon = (var_wrapper_t *)ctx;
- int rc;
-
- /* pass through to original callback */
- rc = (*wcon->cb_value_fct)(var, wcon->cb_value_ctx,
- var_ptr, var_len, var_idx,
- val_ptr, val_len, val_size);
-
- /* convert undefined variable into empty variable */
- if (rc == VAR_ERR_UNDEFINED_VARIABLE) {
- (*wcon->rel_lookup_flag)--;
- buf[0] = NUL;
- *val_ptr = buf;
- *val_len = 0;
- *val_size = 0;
- return VAR_OK;
- }
-
- return rc;
-}
-
/* expand input in general */
static var_rc_t
parse_input(
var_t *var,
var_parse_t *ctx,
const char *begin, const char *end,
- int force_expand,
- tokenbuf_t *output, int index_this,
- size_t recursion_level, int *rel_lookup_flag)
+ tokenbuf_t *output,
+ int recursion_level)
{
const char *p = begin;
int rc, rc2;
@@ -1886,21 +1905,18 @@
int start, step, stop, open_end;
int i;
int output_backup;
- var_wrapper_t wcon;
- int my_rel_lookup_flag;
- int original_rel_lookup_state;
+ int rel_lookup_cnt;
int loop_limit_length;
+ var_parse_t myctx;
tokenbuf_init(&result);
- if (rel_lookup_flag == NULL) {
- rel_lookup_flag = &my_rel_lookup_flag;
- *rel_lookup_flag = 0;
- }
-
do {
- if (begin != end && var->syntax.index_open && *begin == var->syntax.index_open) {
- original_rel_lookup_state = *rel_lookup_flag;
+ /* try to parse a loop construct */
+ if ( begin != end
+ && var->syntax.index_open != NUL
+ && *begin == var->syntax.index_open) {
+
loop_limit_length = -1;
begin++;
start = 0;
@@ -1909,27 +1925,31 @@
open_end = 1;
rc = 0;
output_backup = 0;
- re_loop:
+ rel_lookup_cnt = ctx->rel_lookup_cnt;
+
+ re_loop:
for (i = start;
- (open_end && (loop_limit_length < 0 || *rel_lookup_flag > original_rel_lookup_state)) ||
- (!open_end && i <= stop);
+ ( ( open_end
+ && ( loop_limit_length < 0
+ || rel_lookup_cnt > ctx->rel_lookup_cnt))
+ || ( !open_end
+ && i <= stop) );
i += step) {
- *rel_lookup_flag = original_rel_lookup_state;
+ /* remember current state for backing off */
output_backup = output->end - output->begin;
- /* activate callback wrapper */
- wcon.cb_value_fct = var->cb_value_fct;
- wcon.cb_value_ctx = var->cb_value_ctx;
- wcon.rel_lookup_flag = rel_lookup_flag;
- var->cb_value_fct = lookup_wrapper;
- var->cb_value_ctx = &wcon;
+ /* open temporary context for recursion */
+ ctx = var_parse_push(ctx, &myctx);
+ ctx->force_expand = 1;
+ ctx->rel_lookup_flag = 1;
+ ctx->index_this = i;
rc = parse_input(var, ctx, begin, end,
- 1, output, i, recursion_level+1, rel_lookup_flag);
+ output, recursion_level+1);
- /* deactivate callback wrapper */
- var->cb_value_fct = wcon.cb_value_fct;
- var->cb_value_ctx = wcon.cb_value_ctx;
+ /* retrieve info and close temporary context */
+ rel_lookup_cnt = ctx->rel_lookup_cnt;
+ ctx = var_parse_pop(ctx);
if (rc < 0)
goto error_return;
@@ -1955,13 +1975,14 @@
if (open_end)
output->end = output->begin + output_backup;
else
- *rel_lookup_flag = original_rel_lookup_state;
+ rel_lookup_cnt = ctx->rel_lookup_cnt;
begin += rc;
begin++;
begin += loop_limit_length;
continue;
}
+ /* try to parse plain text */
rc = parse_text(var, ctx, begin, end);
if (rc > 0) {
if (!tokenbuf_append(output, begin, rc)) {
@@ -1973,9 +1994,8 @@
} else if (rc < 0)
goto error_return;
- rc = parse_variable(var, ctx, begin, end,
- force_expand, &result,
- index_this, rel_lookup_flag);
+ /* try to parse a variable construct */
+ rc = parse_variable(var, ctx, begin, end, &result);
if (rc > 0) {
if (!tokenbuf_append(output, result.begin, result.end - result.begin)) {
rc = VAR_ERR_OUT_OF_MEMORY;
@@ -1986,6 +2006,7 @@
}
if (rc < 0)
goto error_return;
+
} while (begin != end && rc > 0);
if (recursion_level == 0 && begin != end) {
@@ -2164,7 +2185,11 @@
return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
/* prepare internal expansion context */
+ ctx.lower = NULL;
ctx.force_expand = force_expand;
+ ctx.rel_lookup_flag = 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. */
@@ -2172,9 +2197,7 @@
/* call the parsing */
tokenbuf_init(&output);
- rc = parse_input(var, &ctx,
- src_ptr, src_ptr + src_len,
- ctx.force_expand, &output, 0, 0, NULL);
+ rc = parse_input(var, &ctx, src_ptr, src_ptr + src_len, &output, 0);
/* post-process output */
if (rc >= 0) {
|