--- var.c 2002/02/27 13:44:16 1.61
+++ var.c 2002/02/28 08:08:16 1.62
@@ -31,6 +31,8 @@
#include "config.h"
#endif
+#include <stdlib.h>
+#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
@@ -56,75 +58,29 @@
#define VAR_RC(rv) (rv)
#endif /* WITH_EX */
-/* The default configuration for the parser. */
-
-const var_config_t var_config_default = {
- '$', /* varinit */
- '{', /* startdelim */
- '}', /* enddelim */
- '[', /* startindex */
- ']', /* endindex */
- '#', /* current_index */
- '\\', /* escape */
- "a-zA-Z0-9_" /* namechars */
+/* the external context structure */
+struct var_st {
+ var_syntax_t syntax;
+ var_cb_value_t cb_value_fct;
+ void *cb_value_ctx;
};
-/* The var_strerror() routine will map a var_rc_t into a text message. */
-
-const char *var_strerror(var_rc_t rc)
-{
- static char *var_errors[] = {
- "everything ok", /* VAR_OK = 0 */
- "incomplete named character", /* VAR_ERR_INCOMPLETE_NAMED_CHARACTER */
- "incomplete hexadecimal value", /* VAR_ERR_INCOMPLETE_HEX */
- "invalid hexadecimal value", /* VAR_ERR_INVALID_HEX */
- "octal value too large", /* VAR_ERR_OCTAL_TOO_LARGE */
- "invalid octal value", /* VAR_ERR_INVALID_OCTAL */
- "incomplete octal value", /* VAR_ERR_INCOMPLETE_OCTAL */
- "incomplete grouped hexadecimal value", /* VAR_ERR_INCOMPLETE_GROUPED_HEX */
- "incorrect character class specification", /* VAR_ERR_INCORRECT_CLASS_SPEC */
- "invalid expansion configuration", /* VAR_ERR_INVALID_CONFIGURATION */
- "out of memory", /* VAR_ERR_OUT_OF_MEMORY */
- "incomplete variable specification", /* VAR_ERR_INCOMPLETE_VARIABLE_SPEC */
- "undefined variable", /* VAR_ERR_UNDEFINED_VARIABLE */
- "input is neither text nor variable", /* VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE */
- "unknown command character in variable", /* VAR_ERR_UNKNOWN_COMMAND_CHAR */
- "malformated search and replace operation", /* VAR_ERR_MALFORMATTED_REPLACE */
- "unknown flag in search and replace operation", /* VAR_ERR_UNKNOWN_REPLACE_FLAG */
- "invalid regular expression in search and replace operation", /* VAR_ERR_INVALID_REGEX_IN_REPLACE */
- "missing parameter in command", /* VAR_ERR_MISSING_PARAMETER_IN_COMMAND */
- "empty search string in search and replace operation", /* VAR_ERR_EMPTY_SEARCH_STRING */
- "start offset missing in cut operation", /* VAR_ERR_MISSING_START_OFFSET */
- "offsets in cut operation delimited by unknown character", /* VAR_ERR_INVALID_OFFSET_DELIMITER */
- "range out of bounds in cut operation", /* VAR_ERR_RANGE_OUT_OF_BOUNDS */
- "offset out of bounds in cut operation", /* VAR_ERR_OFFSET_OUT_OF_BOUNDS */
- "logic error in cut operation", /* VAR_ERR_OFFSET_LOGIC */
- "malformatted transpose operation", /* VAR_ERR_MALFORMATTED_TRANSPOSE */
- "source and destination classes do not match in transpose operation", /* VAR_ERR_TRANSPOSE_CLASSES_MISMATCH */
- "empty character class in transpose operation", /* VAR_ERR_EMPTY_TRANSPOSE_CLASS */
- "incorrect character class in transpose operation", /* VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC */
- "malformatted padding operation", /* VAR_ERR_MALFORMATTED_PADDING */
- "width parameter missing in padding operation", /* VAR_ERR_MISSING_PADDING_WIDTH */
- "fill string missing in padding operation", /* VAR_ERR_EMPTY_PADDING_FILL_STRING */
- "unknown quoted pair in search and replace operation", /* VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE */
- "sub-matching reference out of range", /* VAR_ERR_SUBMATCH_OUT_OF_RANGE */
- "invalid argument", /* VAR_ERR_INVALID_ARGUMENT */
- "incomplete quoted pair", /* VAR_ERR_INCOMPLETE_QUOTED_PAIR */
- "lookup function does not support variable arrays", /* VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED */
- "index specification of array variable contains an invalid character", /* VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC */
- "index specification of array variable is incomplete", /* VAR_ERR_INCOMPLETE_INDEX_SPEC */
- "bracket expression in array variable's index is not closed", /* VAR_ERR_UNCLOSED_BRACKET_IN_INDEX */
- "division by zero error in index specification", /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX */
- "unterminated loop construct", /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT */
- "invalid character in loop limits" /* VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS */
- };
-
- rc = 0 - rc;
- if (rc < 0 || rc >= sizeof(var_errors) / sizeof(char *))
- return "unknown error";
+/* the internal expansion context structure */
+typedef struct {
+ int force_expand;
+} var_expand_t;
- return var_errors[rc];
-}
+/* the default syntax configuration */
+static const var_syntax_t var_syntax_default = {
+ '\\', /* escape */
+ '$', /* delim_init */
+ '{', /* delim_open */
+ '}', /* delim_close */
+ '[', /* index_open */
+ ']', /* index_close */
+ '#', /* index_mark */
+ "a-zA-Z0-9_" /* name_chars */
+};
/* Routines for manipulation of token buffers. */
@@ -384,85 +340,25 @@
return expand_simple_hex(src, dst, end);
}
-var_rc_t var_unescape(const char *src, size_t len, char *dst,
- int unescape_all)
-{
- const char *end = src + len;
- var_rc_t rc;
-
- while (src < end) {
- if (*src == '\\') {
- if (++src == end)
- return VAR_RC(VAR_ERR_INCOMPLETE_NAMED_CHARACTER);
- switch (*src) {
- case '\\':
- if (!unescape_all) {
- *dst++ = '\\';
- }
- *dst++ = '\\';
- break;
- case 'n':
- *dst++ = '\n';
- break;
- case 't':
- *dst++ = '\t';
- break;
- case 'r':
- *dst++ = '\r';
- break;
- case 'x':
- ++src;
- if ((rc = expand_hex(&src, &dst, end)) != VAR_OK)
- return VAR_RC(rc);
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (end - src >= 3 && isdigit((int)src[1]) && isdigit((int)src[2])) {
- if ((rc = expand_octal(&src, &dst, end)) != 0)
- return VAR_RC(rc);
- break;
- }
- default:
- if (!unescape_all) {
- *dst++ = '\\';
- }
- *dst++ = *src;
- }
- ++src;
- } else
- *dst++ = *src++;
- }
- *dst = '\0';
- return VAR_OK;
-}
-
/* The recursive-descent parser for variable expressions. */
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 current_index,
+ const var_syntax_t *config, const char_class_t nameclass,
+ var_cb_value_t lookup, void *lookup_context,
+ int force_expand, tokenbuf_t *result, int index_mark,
int* rel_lookup_flag);
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, int current_index, int* rel_lookup_flag);
-static int num_exp(const char *begin, const char *end, int current_index,
+ const var_syntax_t *config, const char_class_t nameclass,
+ var_cb_value_t lookup, void *lookup_context, int force_expand,
+ tokenbuf_t *data, int index_mark, int* rel_lookup_flag);
+static int num_exp(const char *begin, const char *end, int index_mark,
int* result, int* failed, int* rel_lookup_flag,
- const var_config_t *config,
+ const var_syntax_t *config,
const char_class_t nameclass,
- var_cb_t lookup, void* lookup_context);
+ var_cb_value_t lookup, void* lookup_context);
-static int text(const char *begin, const char *end, char varinit,
- char startindex, char endindex, char escape)
+static int text(const char *begin, const char *end, char delim_init,
+ char index_open, char index_close, char escape)
{
const char *p;
@@ -471,9 +367,9 @@
if (++p == end)
return VAR_ERR_INCOMPLETE_QUOTED_PAIR;
}
- else if (*p == varinit)
+ else if (*p == delim_init)
break;
- else if (startindex && (*p == startindex || *p == endindex))
+ else if (index_open && (*p == index_open || *p == index_close))
break;
}
return p - begin;
@@ -499,11 +395,11 @@
}
static int substext(const char *begin, const char *end,
- const var_config_t *config)
+ const var_syntax_t *config)
{
const char *p;
- for (p = begin; p != end && *p != config->varinit && *p != '/'; p++) {
+ for (p = begin; p != end && *p != config->delim_init && *p != '/'; p++) {
if (*p == config->escape) {
if (p + 1 == end)
return VAR_ERR_INCOMPLETE_QUOTED_PAIR;
@@ -514,14 +410,14 @@
}
static int exptext(const char *begin, const char *end,
- const var_config_t *config)
+ const var_syntax_t *config)
{
const char *p;
for (p = begin;
p != end
- && *p != config->varinit
- && *p != config->enddelim
+ && *p != config->delim_init
+ && *p != config->delim_close
&& *p != ':'; p++) {
if (*p == config->escape) {
if (p + 1 == end)
@@ -544,11 +440,11 @@
return num;
}
-static int num_exp_read_operand(const char *begin, const char *end, int current_index,
+static int num_exp_read_operand(const char *begin, const char *end, int index_mark,
int *result, int *failed, int *rel_lookup_flag,
- const var_config_t *config,
+ const var_syntax_t *config,
const char_class_t nameclass,
- var_cb_t lookup, void *lookup_context)
+ var_cb_value_t lookup, void *lookup_context)
{
const char* p = begin;
tokenbuf_t tmp;
@@ -560,7 +456,7 @@
return VAR_ERR_INCOMPLETE_INDEX_SPEC;
if (*p == '(') {
- rc = num_exp(++p, end, current_index, result, failed,
+ rc = num_exp(++p, end, index_mark, result, failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
return rc;
@@ -571,13 +467,13 @@
return VAR_ERR_UNCLOSED_BRACKET_IN_INDEX;
++p;
}
- else if (*p == config->varinit) {
+ else if (*p == config->delim_init) {
rc = variable(p, end, config, nameclass, lookup,
- lookup_context, 1, &tmp, current_index, rel_lookup_flag);
+ lookup_context, 1, &tmp, index_mark, rel_lookup_flag);
if (rc == VAR_ERR_UNDEFINED_VARIABLE) {
*failed = 1;
rc = variable(p, end, config, nameclass, lookup,
- lookup_context, 0, &tmp, current_index, rel_lookup_flag);
+ lookup_context, 0, &tmp, index_mark, rel_lookup_flag);
if (rc < 0)
return rc;
p += rc;
@@ -587,16 +483,16 @@
if (rc < 0)
return rc;
p += rc;
- rc = num_exp(tmp.begin, tmp.end, current_index, result,
+ rc = num_exp(tmp.begin, tmp.end, index_mark, result,
failed, rel_lookup_flag, config, nameclass, lookup, lookup_context);
tokenbuf_free(&tmp);
if (rc < 0)
return rc;
}
}
- else if (config->current_index && *p == config->current_index) {
+ else if (config->index_mark && *p == config->index_mark) {
p++;
- *result = current_index;
+ *result = index_mark;
(*rel_lookup_flag)++;
}
else if (isdigit(*p)) {
@@ -625,11 +521,11 @@
return p - begin;
}
-static int num_exp(const char *begin, const char *end, int current_index,
+static int num_exp(const char *begin, const char *end, int index_mark,
int *result, int *failed, int *rel_lookup_flag,
- const var_config_t *config,
+ const var_syntax_t *config,
const char_class_t nameclass,
- var_cb_t lookup, void *lookup_context)
+ var_cb_value_t lookup, void *lookup_context)
{
const char *p = begin;
char operator;
@@ -639,7 +535,7 @@
if (begin == end)
return VAR_ERR_INCOMPLETE_INDEX_SPEC;
- rc = num_exp_read_operand(p, end, current_index, result,
+ rc = num_exp_read_operand(p, end, index_mark, result,
failed, rel_lookup_flag, config, nameclass,
lookup, lookup_context);
if (rc < 0)
@@ -649,7 +545,7 @@
while (p != end) {
if (*p == '+' || *p == '-') {
operator = *p++;
- rc = num_exp(p, end, current_index, &right, failed,
+ rc = num_exp(p, end, index_mark, &right, failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
return rc;
@@ -661,7 +557,7 @@
}
else if (*p == '*' || *p == '/' || *p == '%') {
operator = *p++;
- rc = num_exp_read_operand(p, end, current_index, &right, failed,
+ rc = num_exp_read_operand(p, end, index_mark, &right, failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
return rc;
@@ -697,10 +593,10 @@
}
static int expression(const char *begin, const char *end,
- const var_config_t *config,
- const char_class_t nameclass, var_cb_t lookup,
+ const var_syntax_t *config,
+ const char_class_t nameclass, var_cb_value_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *result, int current_index, int *rel_lookup_flag)
+ tokenbuf_t *result, int index_mark, int *rel_lookup_flag)
{
const char *p = begin;
const char *data;
@@ -719,7 +615,7 @@
/* Expect STARTDELIM. */
- if (p == end || *p != config->startdelim)
+ if (p == end || *p != config->delim_open)
return 0;
if (++p == end)
@@ -741,7 +637,7 @@
}
rc = variable(p, end, config, nameclass, lookup, lookup_context,
- force_expand, &tmp, current_index, rel_lookup_flag);
+ force_expand, &tmp, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -763,8 +659,8 @@
/* If the next token is START-INDEX, read the index specification. */
- if (config->startindex && *p == config->startindex) {
- rc = num_exp(++p, end, current_index, &idx, &failed,
+ if (config->index_open && *p == config->index_open) {
+ rc = num_exp(++p, end, index_mark, &idx, &failed,
rel_lookup_flag, config, nameclass, lookup, lookup_context);
if (rc < 0)
goto error_return;
@@ -778,7 +674,7 @@
rc = VAR_ERR_INCOMPLETE_INDEX_SPEC;
goto error_return;
}
- if (*p != config->endindex) {
+ if (*p != config->index_close) {
rc = VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC;
goto error_return;
}
@@ -788,7 +684,7 @@
/* Now we have the name of the variable stored in "name". The next
token here must either be an END-DELIM or a ':'. */
- if (p == end || (*p != config->enddelim && *p != ':')) {
+ if (p == end || (*p != config->delim_close && *p != ':')) {
rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
goto error_return;
}
@@ -839,11 +735,11 @@
if (!failed)
rc = command(p, end, config, nameclass, lookup,
lookup_context, force_expand, result,
- current_index, rel_lookup_flag);
+ index_mark, rel_lookup_flag);
else
rc = command(p, end, config, nameclass, lookup,
lookup_context, force_expand, &tmp,
- current_index, rel_lookup_flag);
+ index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
p += rc;
@@ -851,7 +747,7 @@
result->end += rc;
}
- if (p == end || *p != config->enddelim) {
+ if (p == end || *p != config->delim_close) {
rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
goto error_return;
}
@@ -876,9 +772,9 @@
}
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 current_index,
+ const var_syntax_t *config, const char_class_t nameclass,
+ var_cb_value_t lookup, void *lookup_context,
+ int force_expand, tokenbuf_t *result, int index_mark,
int *rel_lookup_flag)
{
const char *p = begin;
@@ -893,7 +789,7 @@
/* Expect VARINIT. */
- if (p == end || *p != config->varinit)
+ if (p == end || *p != config->delim_init)
return 0;
if (++p == end)
@@ -924,17 +820,17 @@
/* OK, we're dealing with a complex expression here. */
rc = expression(p, end, config, nameclass, lookup, lookup_context,
- force_expand, result, current_index, rel_lookup_flag);
+ force_expand, result, index_mark, rel_lookup_flag);
if (rc > 0)
rc++;
return rc;
}
static int exptext_or_variable(const char *begin, const char *end,
- const var_config_t *config,
- const char_class_t nameclass, var_cb_t lookup,
+ const var_syntax_t *config,
+ const char_class_t nameclass, var_cb_value_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *result, int current_index,
+ tokenbuf_t *result, int index_mark,
int *rel_lookup_flag)
{
const char *p = begin;
@@ -960,7 +856,7 @@
}
rc = variable(p, end, config, nameclass, lookup, lookup_context,
- force_expand, &tmp, current_index, rel_lookup_flag);
+ force_expand, &tmp, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -983,10 +879,10 @@
}
static int substext_or_variable(const char *begin, const char *end,
- const var_config_t *config,
- const char_class_t nameclass, var_cb_t lookup,
+ const var_syntax_t *config,
+ const char_class_t nameclass, var_cb_value_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *result, int current_index,
+ tokenbuf_t *result, int index_mark,
int *rel_lookup_flag)
{
const char *p = begin;
@@ -1012,7 +908,7 @@
}
rc = variable(p, end, config, nameclass, lookup, lookup_context,
- force_expand, &tmp, current_index, rel_lookup_flag);
+ force_expand, &tmp, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -1469,9 +1365,9 @@
}
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, int current_index, int *rel_lookup_flag)
+ const var_syntax_t *config, const char_class_t nameclass,
+ var_cb_value_t lookup, void *lookup_context, int force_expand,
+ tokenbuf_t *data, int index_mark, int *rel_lookup_flag)
{
const char *p = begin;
tokenbuf_t tmptokbuf;
@@ -1577,7 +1473,7 @@
p++;
rc = exptext_or_variable(p, end, config, nameclass, lookup,
lookup_context, force_expand, &tmptokbuf,
- current_index, rel_lookup_flag);
+ index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -1594,7 +1490,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, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &tmptokbuf, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -1617,7 +1513,7 @@
case '+': /* Substitute parameter if data is not empty. */
p++;
rc = exptext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &tmptokbuf, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &tmptokbuf, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -1639,7 +1535,7 @@
p++;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &search, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &search, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
p += rc;
@@ -1651,7 +1547,7 @@
p++;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &replace, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &replace, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
p += rc;
@@ -1685,7 +1581,7 @@
p++;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &search, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &search, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
p += rc;
@@ -1697,7 +1593,7 @@
p++;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &replace, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &replace, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
p += rc;
@@ -1740,7 +1636,7 @@
p++;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &replace, current_index, rel_lookup_flag);
+ lookup_context, force_expand, &replace, index_mark, rel_lookup_flag);
if (rc < 0)
goto error_return;
p += rc;
@@ -1790,7 +1686,7 @@
}
struct wrapper_context {
- var_cb_t lookup;
+ var_cb_value_t lookup;
void *context;
int *rel_lookup_flag;
};
@@ -1817,9 +1713,9 @@
}
static var_rc_t loop_limits(const char *begin, const char *end,
- const var_config_t *config,
+ const var_syntax_t *config,
const char_class_t nameclass,
- var_cb_t lookup, void* lookup_context,
+ var_cb_value_t lookup, void* lookup_context,
int* start, int* step, int* stop, int* open_end)
{
const char* p = begin;
@@ -1830,7 +1726,7 @@
if (begin == end)
return 0;
- if (*p != config->startdelim)
+ if (*p != config->delim_open)
return 0;
else
++p;
@@ -1870,7 +1766,7 @@
if (*p != ',')
{
- if (*p != config->enddelim)
+ if (*p != config->delim_close)
return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
else
{
@@ -1907,17 +1803,17 @@
if (failed)
return VAR_ERR_UNDEFINED_VARIABLE;
- if (*p != config->enddelim)
+ if (*p != config->delim_close)
return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
return ++p - begin;
}
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,
+ const var_syntax_t *config,
+ const char_class_t nameclass, var_cb_value_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *output, int current_index,
+ tokenbuf_t *output, int index_mark,
size_t recursion_level, int *rel_lookup_flag)
{
const char *p = begin;
@@ -1939,7 +1835,7 @@
}
do {
- if (begin != end && config->startindex && *begin == config->startindex) {
+ if (begin != end && config->index_open && *begin == config->index_open) {
original_rel_lookup_state = *rel_lookup_flag;
loop_limit_length = -1;
wcon.lookup = lookup;
@@ -1963,7 +1859,7 @@
&wcon, 1, output, i, recursion_level+1, rel_lookup_flag);
if (rc < 0)
goto error_return;
- if (begin[rc] != config->endindex) {
+ if (begin[rc] != config->index_close) {
rc = VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT;
goto error_return;
}
@@ -1998,8 +1894,8 @@
continue;
}
- rc = text(begin, end, config->varinit, config->startindex,
- config->endindex, config->escape);
+ rc = text(begin, end, config->delim_init, config->index_open,
+ config->index_close, config->escape);
if (rc > 0) {
if (!tokenbuf_append(output, begin, rc)) {
rc = VAR_ERR_OUT_OF_MEMORY;
@@ -2012,7 +1908,7 @@
rc = variable(begin, end, config, nameclass, lookup,
lookup_context, force_expand, &result,
- current_index, rel_lookup_flag);
+ index_mark, rel_lookup_flag);
if (rc > 0) {
if (!tokenbuf_append(output, result.begin, result.end - result.begin)) {
rc = VAR_ERR_OUT_OF_MEMORY;
@@ -2041,10 +1937,11 @@
return rc;
}
-var_rc_t var_expand(const char *input_buf, size_t input_len,
- char **result, size_t *result_len,
- var_cb_t lookup, void *lookup_context,
- const var_config_t *config, int force_expand)
+static var_rc_t internal_expand(
+ const char *input_buf, size_t input_len,
+ char **result, size_t *result_len,
+ var_cb_value_t lookup, void *lookup_context,
+ const var_syntax_t *config, int force_expand)
{
char_class_t nameclass;
var_rc_t rc;
@@ -2058,21 +1955,21 @@
/* Optionally use default configuration */
if (config == NULL)
- config = &var_config_default;
+ config = &var_syntax_default;
/* Set the result pointer to the begining of the input buffer so
that it is correctly initialized in case we fail with an error. */
*result = (char *)input_buf;
/* Expand the class description for valid variable names. */
- if ((rc = expand_character_class(config->namechars, nameclass)) != VAR_OK)
+ if ((rc = expand_character_class(config->name_chars, nameclass)) != VAR_OK)
return VAR_RC(rc);
/* Make sure that the specials defined in the configuration do not
appear in the character name class. */
- if (nameclass[(int)config->varinit] ||
- nameclass[(int)config->startdelim] ||
- nameclass[(int)config->enddelim] ||
+ if (nameclass[(int)config->delim_init] ||
+ nameclass[(int)config->delim_open] ||
+ nameclass[(int)config->delim_close] ||
nameclass[(int)config->escape])
return VAR_RC(VAR_ERR_INVALID_CONFIGURATION);
@@ -2108,3 +2005,212 @@
return VAR_RC(rc);
}
+/* ------------------------------------------------------------------ */
+
+var_rc_t
+var_create(
+ var_t **pvar)
+{
+ var_t *var;
+
+ if (pvar == NULL)
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ if ((var = (var_t *)malloc(sizeof(var_t))) == NULL)
+ return VAR_RC(VAR_ERR_OUT_OF_MEMORY);
+ memset(var, 0, sizeof(var));
+ var_config(var, VAR_CONFIG_SYNTAX, &var_syntax_default);
+ *pvar = var;
+ return VAR_OK;
+}
+
+var_rc_t
+var_destroy(
+ var_t *var)
+{
+ if (var == NULL)
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ free(var);
+ return VAR_OK;
+}
+
+var_rc_t
+var_config(
+ var_t *var,
+ var_config_t mode,
+ ...)
+{
+ va_list ap;
+
+ if (var == NULL)
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ va_start(ap, mode);
+ switch (mode) {
+ case VAR_CONFIG_SYNTAX: {
+ var_syntax_t *s;
+ s = (var_syntax_t *)va_arg(ap, void *);
+ if (s == NULL)
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ var->syntax.escape = s->escape;
+ var->syntax.delim_init = s->delim_init;
+ var->syntax.delim_open = s->delim_open;
+ var->syntax.delim_close = s->delim_close;
+ var->syntax.index_open = s->index_open;
+ var->syntax.index_close = s->index_close;
+ var->syntax.index_mark = s->index_mark;
+ if (var->syntax.name_chars != NULL)
+ free(var->syntax.name_chars);
+ var->syntax.name_chars = strdup(s->name_chars);
+ break;
+ }
+ case VAR_CONFIG_CB_VALUE: {
+ var_cb_value_t fct;
+ void *ctx;
+ fct = (var_cb_value_t)va_arg(ap, void *);
+ ctx = (void *)va_arg(ap, void *);
+ var->cb_value_fct = fct;
+ var->cb_value_ctx = ctx;
+ break;
+ }
+ default:
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ }
+ va_end(ap);
+ return VAR_OK;
+}
+
+var_rc_t
+var_unescape(
+ var_t *var,
+ const char *src, size_t srclen,
+ char *dst, size_t dstlen,
+ int all)
+{
+ const char *end;
+ var_rc_t rc;
+
+ if (var == NULL || src == NULL || dst == NULL)
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ end = src + srclen;
+ while (src < end) {
+ if (*src == '\\') {
+ if (++src == end)
+ return VAR_RC(VAR_ERR_INCOMPLETE_NAMED_CHARACTER);
+ switch (*src) {
+ case '\\':
+ if (!all) {
+ *dst++ = '\\';
+ }
+ *dst++ = '\\';
+ break;
+ case 'n':
+ *dst++ = '\n';
+ break;
+ case 't':
+ *dst++ = '\t';
+ break;
+ case 'r':
+ *dst++ = '\r';
+ break;
+ case 'x':
+ ++src;
+ if ((rc = expand_hex(&src, &dst, end)) != VAR_OK)
+ return VAR_RC(rc);
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if ( end - src >= 3
+ && isdigit((int)src[1])
+ && isdigit((int)src[2])) {
+ if ((rc = expand_octal(&src, &dst, end)) != 0)
+ return VAR_RC(rc);
+ break;
+ }
+ default:
+ if (!all) {
+ *dst++ = '\\';
+ }
+ *dst++ = *src;
+ }
+ ++src;
+ } else
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ return VAR_OK;
+}
+
+var_rc_t
+var_expand(
+ var_t *var,
+ const char *src, size_t srclen,
+ char **dst, size_t *dstlen,
+ int force_expand)
+{
+ /* var_expand_t ctx; */
+ var_rc_t rc;
+
+ /* ctx.force_expand = force_expand; */
+ rc = internal_expand(src, srclen, dst, dstlen,
+ var->cb_value_fct, var->cb_value_ctx,
+ &var->syntax, force_expand);
+ return rc;
+}
+
+var_rc_t var_strerror(var_t *var, var_rc_t rc, char **str)
+{
+ static char *errors[] = {
+ "everything ok", /* VAR_OK = 0 */
+ "incomplete named character", /* VAR_ERR_INCOMPLETE_NAMED_CHARACTER */
+ "incomplete hexadecimal value", /* VAR_ERR_INCOMPLETE_HEX */
+ "invalid hexadecimal value", /* VAR_ERR_INVALID_HEX */
+ "octal value too large", /* VAR_ERR_OCTAL_TOO_LARGE */
+ "invalid octal value", /* VAR_ERR_INVALID_OCTAL */
+ "incomplete octal value", /* VAR_ERR_INCOMPLETE_OCTAL */
+ "incomplete grouped hexadecimal value", /* VAR_ERR_INCOMPLETE_GROUPED_HEX */
+ "incorrect character class specification", /* VAR_ERR_INCORRECT_CLASS_SPEC */
+ "invalid expansion configuration", /* VAR_ERR_INVALID_CONFIGURATION */
+ "out of memory", /* VAR_ERR_OUT_OF_MEMORY */
+ "incomplete variable specification", /* VAR_ERR_INCOMPLETE_VARIABLE_SPEC */
+ "undefined variable", /* VAR_ERR_UNDEFINED_VARIABLE */
+ "input is neither text nor variable", /* VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE */
+ "unknown command character in variable", /* VAR_ERR_UNKNOWN_COMMAND_CHAR */
+ "malformated search and replace operation", /* VAR_ERR_MALFORMATTED_REPLACE */
+ "unknown flag in search and replace operation", /* VAR_ERR_UNKNOWN_REPLACE_FLAG */
+ "invalid regular expression in search and replace operation", /* VAR_ERR_INVALID_REGEX_IN_REPLACE */
+ "missing parameter in command", /* VAR_ERR_MISSING_PARAMETER_IN_COMMAND */
+ "empty search string in search and replace operation", /* VAR_ERR_EMPTY_SEARCH_STRING */
+ "start offset missing in cut operation", /* VAR_ERR_MISSING_START_OFFSET */
+ "offsets in cut operation delimited by unknown character", /* VAR_ERR_INVALID_OFFSET_DELIMITER */
+ "range out of bounds in cut operation", /* VAR_ERR_RANGE_OUT_OF_BOUNDS */
+ "offset out of bounds in cut operation", /* VAR_ERR_OFFSET_OUT_OF_BOUNDS */
+ "logic error in cut operation", /* VAR_ERR_OFFSET_LOGIC */
+ "malformatted transpose operation", /* VAR_ERR_MALFORMATTED_TRANSPOSE */
+ "source and destination classes do not match in transpose operation", /* VAR_ERR_TRANSPOSE_CLASSES_MISMATCH */
+ "empty character class in transpose operation", /* VAR_ERR_EMPTY_TRANSPOSE_CLASS */
+ "incorrect character class in transpose operation", /* VAR_ERR_INCORRECT_TRANSPOSE_CLASS_SPEC */
+ "malformatted padding operation", /* VAR_ERR_MALFORMATTED_PADDING */
+ "width parameter missing in padding operation", /* VAR_ERR_MISSING_PADDING_WIDTH */
+ "fill string missing in padding operation", /* VAR_ERR_EMPTY_PADDING_FILL_STRING */
+ "unknown quoted pair in search and replace operation", /* VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE */
+ "sub-matching reference out of range", /* VAR_ERR_SUBMATCH_OUT_OF_RANGE */
+ "invalid argument", /* VAR_ERR_INVALID_ARGUMENT */
+ "incomplete quoted pair", /* VAR_ERR_INCOMPLETE_QUOTED_PAIR */
+ "lookup function does not support variable arrays", /* VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED */
+ "index specification of array variable contains an invalid character", /* VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC */
+ "index specification of array variable is incomplete", /* VAR_ERR_INCOMPLETE_INDEX_SPEC */
+ "bracket expression in array variable's index is not closed", /* VAR_ERR_UNCLOSED_BRACKET_IN_INDEX */
+ "division by zero error in index specification", /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX */
+ "unterminated loop construct", /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT */
+ "invalid character in loop limits" /* VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS */
+ };
+
+ if (str == NULL)
+ return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
+ rc = 0 - rc;
+ if (rc < 0 || rc >= sizeof(errors) / sizeof(char *))
+ *str = "unknown error";
+ else
+ *str = errors[rc];
+ return VAR_OK;
+}
+
|