Index: ossp-pkg/var/var.c RCS File: /v/ossp/cvs/ossp-pkg/var/var.c,v rcsdiff -q -kk '-r1.69' '-r1.70' -u '/v/ossp/cvs/ossp-pkg/var/var.c,v' 2>/dev/null --- var.c 2002/02/28 12:40:01 1.69 +++ var.c 2002/02/28 20:28:14 1.70 @@ -58,6 +58,16 @@ #define VAR_RC(rv) (rv) #endif /* WITH_EX */ +#ifndef NUL +#define NUL '\0' +#endif + +/* +** +** ==== INTERNAL DATA STRUCTURES ==== +** +*/ + typedef char char_class_t[256]; /* 256 == 2 ^ sizeof(unsigned char)*8 */ /* the external context structure */ @@ -71,7 +81,7 @@ /* the internal expansion context structure */ typedef struct { int force_expand; -} var_expand_t; +} var_parse_t; /* the default syntax configuration */ static const var_syntax_t var_syntax_default = { @@ -85,7 +95,11 @@ "a-zA-Z0-9_" /* name_chars */ }; -/* Routines for manipulation of token buffers. */ +/* +** +** ==== TOKEN BUFFER FUNCTIONS ==== +** +*/ #define TOKENBUF_INITIAL_BUFSIZE 64 @@ -122,7 +136,7 @@ buf->begin = p; buf->end = p + len; buf->buffer_size = len + 1; - *((char *)(buf->end)) = '\0'; + *((char *)(buf->end)) = NUL; return 1; } @@ -176,7 +190,7 @@ /* Append the data at the end of the current buffer. */ memcpy((char *)output->end, data, len); output->end += len; - *((char *)output->end) = '\0'; + *((char *)output->end) = NUL; return 1; } @@ -202,7 +216,11 @@ return num; } -/* Routines for the expansion of quoted-pair expressions. */ +/* +** +** ==== ESCAPE SEQUENCE FUNCTIONS ==== +** +*/ static void expand_range(char a, char b, char_class_t class) { @@ -224,8 +242,8 @@ /* Walk through the class description and set the appropriate entries in the array. */ - while (*desc != '\0') { - if (desc[1] == '-' && desc[2] != '\0') { + while (*desc != NUL) { + if (desc[1] == '-' && desc[2] != NUL) { if (desc[0] > desc[2]) return VAR_ERR_INCORRECT_CLASS_SPEC; expand_range(desc[0], desc[2], class); @@ -341,95 +359,115 @@ return expand_simple_hex(src, dst, end); } -/* The recursive-descent parser for variable expressions. */ - -static int variable(const char *begin, const char *end, - 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_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_syntax_t *config, - const char_class_t nameclass, - var_cb_value_t lookup, void* lookup_context); - -static int text(const char *begin, const char *end, char delim_init, - char index_open, char index_close, char escape) +/* +** +** ==== RECURSIVE-DESCEND VARIABLE EXPANSION PARSER ==== +** +*/ + +/* 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); + +/* parse plain text */ +static int +parse_text( + var_t *var, var_parse_t *ctx, + const char *begin, const char *end) { const char *p; - for (p = begin; p != end; ++p) { - if (*p == escape) { - if (++p == end) + /* parse until delim_init (variable construct) + or index_open (loop construct) is found */ + for (p = begin; p != end; p++) { + if (*p == var->syntax.escape) { + p++; /* skip next character */ + if (p == end) return VAR_ERR_INCOMPLETE_QUOTED_PAIR; } - else if (*p == delim_init) + else if (*p == var->syntax.delim_init) break; - else if (index_open && (*p == index_open || *p == index_close)) + else if ( var->syntax.index_open != NUL + && ( *p == var->syntax.index_open + || *p == var->syntax.index_close)) break; } - return p - begin; + return (p - begin); } -static int varname(const char *begin, const char *end, - const char_class_t nameclass) +/* parse variable name */ +static int +parse_varname( + var_t *var, var_parse_t *ctx, + const char *begin, const char *end) { const char *p; - for (p = begin; p != end && nameclass[(int) *p]; p++) + /* parse as long as name class characters are found */ + for (p = begin; p != end && var->syntax_nameclass[(int)(*p)]; p++) ; - return p - begin; + return (p - begin); } -static int number(const char *begin, const char *end) +/* parse number */ +static int +parse_number( + var_t *var, var_parse_t *ctx, + const char *begin, const char *end) { const char *p; - for (p = begin; p != end && isdigit((int)*p); p++) + /* parse as long as digits are found */ + for (p = begin; p != end && isdigit((int)(*p)); p++) ; - return p - begin; + return (p - begin); } -static int substext(const char *begin, const char *end, - const var_syntax_t *config) +/* parse substitution text */ +static int +parse_substext( + var_t *var, var_parse_t *ctx, + const char *begin, const char *end) { const char *p; - for (p = begin; p != end && *p != config->delim_init && *p != '/'; p++) { - if (*p == config->escape) { + /* parse until delim_init or '/' */ + for (p = begin; p != end && *p != var->syntax.delim_init && *p != '/'; p++) { + if (*p == var->syntax.escape) { if (p + 1 == end) return VAR_ERR_INCOMPLETE_QUOTED_PAIR; p++; } } - return p - begin; + return (p - begin); } -static int exptext(const char *begin, const char *end, - const var_syntax_t *config) +/* parse expression? XXX text */ +static int +parse_exptext( + var_t *var, var_parse_t *ctx, + const char *begin, const char *end) { const char *p; - for (p = begin; - p != end - && *p != config->delim_init - && *p != config->delim_close - && *p != ':'; p++) { - if (*p == config->escape) { + /* parse until delim_init or delim_close or ':' */ + for (p = begin; p != end + && *p != var->syntax.delim_init + && *p != var->syntax.delim_close + && *p != ':'; p++) { + if (*p == var->syntax.escape) { if (p + 1 == end) return VAR_ERR_INCOMPLETE_QUOTED_PAIR; p++; } } - return p - begin; + return (p - begin); } -static int num_exp_read_int(const char **begin, const char *end) +/* convert a string into a decimal number */ +static int +convert_num_exp_read_int(const char **begin, const char *end) { int num = 0; @@ -441,24 +479,26 @@ return num; } -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_syntax_t *config, - const char_class_t nameclass, - var_cb_value_t lookup, void *lookup_context) +/* parse number expression operand */ +static int +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) { - const char* p = begin; + const char *p; tokenbuf_t tmp; int rc; + p = begin; tokenbuf_init(&tmp); if (begin == end) return VAR_ERR_INCOMPLETE_INDEX_SPEC; if (*p == '(') { - rc = num_exp(++p, end, index_mark, result, failed, - rel_lookup_flag, config, nameclass, lookup, lookup_context); + rc = parse_num_exp(var, ctx, ++p, end, index_this, result, failed, + rel_lookup_flag); if (rc < 0) return rc; p += rc; @@ -468,13 +508,13 @@ return VAR_ERR_UNCLOSED_BRACKET_IN_INDEX; ++p; } - else if (*p == config->delim_init) { - rc = variable(p, end, config, nameclass, lookup, - lookup_context, 1, &tmp, index_mark, rel_lookup_flag); + else if (*p == var->syntax.delim_init) { + rc = parse_variable(var, ctx, p, end, + 1, &tmp, index_this, rel_lookup_flag); if (rc == VAR_ERR_UNDEFINED_VARIABLE) { *failed = 1; - rc = variable(p, end, config, nameclass, lookup, - lookup_context, 0, &tmp, index_mark, rel_lookup_flag); + rc = parse_variable(var, ctx, p, end, + 0, &tmp, index_this, rel_lookup_flag); if (rc < 0) return rc; p += rc; @@ -484,25 +524,25 @@ if (rc < 0) return rc; p += rc; - rc = num_exp(tmp.begin, tmp.end, index_mark, result, - failed, rel_lookup_flag, config, nameclass, lookup, lookup_context); + rc = parse_num_exp(var, ctx, tmp.begin, tmp.end, index_this, result, + failed, rel_lookup_flag ); tokenbuf_free(&tmp); if (rc < 0) return rc; } } - else if (config->index_mark && *p == config->index_mark) { + else if (var->syntax.index_mark && *p == var->syntax.index_mark) { p++; - *result = index_mark; + *result = index_this; (*rel_lookup_flag)++; } else if (isdigit(*p)) { - *result = num_exp_read_int(&p, end); + *result = convert_num_exp_read_int(&p, end); } else if (*p == '+') { if (end - p > 1 && isdigit(p[1])) { p++; - *result = num_exp_read_int(&p, end); + *result = convert_num_exp_read_int(&p, end); } else return VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC; @@ -510,7 +550,7 @@ else if (*p == '-') { if (end - p > 1 && isdigit(p[1])) { p++; - *result = num_exp_read_int(&p, end); + *result = convert_num_exp_read_int(&p, end); *result = 0 - *result; } else @@ -519,14 +559,15 @@ else return VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC; - return p - begin; + return (p - begin); } -static int num_exp(const char *begin, const char *end, int index_mark, - int *result, int *failed, int *rel_lookup_flag, - const var_syntax_t *config, - const char_class_t nameclass, - var_cb_value_t lookup, void *lookup_context) +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) { const char *p = begin; char operator; @@ -536,9 +577,8 @@ if (begin == end) return VAR_ERR_INCOMPLETE_INDEX_SPEC; - rc = num_exp_read_operand(p, end, index_mark, result, - failed, rel_lookup_flag, config, nameclass, - lookup, lookup_context); + rc = parse_num_exp_operand(var, ctx, p, end, index_this, result, + failed, rel_lookup_flag); if (rc < 0) return rc; p += rc; @@ -546,8 +586,8 @@ while (p != end) { if (*p == '+' || *p == '-') { operator = *p++; - rc = num_exp(p, end, index_mark, &right, failed, - rel_lookup_flag, config, nameclass, lookup, lookup_context); + rc = parse_num_exp(var, ctx, p, end, index_this, &right, failed, + rel_lookup_flag); if (rc < 0) return rc; p += rc; @@ -558,8 +598,8 @@ } else if (*p == '*' || *p == '/' || *p == '%') { operator = *p++; - rc = num_exp_read_operand(p, end, index_mark, &right, failed, - rel_lookup_flag, config, nameclass, lookup, lookup_context); + rc = parse_num_exp_operand(var, ctx, p, end, index_this, &right, failed, + rel_lookup_flag); if (rc < 0) return rc; p += rc; @@ -593,12 +633,13 @@ return p - begin; } -static int expression(const char *begin, const char *end, - 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 +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) +{ const char *p = begin; const char *data; size_t len, buffer_size; @@ -616,7 +657,7 @@ /* Expect STARTDELIM. */ - if (p == end || *p != config->delim_open) + if (p == end || *p != var->syntax.delim_open) return 0; if (++p == end) @@ -626,7 +667,7 @@ an arbitrary number of VARNAMEs and VARIABLEs. */ do { - rc = varname(p, end, nameclass); + rc = parse_varname(var, ctx, p, end); if (rc < 0) goto error_return; if (rc > 0) { @@ -637,8 +678,8 @@ p += rc; } - rc = variable(p, end, config, nameclass, lookup, lookup_context, - force_expand, &tmp, index_mark, rel_lookup_flag); + rc = parse_variable(var, ctx, p, end, + force_expand, &tmp, index_this, rel_lookup_flag); if (rc < 0) goto error_return; if (rc > 0) { @@ -673,9 +714,9 @@ /* If the next token is START-INDEX, read the index specification. */ - 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 (var->syntax.index_open && *p == var->syntax.index_open) { + rc = parse_num_exp(var, ctx, ++p, end, index_this, &idx, &failed, + rel_lookup_flag); if (rc < 0) goto error_return; if (rc == 0) { @@ -688,7 +729,7 @@ rc = VAR_ERR_INCOMPLETE_INDEX_SPEC; goto error_return; } - if (*p != config->index_close) { + if (*p != var->syntax.index_close) { rc = VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC; goto error_return; } @@ -698,7 +739,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->delim_close && *p != ':')) { + if (p == end || (*p != var->syntax.delim_close && *p != ':')) { rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC; goto error_return; } @@ -712,7 +753,7 @@ result->buffer_size = 0; } else { - rc = (*lookup) (NULL, lookup_context, name.begin, name.end - name.begin, idx, + rc = (*var->cb_value_fct) (var, var->cb_value_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 @@ -748,13 +789,13 @@ while (p != end && *p == ':') { p++; if (!failed) - rc = command(p, end, config, nameclass, lookup, - lookup_context, force_expand, result, - index_mark, rel_lookup_flag); + rc = parse_command(var, ctx, p, end, + force_expand, result, + index_this, rel_lookup_flag); else - rc = command(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmp, - index_mark, rel_lookup_flag); + rc = parse_command(var, ctx, p, end, + force_expand, &tmp, + index_this, rel_lookup_flag); if (rc < 0) goto error_return; p += rc; @@ -762,7 +803,7 @@ result->end += rc; } - if (p == end || *p != config->delim_close) { + if (p == end || *p != var->syntax.delim_close) { rc = VAR_ERR_INCOMPLETE_VARIABLE_SPEC; goto error_return; } @@ -786,11 +827,13 @@ return rc; } -static int variable(const char *begin, const char *end, - 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 +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) { const char *p = begin; const char *data; @@ -804,7 +847,7 @@ /* Expect VARINIT. */ - if (p == end || *p != config->delim_init) + if (p == end || *p != var->syntax.delim_init) return 0; if (++p == end) @@ -813,11 +856,11 @@ /* Try to read the variable name. If that fails, we're parsing a complex expression. */ - rc = varname(p, end, nameclass); + rc = parse_varname(var, ctx, p, end); if (rc < 0) return rc; if (rc > 0) { - rc2 = (*lookup)(NULL, lookup_context, p, rc, 0, &data, &len, &buffer_size); + 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) { result->begin = begin; result->end = begin + 1 + rc; @@ -834,19 +877,20 @@ /* OK, we're dealing with a complex expression here. */ - rc = expression(p, end, config, nameclass, lookup, lookup_context, - force_expand, result, index_mark, rel_lookup_flag); + rc = parse_expression(var, ctx, p, end, + force_expand, result, index_this, rel_lookup_flag); if (rc > 0) rc++; return rc; } -static int exptext_or_variable(const char *begin, const char *end, - 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 +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) { const char *p = begin; tokenbuf_t tmp; @@ -859,7 +903,7 @@ return 0; do { - rc = exptext(p, end, config); + rc = parse_exptext(var, ctx, p, end); if (rc < 0) goto error_return; if (rc > 0) { @@ -870,8 +914,8 @@ p += rc; } - rc = variable(p, end, config, nameclass, lookup, lookup_context, - force_expand, &tmp, index_mark, rel_lookup_flag); + rc = parse_variable(var, ctx, p, end, + force_expand, &tmp, index_this, rel_lookup_flag); if (rc < 0) goto error_return; if (rc > 0) { @@ -893,12 +937,13 @@ return rc; } -static int substext_or_variable(const char *begin, const char *end, - 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 +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) { const char *p = begin; tokenbuf_t tmp; @@ -911,7 +956,7 @@ return 0; do { - rc = substext(p, end, config); + rc = parse_substext(var, ctx, p, end); if (rc < 0) goto error_return; if (rc > 0) { @@ -922,8 +967,8 @@ p += rc; } - rc = variable(p, end, config, nameclass, lookup, lookup_context, - force_expand, &tmp, index_mark, rel_lookup_flag); + rc = parse_variable(var, ctx, p, end, + force_expand, &tmp, index_this, rel_lookup_flag); if (rc < 0) goto error_return; if (rc > 0) { @@ -945,7 +990,7 @@ return rc; } -static int expand_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; @@ -979,9 +1024,9 @@ tokenbuf_init(&srcclass); tokenbuf_init(&dstclass); - if ((rc = expand_class_description(search, &srcclass)) != VAR_OK) + if ((rc = parse_class_description(search, &srcclass)) != VAR_OK) goto error_return; - if ((rc = expand_class_description(replace, &dstclass)) != VAR_OK) + if ((rc = parse_class_description(replace, &dstclass)) != VAR_OK) goto error_return; if (srcclass.begin == srcclass.end) { @@ -1067,7 +1112,7 @@ return VAR_OK; } -static int expand_regex_replace(const char *data, tokenbuf_t *orig, +static int parse_regex_replace(const char *data, tokenbuf_t *orig, regmatch_t *pmatch, tokenbuf_t *expanded) { const char *p = orig->begin; @@ -1219,7 +1264,7 @@ tokenbuf_append(&tmp, p, mydata.end - p); break; } else { - rc = expand_regex_replace(p, replace, pmatch, &myreplace); + rc = parse_regex_replace(p, replace, pmatch, &myreplace); if (rc != VAR_OK) { regfree(&preg); tokenbuf_free(&tmp); @@ -1379,10 +1424,12 @@ return VAR_OK; } -static int command(const char *begin, const char *end, - 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 +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) { const char *p = begin; tokenbuf_t tmptokbuf; @@ -1438,7 +1485,7 @@ case 'o': /* Cut out substrings. */ ++p; - rc = number(p, end); + rc = parse_number(var, ctx, p, end); if (rc == 0) { rc = VAR_ERR_MISSING_START_OFFSET; goto error_return; @@ -1459,7 +1506,7 @@ goto error_return; } - rc = number(p, end); + rc = parse_number(var, ctx, p, end); number2.begin = p; number2.end = p + rc; number2.buffer_size = 0; @@ -1486,9 +1533,9 @@ case '-': /* Substitute parameter if data is empty. */ p++; - rc = exptext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmptokbuf, - index_mark, rel_lookup_flag); + 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) { @@ -1504,8 +1551,8 @@ case '*': /* Return "" if data is not empty, parameter otherwise. */ p++; - rc = exptext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmptokbuf, index_mark, rel_lookup_flag); + 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) { @@ -1527,8 +1574,8 @@ case '+': /* Substitute parameter if data is not empty. */ p++; - rc = exptext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmptokbuf, index_mark, rel_lookup_flag); + 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) { @@ -1549,8 +1596,8 @@ return VAR_ERR_MALFORMATTED_REPLACE; p++; - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &search, index_mark, rel_lookup_flag); + 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; @@ -1561,8 +1608,8 @@ } p++; - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &replace, index_mark, rel_lookup_flag); + 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; @@ -1573,7 +1620,7 @@ } p++; - rc = exptext(p, end, config); + rc = parse_exptext(var, ctx, p, end); if (rc < 0) goto error_return; flags.begin = p; @@ -1595,8 +1642,8 @@ return VAR_ERR_MALFORMATTED_TRANSPOSE; p++; - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &search, index_mark, rel_lookup_flag); + 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; @@ -1607,8 +1654,8 @@ } p++; - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &replace, index_mark, rel_lookup_flag); + 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; @@ -1634,7 +1681,7 @@ return VAR_ERR_MALFORMATTED_PADDING; p++; - rc = number(p, end); + rc = parse_number(var, ctx, p, end); if (rc == 0) { rc = VAR_ERR_MISSING_PADDING_WIDTH; goto error_return; @@ -1650,8 +1697,8 @@ } p++; - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &replace, index_mark, rel_lookup_flag); + 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; @@ -1700,57 +1747,30 @@ return rc; } -struct wrapper_context { - var_cb_value_t lookup; - void *context; - int *rel_lookup_flag; -}; - -static int lookup_wrapper(var_t *var, void *context, - const char *name, size_t name_len, int idx, - const char **data, size_t *data_len, - size_t *buffer_size) +/* expand the loop limits */ +static var_rc_t +parse_looplimits( + var_t *var, + var_parse_t *ctx, + const char *begin, const char *end, + int* start, int* step, int* stop, int* open_end) { - static char buf[1]; - struct wrapper_context *wcon = context; - int rc; - - rc = (*wcon->lookup)(NULL, wcon->context, name, name_len, - idx, data, data_len, buffer_size); - if (rc == VAR_ERR_UNDEFINED_VARIABLE) { - (*wcon->rel_lookup_flag)--; - *data = buf; - *data_len = 0; - *buffer_size = 0; - return VAR_OK; - } - return rc; -} - -static var_rc_t loop_limits(const char *begin, const char *end, - const var_syntax_t *config, - const char_class_t nameclass, - var_cb_value_t lookup, void* lookup_context, - int* start, int* step, int* stop, int* open_end) - { - const char* p = begin; + const char *p; int rc; int failed; int dummy; + p = begin; if (begin == end) return 0; - - if (*p != config->delim_open) + if (*p != var->syntax.delim_open) return 0; else - ++p; + p++; /* Read start value for the loop. */ - failed = 0; - rc = num_exp(p, end, 0, start, &failed, &dummy, - config, nameclass, lookup, lookup_context); + rc = parse_num_exp(var, ctx, p, end, 0, start, &failed, &dummy); if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC) *start = 0; /* use default */ else if (rc < 0) @@ -1763,13 +1783,11 @@ if (*p != ',') return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS; else - ++p; + p++; /* Read step value for the loop. */ - failed = 0; - rc = num_exp(p, end, 0, step, &failed, &dummy, - config, nameclass, lookup, lookup_context); + rc = parse_num_exp(var, ctx, p, end, 0, step, &failed, &dummy); if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC) *step = 1; /* use default */ else if (rc < 0) @@ -1778,14 +1796,11 @@ p += rc; if (failed) return VAR_ERR_UNDEFINED_VARIABLE; - - if (*p != ',') - { - if (*p != config->delim_close) + if (*p != ',') { + if (*p != var->syntax.delim_close) return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS; - else - { - ++p; + else { + p++; *stop = *step; *step = 1; if (rc > 0) @@ -1793,43 +1808,77 @@ else *open_end = 1; return p - begin; - } } + } else - ++p; + p++; /* Read stop value for the loop. */ - failed = 0; - rc = num_exp(p, end, 0, stop, &failed, &dummy, - config, nameclass, lookup, lookup_context); - if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC) - { - *stop = 0; /* use default */ + rc = parse_num_exp(var, ctx, p, end, 0, stop, &failed, &dummy); + if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC) { + *stop = 0; /* use default */ *open_end = 1; - } + } else if (rc < 0) return rc; - else - { + else { *open_end = 0; p += rc; - } + } if (failed) return VAR_ERR_UNDEFINED_VARIABLE; - - if (*p != config->delim_close) + if (*p != var->syntax.delim_close) return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS; 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; } -static var_rc_t input(const char *begin, const char *end, - 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 index_mark, - size_t recursion_level, int *rel_lookup_flag) + 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) { const char *p = begin; int rc, rc2; @@ -1837,7 +1886,7 @@ int start, step, stop, open_end; int i; int output_backup; - struct wrapper_context wcon; + var_wrapper_t wcon; int my_rel_lookup_flag; int original_rel_lookup_state; int loop_limit_length; @@ -1850,12 +1899,9 @@ } do { - if (begin != end && config->index_open && *begin == config->index_open) { + if (begin != end && var->syntax.index_open && *begin == var->syntax.index_open) { original_rel_lookup_state = *rel_lookup_flag; loop_limit_length = -1; - wcon.lookup = lookup; - wcon.context = lookup_context; - wcon.rel_lookup_flag = rel_lookup_flag; begin++; start = 0; step = 1; @@ -1870,34 +1916,41 @@ i += step) { *rel_lookup_flag = original_rel_lookup_state; output_backup = output->end - output->begin; - rc = input(begin, end, config, nameclass, &lookup_wrapper, - &wcon, 1, output, i, recursion_level+1, rel_lookup_flag); + + /* 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; + + rc = parse_input(var, ctx, begin, end, + 1, output, i, recursion_level+1, rel_lookup_flag); + + /* deactivate callback wrapper */ + var->cb_value_fct = wcon.cb_value_fct; + var->cb_value_ctx = wcon.cb_value_ctx; + if (rc < 0) goto error_return; - if (begin[rc] != config->index_close) { + if (begin[rc] != var->syntax.index_close) { rc = VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT; goto error_return; } - if (loop_limit_length < 0) - { - rc2 = loop_limits(begin + rc + 1, end, config, nameclass, - lookup, lookup_context, &start, &step, - &stop, &open_end); + if (loop_limit_length < 0) { + rc2 = parse_looplimits(var, ctx, begin + rc + 1, end, + &start, &step, + &stop, &open_end); if (rc2 < 0) - { goto error_return; - } else if (rc2 == 0) - { loop_limit_length = 0; - } - else if (rc2 > 0) - { + else if (rc2 > 0) { loop_limit_length = rc2; output->end = output->begin + output_backup; goto re_loop; - } } + } } if (open_end) output->end = output->begin + output_backup; @@ -1909,8 +1962,7 @@ continue; } - rc = text(begin, end, config->delim_init, config->index_open, - config->index_close, config->escape); + rc = parse_text(var, ctx, begin, end); if (rc > 0) { if (!tokenbuf_append(output, begin, rc)) { rc = VAR_ERR_OUT_OF_MEMORY; @@ -1921,9 +1973,9 @@ } else if (rc < 0) goto error_return; - rc = variable(begin, end, config, nameclass, lookup, - lookup_context, force_expand, &result, - index_mark, rel_lookup_flag); + rc = parse_variable(var, ctx, begin, end, + force_expand, &result, + index_this, rel_lookup_flag); if (rc > 0) { if (!tokenbuf_append(output, result.begin, result.end - result.begin)) { rc = VAR_ERR_OUT_OF_MEMORY; @@ -1952,7 +2004,11 @@ return rc; } -/* ------------------------------------------------------------------ */ +/* +** +** ==== APPLICATION PROGRAMMING INTERFACE (API) ==== +** +*/ var_rc_t var_create( @@ -2088,7 +2144,7 @@ } else *dst++ = *src++; } - *dst = '\0'; + *dst = NUL; return VAR_OK; } @@ -2099,7 +2155,7 @@ char **dst_ptr, size_t *dst_len, int force_expand) { - var_expand_t ctx; + var_parse_t ctx; tokenbuf_t output; var_rc_t rc; @@ -2116,10 +2172,9 @@ /* call the parsing */ tokenbuf_init(&output); - rc = input(src_ptr, src_ptr + src_len, - &var->syntax, var->syntax_nameclass, - var->cb_value_fct, var->cb_value_ctx, - ctx.force_expand, &output, 0, 0, NULL); + rc = parse_input(var, &ctx, + src_ptr, src_ptr + src_len, + ctx.force_expand, &output, 0, 0, NULL); /* post-process output */ if (rc >= 0) {