Index: ossp-pkg/var/var.c RCS File: /v/ossp/cvs/ossp-pkg/var/var.c,v rcsdiff -q -kk '-r1.9' '-r1.10' -u '/v/ossp/cvs/ossp-pkg/var/var.c,v' 2>/dev/null --- var.c 2001/11/13 14:56:05 1.9 +++ var.c 2001/11/13 19:25:41 1.10 @@ -38,11 +38,11 @@ /* The default configuration for the parser. */ const var_config_t var_config_default = { - '$', /* varinit */ - '{', /* startdelim */ - '}', /* enddelim */ - '\\', /* escape */ - "a-zA-Z0-9_" /* namechars */ + '$', /* varinit */ + '{', /* startdelim */ + '}', /* enddelim */ + '\\', /* escape */ + "a-zA-Z0-9_" /* namechars */ }; /* Routines for manipulation of tokenbufs. */ @@ -73,18 +73,18 @@ { char *p = malloc(len + 1); if (p) { - memcpy(p, data, len); - buf->begin = p; - buf->end = p + len; - buf->buffer_size = len + 1; - *((char *) (buf->end)) = '\0'; - return 1; + memcpy(p, data, len); + buf->begin = p; + buf->end = p + len; + buf->buffer_size = len + 1; + *((char *) (buf->end)) = '\0'; + return 1; } else - return 0; + return 0; } static int append_to_tokenbuf(tokenbuf * output, const char *data, - size_t len) + size_t len) { char *new_buffer; size_t new_size; @@ -93,55 +93,55 @@ standard-sized buffer to begin with. */ if (output->begin == NULL) { - if ((output->begin = output->end = - malloc(VAR_INITIAL_BUFFER_SIZE)) == NULL) - return 0; - else - output->buffer_size = VAR_INITIAL_BUFFER_SIZE; + if ((output->begin = output->end = + malloc(VAR_INITIAL_BUFFER_SIZE)) == NULL) + return 0; + else + output->buffer_size = VAR_INITIAL_BUFFER_SIZE; } /* Does the token contain text, but no buffer has been allocated yet? */ if (output->buffer_size == 0) { - /* Check whether data borders to output. If, we can append - simly by increasing the end pointer. */ + /* Check whether data borders to output. If, we can append + simly by increasing the end pointer. */ - if (output->end == data) { - output->end += len; - return 1; - } - - /* OK, so copy the contents of output into an allocated buffer - so that we can append that way. */ - - else { - char *tmp = malloc(output->end - output->begin + len + 1); - if (!tmp) - return 0; - memcpy(tmp, output->begin, output->end - output->begin); - output->buffer_size = output->end - output->begin; - output->begin = tmp; - output->end = tmp + output->buffer_size; - output->buffer_size += len + 1; - } + if (output->end == data) { + output->end += len; + return 1; + } + + /* OK, so copy the contents of output into an allocated buffer + so that we can append that way. */ + + else { + char *tmp = malloc(output->end - output->begin + len + 1); + if (!tmp) + return 0; + memcpy(tmp, output->begin, output->end - output->begin); + output->buffer_size = output->end - output->begin; + output->begin = tmp; + output->end = tmp + output->buffer_size; + output->buffer_size += len + 1; + } } /* Does the token fit into the current buffer? If not, realloc a larger buffer that fits. */ if ((output->buffer_size - (output->end - output->begin)) <= len) { - new_size = output->buffer_size; - do { - new_size *= 2; - } - while ((new_size - (output->end - output->begin)) <= len); - new_buffer = realloc((char *) output->begin, new_size); - if (new_buffer == NULL) - return 0; - output->end = new_buffer + (output->end - output->begin); - output->begin = new_buffer; - output->buffer_size = new_size; + new_size = output->buffer_size; + do { + new_size *= 2; + } + while ((new_size - (output->end - output->begin)) <= len); + new_buffer = realloc((char *) output->begin, new_size); + if (new_buffer == NULL) + return 0; + output->end = new_buffer + (output->end - output->begin); + output->begin = new_buffer; + output->buffer_size = new_size; } /* Append the data at the end of the current buffer. */ @@ -155,7 +155,7 @@ static void free_tokenbuf(tokenbuf * buf) { if (buf->begin != NULL && buf->buffer_size > 0) - free((char *) buf->begin); + free((char *) buf->begin); buf->begin = buf->end = NULL; buf->buffer_size = 0; } @@ -165,8 +165,8 @@ const char *p; size_t num = 0; for (p = number->begin; p != number->end; ++p) { - num *= 10; - num += *p - '0'; + num *= 10; + num += *p - '0'; } return num; } @@ -176,7 +176,7 @@ static void expand_range(char a, char b, char class[256]) { do { - class[(int) a] = 1; + class[(int) a] = 1; } while (++a <= b); } @@ -188,21 +188,21 @@ /* Clear the class array. */ for (i = 0; i < 256; ++i) - class[i] = 0; + class[i] = 0; /* Walk through the class description and set the appropriate entries in the array. */ while (*desc != '\0') { - if (desc[1] == '-' && desc[2] != '\0') { - if (desc[0] > desc[2]) - return VAR_INCORRECT_CLASS_SPEC; - expand_range(desc[0], desc[2], class); - desc += 3; - } else { - class[(int) *desc] = 1; - ++desc; - } + if (desc[1] == '-' && desc[2] != '\0') { + if (desc[0] > desc[2]) + return VAR_INCORRECT_CLASS_SPEC; + expand_range(desc[0], desc[2], class); + desc += 3; + } else { + class[(int) *desc] = 1; + ++desc; + } } return VAR_OK; @@ -211,9 +211,9 @@ static int isoct(char c) { if (c >= '0' && c <= '7') - return 1; + return 1; else - return 0; + return 0; } static var_rc_t expand_octal(const char **src, char **dst, const char *end) @@ -221,13 +221,13 @@ unsigned char c; if (end - *src < 3) - return VAR_INCOMPLETE_OCTAL; + return VAR_INCOMPLETE_OCTAL; if (!isoct(**src) || !isoct((*src)[1]) || !isoct((*src)[2])) - return VAR_INVALID_OCTAL; + return VAR_INVALID_OCTAL; c = **src - '0'; if (c > 3) - return VAR_OCTAL_TOO_LARGE; + return VAR_OCTAL_TOO_LARGE; c *= 8; ++(*src); @@ -245,38 +245,38 @@ static int ishex(char c) { if ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) - return 1; + (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) + return 1; else - return 0; + return 0; } static var_rc_t expand_simple_hex(const char **src, char **dst, - const char *end) + const char *end) { unsigned char c = 0; if (end - *src < 2) - return VAR_INCOMPLETE_HEX; + return VAR_INCOMPLETE_HEX; if (!ishex(**src) || !ishex((*src)[1])) - return VAR_INVALID_HEX; + return VAR_INVALID_HEX; if (**src >= '0' && **src <= '9') - c = **src - '0'; + c = **src - '0'; else if (c >= 'a' && c <= 'f') - c = **src - 'a' + 10; + c = **src - 'a' + 10; else if (c >= 'A' && c <= 'F') - c = **src - 'A' + 10; + c = **src - 'A' + 10; c = c << 4; ++(*src); if (**src >= '0' && **src <= '9') - c += **src - '0'; + c += **src - '0'; else if (**src >= 'a' && **src <= 'f') - c += **src - 'a' + 10; + c += **src - 'a' + 10; else if (**src >= 'A' && **src <= 'F') - c += **src - 'A' + 10; + c += **src - 'A' + 10; **dst = (char) c; ++(*dst); @@ -284,17 +284,17 @@ } static var_rc_t expand_grouped_hex(const char **src, char **dst, - const char *end) + const char *end) { var_rc_t rc; while (*src < end && **src != '}') { - if ((rc = expand_simple_hex(src, dst, end)) != 0) - return rc; - ++(*src); + if ((rc = expand_simple_hex(src, dst, end)) != 0) + return rc; + ++(*src); } if (*src == end) - return VAR_INCOMPLETE_GROUPED_HEX; + return VAR_INCOMPLETE_GROUPED_HEX; return VAR_OK; } @@ -302,69 +302,69 @@ static var_rc_t expand_hex(const char **src, char **dst, const char *end) { if (*src == end) - return VAR_INCOMPLETE_HEX; + return VAR_INCOMPLETE_HEX; if (**src == '{') { - ++(*src); - return expand_grouped_hex(src, dst, end); + ++(*src); + return expand_grouped_hex(src, dst, end); } else - return expand_simple_hex(src, dst, end); + return expand_simple_hex(src, dst, end); } var_rc_t var_unescape(const char *src, size_t len, char *dst, - int unescape_all) + int unescape_all) { const char *end = src + len; var_rc_t rc; while (src < end) { - if (*src == '\\') { - if (++src == end) - return VAR_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)) != 0) - return 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 rc; - break; - } - default: - if (!unescape_all) { - *dst++ = '\\'; - } - *dst++ = *src; - } - ++src; - } else - *dst++ = *src++; + if (*src == '\\') { + if (++src == end) + return VAR_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)) != 0) + return 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 rc; + break; + } + default: + if (!unescape_all) { + *dst++ = '\\'; + } + *dst++ = *src; + } + ++src; + } else + *dst++ = *src++; } *dst = '\0'; return VAR_OK; @@ -373,27 +373,27 @@ /* The recursive-descent parser for variable expressions. */ static int variable(const char *, const char *, const var_config_t *, - const char[256], var_cb_t, void *, int, tokenbuf *); + const char[256], var_cb_t, void *, int, tokenbuf *); static int command(const char *, const char *, const var_config_t *, - const char[256], var_cb_t, void *, int, tokenbuf *); + const char[256], var_cb_t, void *, int, tokenbuf *); static int text(const char *begin, const char *end, char varinit, - char escape) + char escape) { const char *p; for (p = begin; p != end && *p != varinit; ++p) { - if (*p == escape) { - if (p + 1 == end) - return VAR_INCOMPLETE_QUOTED_PAIR; - else - ++p; - } + if (*p == escape) { + if (p + 1 == end) + return VAR_INCOMPLETE_QUOTED_PAIR; + else + ++p; + } } return p - begin; } static int varname(const char *begin, const char *end, - const char nameclass[256]) + const char nameclass[256]) { const char *p; for (p = begin; p != end && nameclass[(int) *p]; ++p); @@ -408,43 +408,43 @@ } static int substext(const char *begin, const char *end, - const var_config_t * config) + const var_config_t * config) { const char *p; for (p = begin; p != end && *p != config->varinit && *p != '/'; ++p) { - if (*p == config->escape) { - if (p + 1 == end) - return VAR_INCOMPLETE_QUOTED_PAIR; - else - ++p; - } + if (*p == config->escape) { + if (p + 1 == end) + return VAR_INCOMPLETE_QUOTED_PAIR; + else + ++p; + } } return p - begin; } static int exptext(const char *begin, const char *end, - const var_config_t * config) + const var_config_t * config) { const char *p; for (p = begin; - p != end && *p != config->varinit && *p != config->enddelim - && *p != ':'; ++p) { - if (*p == config->escape) { - if (p + 1 == end) - return VAR_INCOMPLETE_QUOTED_PAIR; - else - ++p; - } + p != end && *p != config->varinit && *p != config->enddelim + && *p != ':'; ++p) { + if (*p == config->escape) { + if (p + 1 == end) + return VAR_INCOMPLETE_QUOTED_PAIR; + else + ++p; + } } return p - begin; } static int expression(const char *begin, const char *end, - const var_config_t * config, - const char nameclass[256], var_cb_t lookup, - void *lookup_context, int force_expand, - tokenbuf * result) + const var_config_t * config, + const char nameclass[256], var_cb_t lookup, + void *lookup_context, int force_expand, + tokenbuf * result) { const char *p = begin; const char *data; @@ -463,37 +463,37 @@ /* Expect STARTDELIM. */ if (p == end || *p != config->startdelim) - return 0; + return 0; if (++p == end) - return VAR_INCOMPLETE_VARIABLE_SPEC; + return VAR_INCOMPLETE_VARIABLE_SPEC; /* Get the name of the variable to expand. The name may consist of an arbitrary number of VARNAMEs and VARIABLEs. */ do { - rc = varname(p, end, nameclass); - if (rc < 0) - goto error_return; - else if (rc > 0) { - if (!append_to_tokenbuf(&name, p, rc)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } else - p += rc; - } - - rc = variable(p, end, config, nameclass, lookup, lookup_context, - force_expand, &tmp); - if (rc < 0) - goto error_return; - else if (rc > 0) { - if (!append_to_tokenbuf(&name, tmp.begin, tmp.end - tmp.begin)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } else - p += rc; - } + rc = varname(p, end, nameclass); + if (rc < 0) + goto error_return; + else if (rc > 0) { + if (!append_to_tokenbuf(&name, p, rc)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } else + p += rc; + } + + rc = variable(p, end, config, nameclass, lookup, lookup_context, + force_expand, &tmp); + if (rc < 0) + goto error_return; + else if (rc > 0) { + if (!append_to_tokenbuf(&name, tmp.begin, tmp.end - tmp.begin)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } else + p += rc; + } } while (rc > 0); @@ -501,77 +501,77 @@ do. */ if (name.begin == name.end) { - rc = VAR_INCOMPLETE_VARIABLE_SPEC; - goto error_return; + rc = VAR_INCOMPLETE_VARIABLE_SPEC; + goto error_return; } /* Now we have the name of the variable stored in "name". We expect an ENDDELIM here. */ if (p == end || (*p != config->enddelim && *p != ':')) { - rc = VAR_INCOMPLETE_VARIABLE_SPEC; - goto error_return; + rc = VAR_INCOMPLETE_VARIABLE_SPEC; + goto error_return; } else - ++p; + ++p; /* Use the lookup callback to get the variable's contents. */ rc = (*lookup) (lookup_context, name.begin, name.end - name.begin, - &data, &len, &buffer_size); + &data, &len, &buffer_size); if (rc < 0) - goto error_return; + goto error_return; else if (rc == 0) { - /* The variable is undefined. What we'll do now depends on the - force_expand flag. */ + /* The variable is undefined. What we'll do now depends on the + force_expand flag. */ - if (force_expand) { - rc = VAR_UNDEFINED_VARIABLE; - goto error_return; - } else { - /* Initialize result to point back to the original text in - the buffer. */ - - result->begin = begin - 1; - result->end = p; - result->buffer_size = 0; - failed = 1; - } + if (force_expand) { + rc = VAR_UNDEFINED_VARIABLE; + goto error_return; + } else { + /* Initialize result to point back to the original text in + the buffer. */ + + result->begin = begin - 1; + result->end = p; + result->buffer_size = 0; + failed = 1; + } } else { - /* The preliminary result is the contents of the variable. - This may be modified by the commands that may follow. */ + /* 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; + result->begin = data; + result->end = data + len; + result->buffer_size = buffer_size; } if (p[-1] == ':') { - /* Parse and execute commands. */ + /* Parse and execute commands. */ - free_tokenbuf(&tmp); - --p; - while (p != end && *p == ':') { - ++p; - if (!failed) - rc = command(p, end, config, nameclass, lookup, - lookup_context, force_expand, result); - else - rc = command(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmp); - if (rc < 0) - goto error_return; - p += rc; - if (failed) - result->end += rc; - } - - if (p == end || *p != config->enddelim) { - rc = VAR_INCOMPLETE_VARIABLE_SPEC; - goto error_return; - } - ++p; - if (failed) - ++result->end; + free_tokenbuf(&tmp); + --p; + while (p != end && *p == ':') { + ++p; + if (!failed) + rc = command(p, end, config, nameclass, lookup, + lookup_context, force_expand, result); + else + rc = command(p, end, config, nameclass, lookup, + lookup_context, force_expand, &tmp); + if (rc < 0) + goto error_return; + p += rc; + if (failed) + result->end += rc; + } + + if (p == end || *p != config->enddelim) { + rc = VAR_INCOMPLETE_VARIABLE_SPEC; + goto error_return; + } + ++p; + if (failed) + ++result->end; } /* Exit gracefully. */ @@ -590,9 +590,9 @@ } static int variable(const char *begin, const char *end, - const var_config_t * config, const char nameclass[256], - var_cb_t lookup, void *lookup_context, - int force_expand, tokenbuf * result) + const var_config_t * config, const char nameclass[256], + var_cb_t lookup, void *lookup_context, + int force_expand, tokenbuf * result) { const char *p = begin; const char *data; @@ -607,52 +607,52 @@ /* Expect VARINIT. */ if (p == end || *p != config->varinit) - return 0; + return 0; if (++p == end) - return VAR_INCOMPLETE_VARIABLE_SPEC; + return VAR_INCOMPLETE_VARIABLE_SPEC; /* Try to read the variable name. If that fails, we're parsing a complex expression. */ rc = varname(p, end, nameclass); if (rc < 0) - return rc; + return rc; else if (rc > 0) { - rc2 = (*lookup) (lookup_context, p, rc, &data, &len, &buffer_size); - if (rc2 < 0) - return rc2; - else if (rc2 == 0) { - if (force_expand) - return VAR_UNDEFINED_VARIABLE; - else { - result->begin = begin; - result->end = begin + 1 + rc; - result->buffer_size = 0; - return 1 + rc; - } - } else { - result->begin = data; - result->end = data + len; - result->buffer_size = buffer_size; - return 1 + rc; - } + rc2 = (*lookup) (lookup_context, p, rc, &data, &len, &buffer_size); + if (rc2 < 0) + return rc2; + else if (rc2 == 0) { + if (force_expand) + return VAR_UNDEFINED_VARIABLE; + else { + result->begin = begin; + result->end = begin + 1 + rc; + result->buffer_size = 0; + return 1 + rc; + } + } else { + result->begin = data; + result->end = data + len; + result->buffer_size = buffer_size; + return 1 + rc; + } } /* OK, we're dealing with a complex expression here. */ rc = expression(p, end, config, nameclass, lookup, lookup_context, - force_expand, result); + force_expand, result); if (rc > 0) - ++rc; + ++rc; return rc; } static int exptext_or_variable(const char *begin, const char *end, - const var_config_t * config, - const char nameclass[256], var_cb_t lookup, - void *lookup_context, int force_expand, - tokenbuf * result) + const var_config_t * config, + const char nameclass[256], var_cb_t lookup, + void *lookup_context, int force_expand, + tokenbuf * result) { const char *p = begin; tokenbuf tmp; @@ -662,32 +662,32 @@ init_tokenbuf(&tmp); if (begin == end) - return 0; + return 0; do { - rc = exptext(p, end, config); - if (rc < 0) - goto error_return; - else if (rc > 0) { - if (!append_to_tokenbuf(result, p, rc)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } else - p += rc; - } - - rc = variable(p, end, config, nameclass, lookup, lookup_context, - force_expand, &tmp); - if (rc < 0) - goto error_return; - else if (rc > 0) { - p += rc; - if (!append_to_tokenbuf - (result, tmp.begin, tmp.end - tmp.begin)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } - } + rc = exptext(p, end, config); + if (rc < 0) + goto error_return; + else if (rc > 0) { + if (!append_to_tokenbuf(result, p, rc)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } else + p += rc; + } + + rc = variable(p, end, config, nameclass, lookup, lookup_context, + force_expand, &tmp); + if (rc < 0) + goto error_return; + else if (rc > 0) { + p += rc; + if (!append_to_tokenbuf + (result, tmp.begin, tmp.end - tmp.begin)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } + } } while (rc > 0); @@ -701,10 +701,10 @@ } static int substext_or_variable(const char *begin, const char *end, - const var_config_t * config, - const char nameclass[256], var_cb_t lookup, - void *lookup_context, int force_expand, - tokenbuf * result) + const var_config_t * config, + const char nameclass[256], var_cb_t lookup, + void *lookup_context, int force_expand, + tokenbuf * result) { const char *p = begin; tokenbuf tmp; @@ -714,32 +714,32 @@ init_tokenbuf(&tmp); if (begin == end) - return 0; + return 0; do { - rc = substext(p, end, config); - if (rc < 0) - goto error_return; - else if (rc > 0) { - if (!append_to_tokenbuf(result, p, rc)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } else - p += rc; - } - - rc = variable(p, end, config, nameclass, lookup, lookup_context, - force_expand, &tmp); - if (rc < 0) - goto error_return; - else if (rc > 0) { - p += rc; - if (!append_to_tokenbuf - (result, tmp.begin, tmp.end - tmp.begin)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } - } + rc = substext(p, end, config); + if (rc < 0) + goto error_return; + else if (rc > 0) { + if (!append_to_tokenbuf(result, p, rc)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } else + p += rc; + } + + rc = variable(p, end, config, nameclass, lookup, lookup_context, + force_expand, &tmp); + if (rc < 0) + goto error_return; + else if (rc > 0) { + p += rc; + if (!append_to_tokenbuf + (result, tmp.begin, tmp.end - tmp.begin)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } + } } while (rc > 0); @@ -758,26 +758,26 @@ unsigned char c, d; const char *p = src->begin; while (p != src->end) { - if ((src->end - p) >= 3 && p[1] == '-') { - if (*p > p[2]) - return VAR_INCORRECT_TRANSPOSE_CLASS_SPEC; - for (c = *p, d = p[2]; c <= d; ++c) { - if (!append_to_tokenbuf(dst, (char *) &c, 1)) - return VAR_OUT_OF_MEMORY; - } - p += 3; - } else { - if (!append_to_tokenbuf(dst, p, 1)) - return VAR_OUT_OF_MEMORY; - else - ++p; - } + if ((src->end - p) >= 3 && p[1] == '-') { + if (*p > p[2]) + return VAR_INCORRECT_TRANSPOSE_CLASS_SPEC; + for (c = *p, d = p[2]; c <= d; ++c) { + if (!append_to_tokenbuf(dst, (char *) &c, 1)) + return VAR_OUT_OF_MEMORY; + } + p += 3; + } else { + if (!append_to_tokenbuf(dst, p, 1)) + return VAR_OUT_OF_MEMORY; + else + ++p; + } } return VAR_OK; } static int transpose(tokenbuf * data, tokenbuf * search, - tokenbuf * replace) + tokenbuf * replace) { tokenbuf srcclass, dstclass; const char *p; @@ -788,36 +788,36 @@ init_tokenbuf(&dstclass); if ((rc = expand_class_description(search, &srcclass)) != VAR_OK) - goto error_return; + goto error_return; if ((rc = expand_class_description(replace, &dstclass)) != VAR_OK) - goto error_return; + goto error_return; if (srcclass.begin == srcclass.end) { - rc = VAR_EMPTY_TRANSPOSE_CLASS; - goto error_return; + rc = VAR_EMPTY_TRANSPOSE_CLASS; + goto error_return; } if ((srcclass.end - srcclass.begin) != (dstclass.end - dstclass.begin)) { - rc = VAR_TRANSPOSE_CLASSES_MISMATCH; - goto error_return; + rc = VAR_TRANSPOSE_CLASSES_MISMATCH; + goto error_return; } if (data->buffer_size == 0) { - tokenbuf tmp; - if (!assign_to_tokenbuf - (&tmp, data->begin, data->end - data->begin)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } - move_tokenbuf(&tmp, data); + tokenbuf tmp; + if (!assign_to_tokenbuf + (&tmp, data->begin, data->end - data->begin)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } + move_tokenbuf(&tmp, data); } 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]; - break; - } - } + for (i = 0; i <= (srcclass.end - srcclass.begin); ++i) { + if (*p == srcclass.begin[i]) { + *((char *) p) = dstclass.begin[i]; + break; + } + } } free_tokenbuf(&srcclass); @@ -833,7 +833,7 @@ } static int cut_out_offset(tokenbuf * data, tokenbuf * number1, - tokenbuf * number2, int isrange) + tokenbuf * number2, int isrange) { tokenbuf res; const char *p; @@ -843,30 +843,30 @@ /* Determine begin of result string. */ if ((data->end - data->begin) < num1) - return VAR_OFFSET_OUT_OF_BOUNDS; + return VAR_OFFSET_OUT_OF_BOUNDS; else - p = data->begin + num1; + p = data->begin + num1; /* If num2 is zero, we copy the rest from there. */ if (num2 == 0) { - if (!assign_to_tokenbuf(&res, p, data->end - p)) - return VAR_OUT_OF_MEMORY; - } else { /* OK, then use num2. */ - - if (isrange) { - if ((p + num2) > data->end) - return VAR_RANGE_OUT_OF_BOUNDS; - if (!assign_to_tokenbuf(&res, p, num2)) - return VAR_OUT_OF_MEMORY; - } else { - if (num2 < num1) - return VAR_OFFSET_LOGIC_ERROR; - if ((data->begin + num2) > data->end) - return VAR_RANGE_OUT_OF_BOUNDS; - if (!assign_to_tokenbuf(&res, p, (data->begin + num2) - p)) - return VAR_OUT_OF_MEMORY; - } + if (!assign_to_tokenbuf(&res, p, data->end - p)) + return VAR_OUT_OF_MEMORY; + } else { /* OK, then use num2. */ + + if (isrange) { + if ((p + num2) > data->end) + return VAR_RANGE_OUT_OF_BOUNDS; + if (!assign_to_tokenbuf(&res, p, num2)) + return VAR_OUT_OF_MEMORY; + } else { + if (num2 < num1) + return VAR_OFFSET_LOGIC_ERROR; + if ((data->begin + num2) > data->end) + return VAR_RANGE_OUT_OF_BOUNDS; + if (!assign_to_tokenbuf(&res, p, (data->begin + num2) - p)) + return VAR_OUT_OF_MEMORY; + } } free_tokenbuf(data); move_tokenbuf(&res, data); @@ -874,7 +874,7 @@ } static int expand_regex_replace(const char *data, tokenbuf * orig, - regmatch_t * pmatch, tokenbuf * expanded) + regmatch_t * pmatch, tokenbuf * expanded) { const char *p = orig->begin; size_t i; @@ -882,49 +882,49 @@ init_tokenbuf(expanded); while (p != orig->end) { - if (*p == '\\') { - if (orig->end - p <= 1) { - free_tokenbuf(expanded); - return VAR_INCOMPLETE_QUOTED_PAIR; - } else - ++p; - if (*p == '\\') { - if (!append_to_tokenbuf(expanded, p, 1)) { - free_tokenbuf(expanded); - return VAR_OUT_OF_MEMORY; - } - ++p; - continue; - } - if (!isdigit((int)*p)) { - free_tokenbuf(expanded); - return VAR_UNKNOWN_QUOTED_PAIR_IN_REPLACE; - } - i = *p - '0'; - ++p; - if (pmatch[i].rm_so == -1) { - free_tokenbuf(expanded); - return VAR_SUBMATCH_OUT_OF_RANGE; - } - if (!append_to_tokenbuf(expanded, data + pmatch[i].rm_so, - pmatch[i].rm_eo - pmatch[i].rm_so)) { - free_tokenbuf(expanded); - return VAR_OUT_OF_MEMORY; - } - } else { - if (!append_to_tokenbuf(expanded, p, 1)) { - free_tokenbuf(expanded); - return VAR_OUT_OF_MEMORY; - } - ++p; - } + if (*p == '\\') { + if (orig->end - p <= 1) { + free_tokenbuf(expanded); + return VAR_INCOMPLETE_QUOTED_PAIR; + } else + ++p; + if (*p == '\\') { + if (!append_to_tokenbuf(expanded, p, 1)) { + free_tokenbuf(expanded); + return VAR_OUT_OF_MEMORY; + } + ++p; + continue; + } + if (!isdigit((int)*p)) { + free_tokenbuf(expanded); + return VAR_UNKNOWN_QUOTED_PAIR_IN_REPLACE; + } + i = *p - '0'; + ++p; + if (pmatch[i].rm_so == -1) { + free_tokenbuf(expanded); + return VAR_SUBMATCH_OUT_OF_RANGE; + } + if (!append_to_tokenbuf(expanded, data + pmatch[i].rm_so, + pmatch[i].rm_eo - pmatch[i].rm_so)) { + free_tokenbuf(expanded); + return VAR_OUT_OF_MEMORY; + } + } else { + if (!append_to_tokenbuf(expanded, p, 1)) { + free_tokenbuf(expanded); + return VAR_OUT_OF_MEMORY; + } + ++p; + } } return VAR_OK; } static int search_and_replace(tokenbuf * data, tokenbuf * search, - tokenbuf * replace, tokenbuf * flags) + tokenbuf * replace, tokenbuf * flags) { const char *p; int case_insensitive = 0; @@ -933,251 +933,251 @@ int rc; if (search->begin == search->end) - return VAR_EMPTY_SEARCH_STRING; + return VAR_EMPTY_SEARCH_STRING; for (p = flags->begin; p != flags->end; ++p) { - switch (tolower(*p)) { - case 'i': - case_insensitive = 1; - break; - case 'g': - global = 1; - break; - case 't': - no_regex = 1; - break; - default: - return VAR_UNKNOWN_REPLACE_FLAG; - } + switch (tolower(*p)) { + case 'i': + case_insensitive = 1; + break; + case 'g': + global = 1; + break; + case 't': + no_regex = 1; + break; + default: + return VAR_UNKNOWN_REPLACE_FLAG; + } } if (no_regex) { - tokenbuf tmp; - init_tokenbuf(&tmp); + tokenbuf tmp; + init_tokenbuf(&tmp); - for (p = data->begin; p != data->end;) { - if (case_insensitive) - rc = strncasecmp(p, search->begin, - search->end - search->begin); - else - rc = strncmp(p, search->begin, - search->end - search->begin); - if (rc != 0) { /* no match, copy character */ - if (!append_to_tokenbuf(&tmp, p, 1)) { - free_tokenbuf(&tmp); - return VAR_OUT_OF_MEMORY; - } - ++p; - } else { - append_to_tokenbuf(&tmp, replace->begin, - replace->end - replace->begin); - p += search->end - search->begin; - if (!global) { - if (!append_to_tokenbuf(&tmp, p, data->end - p)) { - free_tokenbuf(&tmp); - return VAR_OUT_OF_MEMORY; - } - break; - } - } - } + for (p = data->begin; p != data->end;) { + if (case_insensitive) + rc = strncasecmp(p, search->begin, + search->end - search->begin); + else + rc = strncmp(p, search->begin, + search->end - search->begin); + if (rc != 0) { /* no match, copy character */ + if (!append_to_tokenbuf(&tmp, p, 1)) { + free_tokenbuf(&tmp); + return VAR_OUT_OF_MEMORY; + } + ++p; + } else { + append_to_tokenbuf(&tmp, replace->begin, + replace->end - replace->begin); + p += search->end - search->begin; + if (!global) { + if (!append_to_tokenbuf(&tmp, p, data->end - p)) { + free_tokenbuf(&tmp); + return VAR_OUT_OF_MEMORY; + } + break; + } + } + } - free_tokenbuf(data); - move_tokenbuf(&tmp, data); + free_tokenbuf(data); + move_tokenbuf(&tmp, data); } else { - tokenbuf tmp; - tokenbuf mydata; - tokenbuf myreplace; - regex_t preg; - regmatch_t pmatch[10]; - int regexec_flag; - - /* Copy the pattern and the data to our own buffer to make - sure they're terminated with a null byte. */ - - if (!assign_to_tokenbuf - (&tmp, search->begin, search->end - search->begin)) - return VAR_OUT_OF_MEMORY; - if (!assign_to_tokenbuf - (&mydata, data->begin, data->end - data->begin)) { - free_tokenbuf(&tmp); - return VAR_OUT_OF_MEMORY; - } - - /* Compile the pattern. */ - - rc = regcomp(&preg, tmp.begin, - REG_EXTENDED | ((case_insensitive) ? REG_ICASE : 0)); - free_tokenbuf(&tmp); - if (rc != 0) { - free_tokenbuf(&mydata); - return VAR_INVALID_REGEX_IN_REPLACE; - } - - /* Match the pattern and create the result string in the tmp - buffer. */ - - for (p = mydata.begin; p != mydata.end;) { - if (p == mydata.begin || p[-1] == '\n') - regexec_flag = 0; - else - regexec_flag = REG_NOTBOL; - if (regexec - (&preg, p, sizeof(pmatch) / sizeof(regmatch_t), pmatch, - regexec_flag) == REG_NOMATCH) { - append_to_tokenbuf(&tmp, p, mydata.end - p); - break; - } else { - rc = expand_regex_replace(p, replace, pmatch, &myreplace); - if (rc != VAR_OK) { - regfree(&preg); - free_tokenbuf(&tmp); - free_tokenbuf(&mydata); - return rc; - } - if (!append_to_tokenbuf(&tmp, p, pmatch[0].rm_so) || - !append_to_tokenbuf(&tmp, myreplace.begin, - myreplace.end - myreplace.begin)) { - regfree(&preg); - free_tokenbuf(&tmp); - free_tokenbuf(&mydata); - free_tokenbuf(&myreplace); - return VAR_OUT_OF_MEMORY; - } else { - p += (pmatch[0].rm_eo > 0) ? pmatch[0].rm_eo : 1; - free_tokenbuf(&myreplace); - } - if (!global) { - append_to_tokenbuf(&tmp, p, mydata.end - p); - break; - } - } - } - - regfree(&preg); - free_tokenbuf(data); - move_tokenbuf(&tmp, data); - free_tokenbuf(&mydata); + tokenbuf tmp; + tokenbuf mydata; + tokenbuf myreplace; + regex_t preg; + regmatch_t pmatch[10]; + int regexec_flag; + + /* Copy the pattern and the data to our own buffer to make + sure they're terminated with a null byte. */ + + if (!assign_to_tokenbuf + (&tmp, search->begin, search->end - search->begin)) + return VAR_OUT_OF_MEMORY; + if (!assign_to_tokenbuf + (&mydata, data->begin, data->end - data->begin)) { + free_tokenbuf(&tmp); + return VAR_OUT_OF_MEMORY; + } + + /* Compile the pattern. */ + + rc = regcomp(&preg, tmp.begin, + REG_EXTENDED | ((case_insensitive) ? REG_ICASE : 0)); + free_tokenbuf(&tmp); + if (rc != 0) { + free_tokenbuf(&mydata); + return VAR_INVALID_REGEX_IN_REPLACE; + } + + /* Match the pattern and create the result string in the tmp + buffer. */ + + for (p = mydata.begin; p != mydata.end;) { + if (p == mydata.begin || p[-1] == '\n') + regexec_flag = 0; + else + regexec_flag = REG_NOTBOL; + if (regexec + (&preg, p, sizeof(pmatch) / sizeof(regmatch_t), pmatch, + regexec_flag) == REG_NOMATCH) { + append_to_tokenbuf(&tmp, p, mydata.end - p); + break; + } else { + rc = expand_regex_replace(p, replace, pmatch, &myreplace); + if (rc != VAR_OK) { + regfree(&preg); + free_tokenbuf(&tmp); + free_tokenbuf(&mydata); + return rc; + } + if (!append_to_tokenbuf(&tmp, p, pmatch[0].rm_so) || + !append_to_tokenbuf(&tmp, myreplace.begin, + myreplace.end - myreplace.begin)) { + regfree(&preg); + free_tokenbuf(&tmp); + free_tokenbuf(&mydata); + free_tokenbuf(&myreplace); + return VAR_OUT_OF_MEMORY; + } else { + p += (pmatch[0].rm_eo > 0) ? pmatch[0].rm_eo : 1; + free_tokenbuf(&myreplace); + } + if (!global) { + append_to_tokenbuf(&tmp, p, mydata.end - p); + break; + } + } + } + + regfree(&preg); + free_tokenbuf(data); + move_tokenbuf(&tmp, data); + free_tokenbuf(&mydata); } return VAR_OK; } static int padding(tokenbuf * data, tokenbuf * widthstr, tokenbuf * fill, - char position) + char position) { tokenbuf result; size_t width = tokenbuf2int(widthstr); int i; if (fill->begin == fill->end) - return VAR_EMPTY_PADDING_FILL_STRING; + return VAR_EMPTY_PADDING_FILL_STRING; init_tokenbuf(&result); if (position == 'l') { - i = width - (data->end - data->begin); - if (i > 0) { - i = i / (fill->end - fill->begin); - while (i > 0) { - if (!append_to_tokenbuf - (data, fill->begin, fill->end - fill->begin)) - return VAR_OUT_OF_MEMORY; - --i; - } - i = (width - (data->end - data->begin)) % (fill->end - - fill->begin); - if (!append_to_tokenbuf(data, fill->begin, i)) - return VAR_OUT_OF_MEMORY; - } + i = width - (data->end - data->begin); + if (i > 0) { + i = i / (fill->end - fill->begin); + while (i > 0) { + if (!append_to_tokenbuf + (data, fill->begin, fill->end - fill->begin)) + return VAR_OUT_OF_MEMORY; + --i; + } + i = (width - (data->end - data->begin)) % (fill->end - + fill->begin); + if (!append_to_tokenbuf(data, fill->begin, i)) + return VAR_OUT_OF_MEMORY; + } } else if (position == 'r') { - i = width - (data->end - data->begin); - if (i > 0) { - i = i / (fill->end - fill->begin); - while (i > 0) { - if (!append_to_tokenbuf - (&result, fill->begin, fill->end - fill->begin)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - --i; - } - i = (width - (data->end - data->begin)) % (fill->end - - fill->begin); - if (!append_to_tokenbuf(&result, fill->begin, i)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - if (!append_to_tokenbuf - (&result, data->begin, data->end - data->begin)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - - free_tokenbuf(data); - move_tokenbuf(&result, data); - } + i = width - (data->end - data->begin); + if (i > 0) { + i = i / (fill->end - fill->begin); + while (i > 0) { + if (!append_to_tokenbuf + (&result, fill->begin, fill->end - fill->begin)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + --i; + } + i = (width - (data->end - data->begin)) % (fill->end - + fill->begin); + if (!append_to_tokenbuf(&result, fill->begin, i)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + if (!append_to_tokenbuf + (&result, data->begin, data->end - data->begin)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + + free_tokenbuf(data); + move_tokenbuf(&result, data); + } } else if (position == 'c') { - i = (width - (data->end - data->begin)) / 2; - if (i > 0) { - /* Create the prefix. */ - - i = i / (fill->end - fill->begin); - while (i > 0) { - if (!append_to_tokenbuf - (&result, fill->begin, fill->end - fill->begin)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - --i; - } - i = ((width - (data->end - data->begin)) / 2) % (fill->end - - fill->begin); - if (!append_to_tokenbuf(&result, fill->begin, i)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - - /* Append the actual data string. */ - - if (!append_to_tokenbuf - (&result, data->begin, data->end - data->begin)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - - /* Append the suffix. */ - - i = width - (result.end - result.begin); - i = i / (fill->end - fill->begin); - while (i > 0) { - if (!append_to_tokenbuf - (&result, fill->begin, fill->end - fill->begin)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - --i; - } - i = width - (result.end - result.begin); - if (!append_to_tokenbuf(&result, fill->begin, i)) { - free_tokenbuf(&result); - return VAR_OUT_OF_MEMORY; - } - - /* Move string from temporary buffer to data buffer. */ - - free_tokenbuf(data); - move_tokenbuf(&result, data); - } + i = (width - (data->end - data->begin)) / 2; + if (i > 0) { + /* Create the prefix. */ + + i = i / (fill->end - fill->begin); + while (i > 0) { + if (!append_to_tokenbuf + (&result, fill->begin, fill->end - fill->begin)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + --i; + } + i = ((width - (data->end - data->begin)) / 2) % (fill->end - + fill->begin); + if (!append_to_tokenbuf(&result, fill->begin, i)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + + /* Append the actual data string. */ + + if (!append_to_tokenbuf + (&result, data->begin, data->end - data->begin)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + + /* Append the suffix. */ + + i = width - (result.end - result.begin); + i = i / (fill->end - fill->begin); + while (i > 0) { + if (!append_to_tokenbuf + (&result, fill->begin, fill->end - fill->begin)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + --i; + } + i = width - (result.end - result.begin); + if (!append_to_tokenbuf(&result, fill->begin, i)) { + free_tokenbuf(&result); + return VAR_OUT_OF_MEMORY; + } + + /* Move string from temporary buffer to data buffer. */ + + free_tokenbuf(data); + move_tokenbuf(&result, data); + } } return VAR_OK; } static int command(const char *begin, const char *end, - const var_config_t * config, const char nameclass[256], - var_cb_t lookup, void *lookup_context, int force_expand, - tokenbuf * data) + const var_config_t * config, const char nameclass[256], + var_cb_t lookup, void *lookup_context, int force_expand, + tokenbuf * data) { const char *p = begin; tokenbuf tmptokbuf; @@ -1194,298 +1194,298 @@ init_tokenbuf(&number2); if (begin == end) - return 0; + return 0; switch (tolower(*p)) { - case 'l': /* Turn data to lowercase. */ - if (data->begin) { - char *ptr; - /* If the buffer does not life in an allocated buffer, - we have to copy it before modifying the contents. */ - - if (data->buffer_size == 0) { - if (!assign_to_tokenbuf - (data, data->begin, data->end - data->begin)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } - } - for (ptr = (char *) data->begin; ptr != data->end; ++ptr) - *ptr = tolower(*ptr); - } - ++p; - break; - - case 'u': /* Turn data to uppercase. */ - if (data->begin) { - char *ptr; - if (data->buffer_size == 0) { - if (!assign_to_tokenbuf - (data, data->begin, data->end - data->begin)) { - rc = VAR_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 = number(p, end); - if (rc == 0) { - rc = VAR_MISSING_START_OFFSET; - goto error_return; - } else { - 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_INVALID_OFFSET_DELIMITER; - goto error_return; - } - - rc = number(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); - if (rc < 0) - goto error_return; - } - break; - - case '#': /* Substitute length of the string. */ - if (data->begin) { - char buf[1024]; - sprintf(buf, "%d", data->end - data->begin); - free_tokenbuf(data); - if (!assign_to_tokenbuf(data, buf, strlen(buf))) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } - } - ++p; - break; - - case '-': /* Substitute parameter if data is empty. */ - ++p; - rc = exptext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmptokbuf); - if (rc < 0) - goto error_return; - else if (rc == 0) { - rc = VAR_MISSING_PARAMETER_IN_COMMAND; - goto error_return; - } else - p += rc; - if (data->begin != NULL && data->begin == data->end) { - free_tokenbuf(data); - move_tokenbuf(&tmptokbuf, data); - } - break; - - case '*': /* Return "" if data is not empty, parameter otherwise. */ - ++p; - rc = exptext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmptokbuf); - if (rc < 0) - goto error_return; - else if (rc == 0) { - rc = VAR_MISSING_PARAMETER_IN_COMMAND; - goto error_return; - } else - p += rc; - if (data->begin != NULL) { - if (data->begin == data->end) { - free_tokenbuf(data); - move_tokenbuf(&tmptokbuf, data); - } else { - free_tokenbuf(data); - data->begin = data->end = ""; - data->buffer_size = 0; - } - } - break; - - case '+': /* Substitute parameter if data is not empty. */ - ++p; - rc = exptext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &tmptokbuf); - if (rc < 0) - goto error_return; - else if (rc == 0) { - rc = VAR_MISSING_PARAMETER_IN_COMMAND; - goto error_return; - } else - p += rc; - if (data->begin != NULL) { - if (data->begin != data->end) { - free_tokenbuf(data); - move_tokenbuf(&tmptokbuf, data); - } - } - break; - - case 's': /* Search and replace. */ - ++p; - - if (*p != '/') - return VAR_MALFORMATTED_REPLACE; - else - ++p; - - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &search); - if (rc < 0) - goto error_return; - else - p += rc; - - if (*p != '/') { - rc = VAR_MALFORMATTED_REPLACE; - goto error_return; - } else - ++p; - - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &replace); - if (rc < 0) - goto error_return; - else - p += rc; - - if (*p != '/') { - rc = VAR_MALFORMATTED_REPLACE; - goto error_return; - } else - ++p; - - rc = exptext(p, end, config); - if (rc < 0) - goto error_return; - else { - flags.begin = p; - flags.end = p + rc; - flags.buffer_size = 0; - p += rc; - } - - if (data->begin) { - rc = search_and_replace(data, &search, &replace, &flags); - if (rc < 0) - goto error_return; - } - break; - - case 'y': /* Transpose characters from class A to class B. */ - ++p; - - if (*p != '/') - return VAR_MALFORMATTED_TRANSPOSE; - else - ++p; - - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &search); - if (rc < 0) - goto error_return; - else - p += rc; - - if (*p != '/') { - rc = VAR_MALFORMATTED_TRANSPOSE; - goto error_return; - } else - ++p; - - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &replace); - if (rc < 0) - goto error_return; - else - p += rc; - - if (*p != '/') { - rc = VAR_MALFORMATTED_TRANSPOSE; - goto error_return; - } else - ++p; - - if (data->begin) { - rc = transpose(data, &search, &replace); - if (rc < 0) - goto error_return; - } - break; - - - case 'p': /* Padding. */ - ++p; - - if (*p != '/') - return VAR_MALFORMATTED_PADDING; - else - ++p; - - rc = number(p, end); - if (rc == 0) { - rc = VAR_MISSING_PADDING_WIDTH; - goto error_return; - } else { - number1.begin = p; - number1.end = p + rc; - number1.buffer_size = 0; - p += rc; - } - - if (*p != '/') { - rc = VAR_MALFORMATTED_PADDING; - goto error_return; - } else - ++p; - - rc = substext_or_variable(p, end, config, nameclass, lookup, - lookup_context, force_expand, &replace); - if (rc < 0) - goto error_return; - else - p += rc; - - if (*p != '/') { - rc = VAR_MALFORMATTED_PADDING; - goto error_return; - } else - ++p; - - if (*p != 'l' && *p != 'c' && *p != 'r') { - rc = VAR_MALFORMATTED_PADDING; - goto error_return; - } else - ++p; - - if (data->begin) { - rc = padding(data, &number1, &replace, p[-1]); - if (rc < 0) - goto error_return; - } - break; + case 'l': /* Turn data to lowercase. */ + if (data->begin) { + char *ptr; + /* If the buffer does not life in an allocated buffer, + we have to copy it before modifying the contents. */ + + if (data->buffer_size == 0) { + if (!assign_to_tokenbuf + (data, data->begin, data->end - data->begin)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } + } + for (ptr = (char *) data->begin; ptr != data->end; ++ptr) + *ptr = tolower(*ptr); + } + ++p; + break; + + case 'u': /* Turn data to uppercase. */ + if (data->begin) { + char *ptr; + if (data->buffer_size == 0) { + if (!assign_to_tokenbuf + (data, data->begin, data->end - data->begin)) { + rc = VAR_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 = number(p, end); + if (rc == 0) { + rc = VAR_MISSING_START_OFFSET; + goto error_return; + } else { + 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_INVALID_OFFSET_DELIMITER; + goto error_return; + } + + rc = number(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); + if (rc < 0) + goto error_return; + } + break; + + case '#': /* Substitute length of the string. */ + if (data->begin) { + char buf[1024]; + sprintf(buf, "%d", data->end - data->begin); + free_tokenbuf(data); + if (!assign_to_tokenbuf(data, buf, strlen(buf))) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } + } + ++p; + break; + + case '-': /* Substitute parameter if data is empty. */ + ++p; + rc = exptext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &tmptokbuf); + if (rc < 0) + goto error_return; + else if (rc == 0) { + rc = VAR_MISSING_PARAMETER_IN_COMMAND; + goto error_return; + } else + p += rc; + if (data->begin != NULL && data->begin == data->end) { + free_tokenbuf(data); + move_tokenbuf(&tmptokbuf, data); + } + break; + + case '*': /* Return "" if data is not empty, parameter otherwise. */ + ++p; + rc = exptext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &tmptokbuf); + if (rc < 0) + goto error_return; + else if (rc == 0) { + rc = VAR_MISSING_PARAMETER_IN_COMMAND; + goto error_return; + } else + p += rc; + if (data->begin != NULL) { + if (data->begin == data->end) { + free_tokenbuf(data); + move_tokenbuf(&tmptokbuf, data); + } else { + free_tokenbuf(data); + data->begin = data->end = ""; + data->buffer_size = 0; + } + } + break; + + case '+': /* Substitute parameter if data is not empty. */ + ++p; + rc = exptext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &tmptokbuf); + if (rc < 0) + goto error_return; + else if (rc == 0) { + rc = VAR_MISSING_PARAMETER_IN_COMMAND; + goto error_return; + } else + p += rc; + if (data->begin != NULL) { + if (data->begin != data->end) { + free_tokenbuf(data); + move_tokenbuf(&tmptokbuf, data); + } + } + break; + + case 's': /* Search and replace. */ + ++p; + + if (*p != '/') + return VAR_MALFORMATTED_REPLACE; + else + ++p; + + rc = substext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &search); + if (rc < 0) + goto error_return; + else + p += rc; + + if (*p != '/') { + rc = VAR_MALFORMATTED_REPLACE; + goto error_return; + } else + ++p; + + rc = substext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &replace); + if (rc < 0) + goto error_return; + else + p += rc; + + if (*p != '/') { + rc = VAR_MALFORMATTED_REPLACE; + goto error_return; + } else + ++p; + + rc = exptext(p, end, config); + if (rc < 0) + goto error_return; + else { + flags.begin = p; + flags.end = p + rc; + flags.buffer_size = 0; + p += rc; + } + + if (data->begin) { + rc = search_and_replace(data, &search, &replace, &flags); + if (rc < 0) + goto error_return; + } + break; + + case 'y': /* Transpose characters from class A to class B. */ + ++p; + + if (*p != '/') + return VAR_MALFORMATTED_TRANSPOSE; + else + ++p; + + rc = substext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &search); + if (rc < 0) + goto error_return; + else + p += rc; + + if (*p != '/') { + rc = VAR_MALFORMATTED_TRANSPOSE; + goto error_return; + } else + ++p; + + rc = substext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &replace); + if (rc < 0) + goto error_return; + else + p += rc; + + if (*p != '/') { + rc = VAR_MALFORMATTED_TRANSPOSE; + goto error_return; + } else + ++p; + + if (data->begin) { + rc = transpose(data, &search, &replace); + if (rc < 0) + goto error_return; + } + break; + + + case 'p': /* Padding. */ + ++p; + + if (*p != '/') + return VAR_MALFORMATTED_PADDING; + else + ++p; + + rc = number(p, end); + if (rc == 0) { + rc = VAR_MISSING_PADDING_WIDTH; + goto error_return; + } else { + number1.begin = p; + number1.end = p + rc; + number1.buffer_size = 0; + p += rc; + } + + if (*p != '/') { + rc = VAR_MALFORMATTED_PADDING; + goto error_return; + } else + ++p; + + rc = substext_or_variable(p, end, config, nameclass, lookup, + lookup_context, force_expand, &replace); + if (rc < 0) + goto error_return; + else + p += rc; + + if (*p != '/') { + rc = VAR_MALFORMATTED_PADDING; + goto error_return; + } else + ++p; + + if (*p != 'l' && *p != 'c' && *p != 'r') { + rc = VAR_MALFORMATTED_PADDING; + goto error_return; + } else + ++p; + + if (data->begin) { + rc = padding(data, &number1, &replace, p[-1]); + if (rc < 0) + goto error_return; + } + break; default: - return VAR_UNKNOWN_COMMAND_CHAR; + return VAR_UNKNOWN_COMMAND_CHAR; } /* Exit gracefully. */ @@ -1510,10 +1510,10 @@ } static var_rc_t input(const char *begin, const char *end, - const var_config_t * config, - const char nameclass[256], var_cb_t lookup, - void *lookup_context, int force_expand, - tokenbuf * output) + const var_config_t * config, + const char nameclass[256], var_cb_t lookup, + void *lookup_context, int force_expand, + tokenbuf * output) { int rc; tokenbuf result; @@ -1521,33 +1521,33 @@ init_tokenbuf(&result); do { - rc = text(begin, end, config->varinit, config->escape); - if (rc > 0) { - if (!append_to_tokenbuf(output, begin, rc)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } - begin += rc; - } else if (rc < 0) - goto error_return; - - rc = variable(begin, end, config, nameclass, lookup, - lookup_context, force_expand, &result); - if (rc > 0) { - if (!append_to_tokenbuf - (output, result.begin, result.end - result.begin)) { - rc = VAR_OUT_OF_MEMORY; - goto error_return; - } else - begin += rc; - } else if (rc < 0) - goto error_return; + rc = text(begin, end, config->varinit, config->escape); + if (rc > 0) { + if (!append_to_tokenbuf(output, begin, rc)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } + begin += rc; + } else if (rc < 0) + goto error_return; + + rc = variable(begin, end, config, nameclass, lookup, + lookup_context, force_expand, &result); + if (rc > 0) { + if (!append_to_tokenbuf + (output, result.begin, result.end - result.begin)) { + rc = VAR_OUT_OF_MEMORY; + goto error_return; + } else + begin += rc; + } else if (rc < 0) + goto error_return; } while (rc > 0); if (begin != end) { - rc = VAR_INPUT_ISNT_TEXT_NOR_VARIABLE; - goto error_return; + rc = VAR_INPUT_ISNT_TEXT_NOR_VARIABLE; + goto error_return; } return VAR_OK; @@ -1558,9 +1558,9 @@ } 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) + char **result, size_t * result_len, + var_cb_t lookup, void *lookup_context, + const var_config_t * config, int force_expand) { char nameclass[256]; var_rc_t rc; @@ -1569,29 +1569,29 @@ /* Expand the class description for valid variable names. */ if (config == NULL) - config = &var_config_default; + config = &var_config_default; rc = expand_character_class(config->namechars, nameclass); if (rc != VAR_OK) - return rc; + return 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] || - nameclass[(int) config->escape]) - return VAR_INVALID_CONFIGURATION; + nameclass[(int) config->startdelim] || + nameclass[(int) config->enddelim] || + nameclass[(int) config->escape]) + return VAR_INVALID_CONFIGURATION; /* Call the parser. */ output.begin = output.end = NULL; output.buffer_size = 0; rc = input(input_buf, input_buf + input_len, config, nameclass, - lookup, lookup_context, force_expand, &output); + lookup, lookup_context, force_expand, &output); if (rc != VAR_OK) { - free_tokenbuf(&output); - return rc; + free_tokenbuf(&output); + return rc; } *result = (char *) output.begin; *result_len = output.end - output.begin;