Index: ossp-pkg/var/var.c RCS File: /v/ossp/cvs/ossp-pkg/var/var.c,v rcsdiff -q -kk '-r1.37' '-r1.38' -u '/v/ossp/cvs/ossp-pkg/var/var.c,v' 2>/dev/null --- 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;