--- var.c 2001/12/03 10:51:27 1.37
+++ var.c 2001/12/04 13:36:37 1.38
@@ -72,12 +72,13 @@
"undefined variable", /* VAR_ERR_UNDEFINED_VARIABLE = -12 */
"input is neither text nor variable", /* VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE = -13 */
"unknown command in variable", /* VAR_ERR_UNKNOWN_COMMAND_CHAR = -14 */
+ "unknown error", /* -15 is not used */
"malformated search and replace operation", /* VAR_ERR_MALFORMATTED_REPLACE = -16 */
"unknown flag specified in search and replace operation", /* VAR_ERR_UNKNOWN_REPLACE_FLAG = -17 */
"invalid regular expression in search and replace operation", /* VAR_ERR_INVALID_REGEX_IN_REPLACE = -18 */
"missing parameter in command", /* VAR_ERR_MISSING_PARAMETER_IN_COMMAND = -19 */
"empty search string in search and replace operation", /* VAR_ERR_EMPTY_SEARCH_STRING = -20 */
- "start offset missing in cut operation" /* VAR_ERR_MISSING_START_OFFSET = -21 */
+ "start offset missing in cut operation", /* VAR_ERR_MISSING_START_OFFSET = -21 */
"offsets in cut operation delimited by unknown character", /* VAR_ERR_INVALID_OFFSET_DELIMITER = -22 */
"range in cut operation is out of bounds", /* VAR_ERR_RANGE_OUT_OF_BOUNDS = -23 */
"offset in cut operation is out of bounds", /* VAR_ERR_OFFSET_OUT_OF_BOUNDS = -24 */
@@ -92,8 +93,11 @@
"unknown quoted pair in search and replace operation", /* VAR_ERR_UNKNOWN_QUOTED_PAIR_IN_REPLACE = -33 */
"submatch referred to in replace string does not exist in search string", /* VAR_ERR_SUBMATCH_OUT_OF_RANGE = -34 */
"invalid argument", /* VAR_ERR_INVALID_ARGUMENT = -35 */
- "incomplete quoted pair" /* VAR_ERR_INCOMPLETE_QUOTED_PAIR = -36 */
- "lookup function does not support variable arrays" /* VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED = -37 */
+ "incomplete quoted pair", /* VAR_ERR_INCOMPLETE_QUOTED_PAIR = -36 */
+ "lookup function does not support variable arrays", /* VAR_ERR_ARRAY_LOOKUPS_ARE_UNSUPPORTED = -37 */
+ "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 */
};
rc = 0 - rc;
@@ -427,6 +431,8 @@
const char_class_t, var_cb_t, void *, int, tokenbuf_t *);
static int command(const char *, const char *, const var_config_t *,
const char_class_t, var_cb_t, void *, int, tokenbuf_t *);
+static int num_exp(const char *begin, const char *end, int current_index,
+ int* result, const var_config_t *config);
static int text(const char *begin, const char *end, char varinit,
char escape)
@@ -488,18 +494,153 @@
return p - begin;
}
+static int num_exp_read_int(const char** begin, const char* end)
+ {
+ int num = 0;
+ do
+ {
+ num *= 10;
+ num += **begin - '0';
+ ++(*begin);
+ }
+ while (isdigit(**begin) && *begin != end);
+ return num;
+ }
+
+static int num_exp_read_operand(const char *begin, const char *end, int current_index,
+ int* result, const var_config_t *config)
+ {
+ const char* p = begin;
+ int rc;
+
+ if (begin == end)
+ return VAR_ERR_INCOMPLETE_INDEX_SPEC;
+
+ printf("Parsing for operand: '%s'\n", p);
+
+ if (*p == '(')
+ {
+ rc = num_exp(++p, end, current_index, result, config);
+ if (rc < 0)
+ return rc;
+ p += rc;
+ if (p == end)
+ return VAR_ERR_INCOMPLETE_INDEX_SPEC;
+ if (*p != ')')
+ return VAR_ERR_UNCLOSED_BRACKET_IN_INDEX;
+ ++p;
+ }
+ else if (*p == config->current_index)
+ {
+ ++p;
+ *result = current_index;
+ }
+ else if (isdigit(*p))
+ {
+ *result = num_exp_read_int(&p, end);
+ }
+ else if (*p == '+')
+ {
+ if (end - p > 1 && isdigit(p[1]))
+ {
+ ++p;
+ *result = num_exp_read_int(&p, end);
+ }
+ else
+ return VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC;
+ }
+ else if (*p == '-')
+ {
+ if (end - p > 1 && isdigit(p[1]))
+ {
+ ++p;
+ *result = num_exp_read_int(&p, end);
+ *result = 0 - *result;
+ }
+ else
+ return VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC;
+ }
+ else
+ return VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC;
+
+ return p - begin;
+ }
+
+static int num_exp(const char *begin, const char *end, int current_index,
+ int* result, const var_config_t *config)
+ {
+ const char* p = begin;
+ char operator;
+ int right;
+ int rc;
+
+ if (begin == end)
+ return VAR_ERR_INCOMPLETE_INDEX_SPEC;
+
+ rc = num_exp_read_operand(p, end, current_index, result, config);
+ if (rc < 0)
+ return rc;
+ p += rc;
+ printf("left operand is %d\n", *result);
+
+ while (p != end)
+ {
+ printf("Parsing for operator: '%s'\n", p);
+ if (*p == '+' || *p == '-')
+ {
+ operator = *p++;
+ printf("Operator is '%c'\n", operator);
+ rc = num_exp(p, end, current_index, &right, config);
+ if (rc < 0)
+ return rc;
+ p += rc;
+ printf("Calculating %d %c %d --> ", *result, operator, right);
+ if (operator == '+')
+ *result = *result + right;
+ else
+ *result = *result - right;
+ printf("%d\n", *result);
+ }
+ else if (*p == '*' || *p == '/' || *p == '%')
+ {
+ operator = *p++;
+ printf("Operator is '%c'\n", operator);
+
+
+ rc = num_exp_read_operand(p, end, current_index, &right, config);
+ if (rc < 0)
+ return rc;
+ p += rc;
+ printf("Calculating %d %c %d --> ", *result, operator, right);
+ if (operator == '*')
+ *result = *result * right;
+ else if (operator == '/')
+ *result = *result / right;
+ else if (operator == '%')
+ *result = *result % right;
+ printf("%d\n", *result);
+ }
+ else
+ break;
+
+ printf("Parsing for right: '%s'\n", p);
+ }
+
+ return p - begin;
+ }
static int expression(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)
-{
+ {
const char *p = begin;
const char *data;
size_t len, buffer_size;
int failed = 0;
int rc;
+ int index = 0;
tokenbuf_t name;
tokenbuf_t tmp;
@@ -520,63 +661,107 @@
/* Get the name of the variable to expand. The name may consist of
an arbitrary number of VARNAMEs and VARIABLEs. */
- do {
+ do
+ {
rc = varname(p, end, nameclass);
if (rc < 0)
goto error_return;
- if (rc > 0) {
- if (!tokenbuf_append(&name, p, rc)) {
+ if (rc > 0)
+ {
+ if (!tokenbuf_append(&name, p, rc))
+ {
rc = VAR_ERR_OUT_OF_MEMORY;
goto error_return;
- }
+ }
p += rc;
- }
+ }
rc = variable(p, end, config, nameclass, lookup, lookup_context,
force_expand, &tmp);
if (rc < 0)
goto error_return;
- if (rc > 0) {
- if (!tokenbuf_append(&name, tmp.begin, tmp.end - tmp.begin)) {
+ if (rc > 0)
+ {
+ if (!tokenbuf_append(&name, tmp.begin, tmp.end - tmp.begin))
+ {
rc = VAR_ERR_OUT_OF_MEMORY;
goto error_return;
- }
+ }
p += rc;
+ }
}
- }
while (rc > 0);
/* We must have the complete variable name now, so make sure we
do. */
- if (name.begin == name.end) {
+ if (name.begin == name.end)
+ {
rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
goto error_return;
- }
+ }
+
+ /* If the next token is START-INDEX, read the index specification. */
+
+ if (*p == config->startindex)
+ {
+ printf("Found START-INDEX: %s\n", p);
+ ++p;
+
+ rc = num_exp(p, end, 0, &index, config);
+ if (rc < 0)
+ goto error_return;
+ if (rc == 0)
+ {
+ rc = VAR_ERR_INCOMPLETE_INDEX_SPEC;
+ goto error_return;
+ }
+ p += rc;
+
+ printf("Expecting END-INDEX: %s\n", p);
+
+ if (p == end)
+ {
+ rc = VAR_ERR_INCOMPLETE_INDEX_SPEC;
+ goto error_return;
+ }
+ if (*p != config->endindex)
+ {
+ rc = VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC;
+ goto error_return;
+ }
+ ++p;
+
+ printf("Found index %d.\n", index);
+
+ }
- /* Now we have the name of the variable stored in "name". We
- expect an ENDDELIM here. */
+ /* 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->enddelim && *p != ':'))
+ {
rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
goto error_return;
- }
+ }
++p;
/* Use the lookup callback to get the variable's contents. */
- rc = (*lookup) (lookup_context, name.begin, name.end - name.begin, 0,
+ rc = (*lookup) (lookup_context, name.begin, name.end - name.begin, index,
&data, &len, &buffer_size);
if (rc < 0)
goto error_return;
- if (rc == 0) {
+ if (rc == 0)
+ {
/* The variable is undefined. What we'll do now depends on the
force_expand flag. */
- if (force_expand) {
+ if (force_expand)
+ {
rc = VAR_ERR_UNDEFINED_VARIABLE;
goto error_return;
- }
+ }
/* Initialize result to point back to the original text in
the buffer. */
@@ -584,21 +769,25 @@
result->end = p;
result->buffer_size = 0;
failed = 1;
- } else {
+ }
+ else
+ {
/* The preliminary result is the contents of the variable.
This may be modified by the commands that may follow. */
result->begin = data;
result->end = data + len;
result->buffer_size = buffer_size;
- }
+ }
- if (p[-1] == ':') {
+ if (p[-1] == ':')
+ {
/* Parse and execute commands. */
tokenbuf_free(&tmp);
--p;
- while (p != end && *p == ':') {
+ while (p != end && *p == ':')
+ {
++p;
if (!failed)
rc = command(p, end, config, nameclass, lookup,
@@ -611,16 +800,17 @@
p += rc;
if (failed)
result->end += rc;
- }
+ }
- if (p == end || *p != config->enddelim) {
+ if (p == end || *p != config->enddelim)
+ {
rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC;
goto error_return;
- }
+ }
++p;
if (failed)
++result->end;
- }
+ }
/* Exit gracefully. */
@@ -635,7 +825,7 @@
tokenbuf_free(&tmp);
tokenbuf_free(result);
return rc;
-}
+ }
static int variable(const char *begin, const char *end,
const var_config_t *config, const char_class_t nameclass,
@@ -1312,9 +1502,9 @@
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);
+ 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;
|