Index: ossp-pkg/var/var.c RCS File: /v/ossp/cvs/ossp-pkg/var/var.c,v rcsdiff -q -kk '-r1.7' '-r1.8' -u '/v/ossp/cvs/ossp-pkg/var/var.c,v' 2>/dev/null --- var.c 2001/11/13 14:36:55 1.7 +++ var.c 2001/11/13 14:42:57 1.8 @@ -37,212 +37,197 @@ /* The default configuration for the parser. */ -const var_config_t var_config_default = - { - '$', /* varinit */ - '{', /* startdelim */ - '}', /* enddelim */ - '\\', /* escape */ - "a-zA-Z0-9_" /* namechars */ - }; +const var_config_t var_config_default = { + '$', /* varinit */ + '{', /* startdelim */ + '}', /* enddelim */ + '\\', /* escape */ + "a-zA-Z0-9_" /* namechars */ +}; /* Routines for manipulation of tokenbufs. */ #define VAR_INITIAL_BUFFER_SIZE 64 -typedef struct - { - const char* begin; - const char* end; +typedef struct { + const char *begin; + const char *end; size_t buffer_size; - } -tokenbuf; +} tokenbuf; -static void init_tokenbuf(tokenbuf* buf) - { +static void init_tokenbuf(tokenbuf * buf) +{ buf->begin = buf->end = NULL; buf->buffer_size = 0; - } +} -static void move_tokenbuf(tokenbuf* src, tokenbuf* dst) - { +static void move_tokenbuf(tokenbuf * src, tokenbuf * dst) +{ dst->begin = src->begin; dst->end = src->end; dst->buffer_size = src->buffer_size; init_tokenbuf(src); - } +} -static int assign_to_tokenbuf(tokenbuf* buf, const char* data, size_t len) - { - 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; - } - else - return 0; - } - -static int append_to_tokenbuf(tokenbuf* output, const char* data, size_t len) - { - char* new_buffer; +static int assign_to_tokenbuf(tokenbuf * buf, const char *data, size_t len) +{ + 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; + } else + return 0; +} + +static int append_to_tokenbuf(tokenbuf * output, const char *data, + size_t len) +{ + char *new_buffer; size_t new_size; /* Is the tokenbuffer initialized at all? If not, allocate a 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 == NULL) { + 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. */ - - 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->buffer_size == 0) { + /* 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; + } + } /* 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; - } + 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; + } /* Append the data at the end of the current buffer. */ - memcpy((char*)output->end, data, len); + memcpy((char *) output->end, data, len); output->end += len; - *((char*)output->end) = '\0'; + *((char *) output->end) = '\0'; return 1; - } +} -static void free_tokenbuf(tokenbuf* buf) - { +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; - } +} -static size_t tokenbuf2int(tokenbuf* number) - { - const char* p; +static size_t tokenbuf2int(tokenbuf * number) +{ + const char *p; size_t num = 0; - for (p = number->begin; p != number->end; ++p) - { - num *= 10; - num += *p - '0'; - } - return num; + for (p = number->begin; p != number->end; ++p) { + num *= 10; + num += *p - '0'; } + return num; +} /* Routines for the expansion of quoted-pair expressions. */ static void expand_range(char a, char b, char class[256]) - { - do - { - class[(int)a] = 1; - } - while (++a <= b); +{ + do { + class[(int) a] = 1; } + while (++a <= b); +} -static var_rc_t expand_character_class(const char* desc, char class[256]) - { +static var_rc_t expand_character_class(const char *desc, char class[256]) +{ size_t i; /* 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; - } - } + 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; + } + } return VAR_OK; - } +} 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) - { +static var_rc_t expand_octal(const char **src, char **dst, const char *end) +{ 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); @@ -252,225 +237,217 @@ c += **src - '0'; - **dst = (char)c; + **dst = (char) c; ++(*dst); return VAR_OK; - } +} 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) - { +static var_rc_t expand_simple_hex(const char **src, char **dst, + 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 = (char) c; ++(*dst); return VAR_OK; - } +} -static var_rc_t expand_grouped_hex(const char** src, char** dst, const char* end) - { +static var_rc_t expand_grouped_hex(const char **src, char **dst, + const char *end) +{ var_rc_t rc; - while (*src < end && **src != '}') - { - if ((rc = expand_simple_hex(src, dst, end)) != 0) - return rc; - ++(*src); - } + while (*src < end && **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; - } +} -static var_rc_t expand_hex(const char** src, char** dst, const char* end) - { +static var_rc_t expand_hex(const char **src, char **dst, const char *end) +{ if (*src == end) - return VAR_INCOMPLETE_HEX; - if (**src == '{') - { - ++(*src); - return expand_grouped_hex(src, dst, end); - } - else - return expand_simple_hex(src, dst, end); - } - -var_rc_t var_unescape(const char* src, size_t len, char* dst, int unescape_all) - { - const char* end = src + len; + return VAR_INCOMPLETE_HEX; + if (**src == '{') { + ++(*src); + return expand_grouped_hex(src, dst, end); + } else + return expand_simple_hex(src, dst, end); +} + +var_rc_t var_unescape(const char *src, size_t len, char *dst, + int unescape_all) +{ + const char *end = src + len; var_rc_t rc; - while (src < end) - { - if (*src == '\\') - { - if (++src == end) - return VAR_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(src[1]) && isdigit(src[2])) - { - if ((rc = expand_octal(&src, &dst, end)) != 0) - return rc; - break; - } - default: - if (!unescape_all) - { - *dst++ = '\\'; - } - *dst++ = *src; - } - ++src; - } - else - *dst++ = *src++; - } + 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(src[1]) && isdigit(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; - } +} /* 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*); -static int command(const char*, const char*, const var_config_t*, - const char[256], var_cb_t, void*, int, tokenbuf*); - -static int text(const char* begin, const char* end, char varinit, 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; - } - } - return p - begin; +static int variable(const char *, const char *, const var_config_t *, + 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 *); + +static int text(const char *begin, const char *end, char varinit, + 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; + } } - -static int varname(const char* begin, const char* end, const char nameclass[256]) - { - const char* p; - for (p = begin; p != end && nameclass[(int)*p]; ++p) - ; return p - begin; - } +} -static int number(const char* begin, const char* end) - { - const char* p; - for (p = begin; p != end && isdigit(*p); ++p) - ; +static int varname(const char *begin, const char *end, + const char nameclass[256]) +{ + const char *p; + for (p = begin; p != end && nameclass[(int) *p]; ++p); return p - begin; - } +} -static int substext(const char* begin, const char* end, 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; - } - } +static int number(const char *begin, const char *end) +{ + const char *p; + for (p = begin; p != end && isdigit(*p); ++p); return p - begin; - } +} -static int exptext(const char* begin, const char* end, 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; - } - } +static int substext(const char *begin, const char *end, + 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; + } + } return p - begin; +} + +static int exptext(const char *begin, const char *end, + 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; + } } + 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 char* p = begin; - const char* data; +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 char *p = begin; + const char *data; size_t len, buffer_size; int failed = 0; int rc; @@ -486,131 +463,116 @@ /* 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; - } - } + 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; + } + } while (rc > 0); /* We must have the complete variable name now, so make sure we do. */ - if (name.begin == name.end) - { - rc = VAR_INCOMPLETE_VARIABLE_SPEC; - goto error_return; - } + if (name.begin == name.end) { + 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; - } - else - ++p; + if (p == end || (*p != config->enddelim && *p != ':')) { + rc = VAR_INCOMPLETE_VARIABLE_SPEC; + goto error_return; + } else + ++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); + rc = (*lookup) (lookup_context, name.begin, name.end - name.begin, + &data, &len, &buffer_size); if (rc < 0) - goto error_return; - else if (rc == 0) - { - /* 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; - } - } - 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] == ':') - { - /* 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; - } + goto error_return; + else if (rc == 0) { + /* 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; + } + } 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] == ':') { + /* 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; + } /* Exit gracefully. */ @@ -625,14 +587,15 @@ free_tokenbuf(&tmp); free_tokenbuf(result); return rc; - } +} -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 char* p = begin; - const char* data; +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 char *p = begin; + const char *data; size_t len, buffer_size; int rc, rc2; @@ -644,56 +607,54 @@ /* 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; - 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; - } - } + 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; + } + } /* OK, we're dealing with a complex expression here. */ - rc = expression(p, end, config, nameclass, lookup, lookup_context, force_expand, result); + rc = expression(p, end, config, nameclass, lookup, lookup_context, + 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 char* p = begin; +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 char *p = begin; tokenbuf tmp; int rc; @@ -701,37 +662,33 @@ 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; - } - } - } + 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; + } + } + } while (rc > 0); free_tokenbuf(&tmp); @@ -741,13 +698,15 @@ free_tokenbuf(&tmp); free_tokenbuf(result); return rc; - } +} -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 char* p = begin; +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 char *p = begin; tokenbuf tmp; int rc; @@ -755,37 +714,33 @@ 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; - } - } - } + 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; + } + } + } while (rc > 0); free_tokenbuf(&tmp); @@ -795,41 +750,37 @@ free_tokenbuf(&tmp); free_tokenbuf(result); return rc; - } +} -static int expand_class_description(tokenbuf* src, tokenbuf* dst) - { +static int expand_class_description(tokenbuf * src, tokenbuf * dst) +{ 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; - } - } - return VAR_OK; + 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; + } } + return VAR_OK; +} -static int transpose(tokenbuf* data, tokenbuf* search, tokenbuf* replace) - { +static int transpose(tokenbuf * data, tokenbuf * search, + tokenbuf * replace) +{ tokenbuf srcclass, dstclass; - const char* p; + const char *p; int rc; size_t i; @@ -837,43 +788,37 @@ 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; - } - if ((srcclass.end - srcclass.begin) != (dstclass.end - dstclass.begin)) - { - 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); - } - - 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; - } - } - } + if (srcclass.begin == srcclass.end) { + 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; + } + + 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); + } + + 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; + } + } + } free_tokenbuf(&srcclass); free_tokenbuf(&dstclass); @@ -885,393 +830,356 @@ free_tokenbuf(&srcclass); free_tokenbuf(&dstclass); return rc; - } +} -static int cut_out_offset(tokenbuf* data, tokenbuf* number1, tokenbuf* number2, int isrange) - { +static int cut_out_offset(tokenbuf * data, tokenbuf * number1, + tokenbuf * number2, int isrange) +{ tokenbuf res; - const char* p; + const char *p; size_t num1 = tokenbuf2int(number1); size_t num2 = tokenbuf2int(number2); /* 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 (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; + } + } free_tokenbuf(data); move_tokenbuf(&res, data); return VAR_OK; - } +} -static int expand_regex_replace(const char* data, tokenbuf* orig, regmatch_t* pmatch, tokenbuf* expanded) - { - const char* p = orig->begin; +static int expand_regex_replace(const char *data, tokenbuf * orig, + regmatch_t * pmatch, tokenbuf * expanded) +{ + const char *p = orig->begin; size_t i; 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(*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; - } - } + 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(*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) - { - const char* p; +static int search_and_replace(tokenbuf * data, tokenbuf * search, + tokenbuf * replace, tokenbuf * flags) +{ + const char *p; int case_insensitive = 0; int global = 0; int no_regex = 0; 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; - } - } - - if (no_regex) - { - 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; - } - } - } - - 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); - } + 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; + } + } + + if (no_regex) { + 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; + } + } + } + + 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); + } return VAR_OK; - } +} -static int padding(tokenbuf* data, tokenbuf* widthstr, tokenbuf* fill, char position) - { +static int padding(tokenbuf * data, tokenbuf * widthstr, tokenbuf * fill, + 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; - } - } - 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); - } - } - 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); - } - } + 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; + } + } 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); + } + } 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); + } + } 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 char* p = begin; +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 char *p = begin; tokenbuf tmptokbuf; tokenbuf search, replace, flags; tokenbuf number1, number2; @@ -1286,349 +1194,299 @@ 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; - - default: - return VAR_UNKNOWN_COMMAND_CHAR; - } + 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; + + default: + return VAR_UNKNOWN_COMMAND_CHAR; + } /* Exit gracefully. */ @@ -1649,66 +1507,61 @@ free_tokenbuf(&number1); free_tokenbuf(&number2); return rc; - } +} -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) - { +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) +{ int rc; tokenbuf result; 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; - } + 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; + } while (rc > 0); - if (begin != end) - { - rc = VAR_INPUT_ISNT_TEXT_NOR_VARIABLE; - goto error_return; - } + if (begin != end) { + rc = VAR_INPUT_ISNT_TEXT_NOR_VARIABLE; + goto error_return; + } return VAR_OK; error_return: free_tokenbuf(&result); return rc; - } +} -var_rc_t var_expand(const char* input_buf, size_t input_len, - char** result, size_t* result_len, - var_cb_t lookup, void* lookup_context, - const var_config_t* config, int force_expand) - { +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 nameclass[256]; var_rc_t rc; tokenbuf output; @@ -1716,33 +1569,32 @@ /* 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; + if (nameclass[(int) config->varinit] || + 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); - if (rc != VAR_OK) - { - free_tokenbuf(&output); - return rc; - } - *result = (char*)output.begin; + lookup, lookup_context, force_expand, &output); + if (rc != VAR_OK) { + free_tokenbuf(&output); + return rc; + } + *result = (char *) output.begin; *result_len = output.end - output.begin; return VAR_OK; - } +} Index: ossp-pkg/var/var.h RCS File: /v/ossp/cvs/ossp-pkg/var/var.h,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/var/var.h,v' 2>/dev/null --- var.h 2001/11/13 14:36:55 1.4 +++ var.h 2001/11/13 14:42:57 1.5 @@ -34,46 +34,44 @@ /* Error codes returned by the varexp library. */ -typedef enum - { - VAR_CALLBACK_ERROR = -64, - VAR_SUBMATCH_OUT_OF_RANGE = -34, +typedef enum { + VAR_CALLBACK_ERROR = -64, + VAR_SUBMATCH_OUT_OF_RANGE = -34, VAR_UNKNOWN_QUOTED_PAIR_IN_REPLACE = -33, - VAR_EMPTY_PADDING_FILL_STRING = -32, - VAR_MISSING_PADDING_WIDTH = -31, - VAR_MALFORMATTED_PADDING = -30, + VAR_EMPTY_PADDING_FILL_STRING = -32, + VAR_MISSING_PADDING_WIDTH = -31, + VAR_MALFORMATTED_PADDING = -30, VAR_INCORRECT_TRANSPOSE_CLASS_SPEC = -29, - VAR_EMPTY_TRANSPOSE_CLASS = -28, - VAR_TRANSPOSE_CLASSES_MISMATCH = -27, - VAR_MALFORMATTED_TRANSPOSE = -26, - VAR_OFFSET_LOGIC_ERROR = -25, - VAR_OFFSET_OUT_OF_BOUNDS = -24, - VAR_RANGE_OUT_OF_BOUNDS = -23, - VAR_INVALID_OFFSET_DELIMITER = -22, - VAR_MISSING_START_OFFSET = -21, - VAR_EMPTY_SEARCH_STRING = -20, - VAR_MISSING_PARAMETER_IN_COMMAND = -19, - VAR_INVALID_REGEX_IN_REPLACE = -18, - VAR_UNKNOWN_REPLACE_FLAG = -17, - VAR_MALFORMATTED_REPLACE = -16, - VAR_UNKNOWN_COMMAND_CHAR = -14, - VAR_INPUT_ISNT_TEXT_NOR_VARIABLE = -13, - VAR_UNDEFINED_VARIABLE = -12, - VAR_INCOMPLETE_VARIABLE_SPEC = -11, - VAR_OUT_OF_MEMORY = -10, - VAR_INVALID_CONFIGURATION = -9, - VAR_INCORRECT_CLASS_SPEC = -8, - VAR_INCOMPLETE_GROUPED_HEX = -7, - VAR_INCOMPLETE_OCTAL = -6, - VAR_INVALID_OCTAL = -5, - VAR_OCTAL_TOO_LARGE = -4, - VAR_INVALID_HEX = -3, - VAR_INCOMPLETE_HEX = -2, - VAR_INCOMPLETE_NAMED_CHARACTER = -1, - VAR_INCOMPLETE_QUOTED_PAIR = -1, - VAR_OK = 0 - } -var_rc_t; + VAR_EMPTY_TRANSPOSE_CLASS = -28, + VAR_TRANSPOSE_CLASSES_MISMATCH = -27, + VAR_MALFORMATTED_TRANSPOSE = -26, + VAR_OFFSET_LOGIC_ERROR = -25, + VAR_OFFSET_OUT_OF_BOUNDS = -24, + VAR_RANGE_OUT_OF_BOUNDS = -23, + VAR_INVALID_OFFSET_DELIMITER = -22, + VAR_MISSING_START_OFFSET = -21, + VAR_EMPTY_SEARCH_STRING = -20, + VAR_MISSING_PARAMETER_IN_COMMAND = -19, + VAR_INVALID_REGEX_IN_REPLACE = -18, + VAR_UNKNOWN_REPLACE_FLAG = -17, + VAR_MALFORMATTED_REPLACE = -16, + VAR_UNKNOWN_COMMAND_CHAR = -14, + VAR_INPUT_ISNT_TEXT_NOR_VARIABLE = -13, + VAR_UNDEFINED_VARIABLE = -12, + VAR_INCOMPLETE_VARIABLE_SPEC = -11, + VAR_OUT_OF_MEMORY = -10, + VAR_INVALID_CONFIGURATION = -9, + VAR_INCORRECT_CLASS_SPEC = -8, + VAR_INCOMPLETE_GROUPED_HEX = -7, + VAR_INCOMPLETE_OCTAL = -6, + VAR_INVALID_OCTAL = -5, + VAR_OCTAL_TOO_LARGE = -4, + VAR_INVALID_HEX = -3, + VAR_INCOMPLETE_HEX = -2, + VAR_INCOMPLETE_NAMED_CHARACTER = -1, + VAR_INCOMPLETE_QUOTED_PAIR = -1, + VAR_OK = 0 +} var_rc_t; /* Expand the following named characters to their binary @@ -89,7 +87,8 @@ Any other character quoted by a backslash is copied verbatim. */ -var_rc_t var_unescape(const char* src, size_t len, char* dst, int unescape_all); +var_rc_t var_unescape(const char *src, size_t len, char *dst, + int unescape_all); /* The callback will be called by variable_expand(), providing the @@ -115,9 +114,10 @@ <0 - error */ -typedef int (*var_cb_t)(void* context, - const char* varname, size_t name_len, - const char** data, size_t* data_len, size_t* buffer_size); +typedef int (*var_cb_t) (void *context, + const char *varname, size_t name_len, + const char **data, size_t * data_len, + size_t * buffer_size); /* This structure configures the parser's specials. I think, the fields @@ -131,15 +131,13 @@ The comments after each field show the default configuration. */ -typedef struct - { - char varinit; /* '$' */ - char startdelim; /* '{' */ - char enddelim; /* '}' */ - char escape; /* '\' */ - char* namechars; /* 'a-zA-Z0-9_' */ - } -var_config_t; +typedef struct { + char varinit; /* '$' */ + char startdelim; /* '{' */ + char enddelim; /* '}' */ + char escape; /* '\' */ + char *namechars; /* 'a-zA-Z0-9_' */ +} var_config_t; extern const var_config_t var_config_default; /* @@ -151,9 +149,9 @@ by the caller. */ -var_rc_t var_expand(const char* input, 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); +var_rc_t var_expand(const char *input, 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); -#endif /* !defined(LIB_OSSP_VAR_H) */ +#endif /* !defined(LIB_OSSP_VAR_H) */ Index: ossp-pkg/var/var_test.c RCS File: /v/ossp/cvs/ossp-pkg/var/var_test.c,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/var/var_test.c,v' 2>/dev/null --- var_test.c 2001/11/13 14:36:55 1.6 +++ var_test.c 2001/11/13 14:42:57 1.7 @@ -3,141 +3,142 @@ #include #include "var.h" -static int env_lookup(void* context, - const char* varname, size_t name_len, - const char** data, size_t* data_len, size_t* buffer_size) - { +static int env_lookup(void *context, + const char *varname, size_t name_len, + const char **data, size_t * data_len, + size_t * buffer_size) +{ char tmp[256]; - if (name_len > sizeof(tmp)-1) - { - /* Callback can't expand variable names longer than - sizeof(tmp) characters. */ + if (name_len > sizeof(tmp) - 1) { + /* Callback can't expand variable names longer than + sizeof(tmp) characters. */ - return VAR_CALLBACK_ERROR; - } + return VAR_CALLBACK_ERROR; + } memcpy(tmp, varname, name_len); tmp[name_len] = '\0'; *data = getenv(tmp); if (*data == NULL) - return 0; + return 0; *data_len = strlen(*data); *buffer_size = 0; return 1; - } +} -struct test_case - { - const char* input; - const char* expected; +struct test_case { + const char *input; + const char *expected; +}; + +int main(int argc, char **argv) +{ + const struct test_case tests[] = { + {"$HOME", "/home/regression-tests"}, + {"${FOO}", "os"}, + {"${BAR}", "type"}, + {"${${FOO:u}${BAR:u}:l:u}", "REGRESSION-OS"}, + {"${UNDEFINED}", "${UNDEFINED}"}, + {"${OSTYPE:#}", "13"}, + {"${EMPTY:-test${FOO}test}", "testostest"}, + {"${EMPTY:-test${FOO:u}test}", "testOStest"}, + {"${TERM:-test${FOO}test}", "regression-term"}, + {"${EMPTY:+FOO}", ""}, + {"${HOME:+test${FOO}test}", "testostest"}, + {"${HOME:+${OS${BAR:u}}}", "regression-os"}, + {"${HOME:+OS${UNDEFINED:u}}", "OS${UNDEFINED:u}"}, + {"${UNDEFINED:+OS${BAR:u}}", "${UNDEFINED:+OS${BAR:u}}"}, + {"${HOME:*heinz}", ""}, + {"${EMPTY:*claus}", "claus"}, + {"${TERM}", "regression-term"}, + {"${HOME:s/reg/bla/}", "/home/blaression-tests"}, + {"${HOME:s/e/bla/}", "/hombla/regression-tests"}, + {"${HOME:s/e/bla/g}", "/hombla/rblagrblassion-tblasts"}, + {"${HOME:s/\\//_/g}", "_home_regression-tests"}, + {"${HOME:s/[eso]/_/g}", "/h_m_/r_gr___i_n-t__t_"}, + {"${HOME:s/[esO]/_/g}", "/hom_/r_gr___ion-t__t_"}, + {"${HOME:s/[esO]/_/gi}", "/h_m_/r_gr___i_n-t__t_"}, + {"${OSTYPE:s/^[re]/_/g}", "_egression-os"}, + {"${EMPTY:s/^[re]/_/g}", ""}, + {"${HOME:s/.*/heinz/}", "heinz"}, + {"${HOME:s/e/bla/t}", "/hombla/regression-tests"}, + {"${HOME:s/E/bla/t}", "/home/regression-tests"}, + {"${HOME:s/E/bla/ti}", "/hombla/regression-tests"}, + {"${HOME:s/E/bla/tig}", "/hombla/rblagrblassion-tblasts"}, + {"${HOME:o1-5}", "home/"}, + {"${HOME:o1,5}", "home"}, + {"${HOME:o5,}", "/regression-tests"}, + {"${HOME:o5-}", "/regression-tests"}, + {"${HOME:o7,13}", "egress"}, + {"${HOME:y/a-z/A-YZ/}", "/HOME/REGRESSION-TESTS"}, + {"${HOME:y/e-g/a-c/}", "/homa/racrassion-tasts"}, + {"${FOO:p/15/../l}", "os............."}, + {"${FOO:p/15/12345/l}", "os1234512345123"}, + {"${FOO:p/15/../r}", ".............os"}, + {"${FOO:p/15/12345/r}", "1234512345123os"}, + {"${FOO:p/15/../c}", "......os......."}, + {"${FOO:p/15/12345/c}", "123451os1234512"}, + {"${FOO:s/os/\\x{4F}\\123/g}", "OS"}, + {"${FOO:s/os/\\1\\x4F\\123/t}", "\\1OS"}, + {"${HOME:s/g(res)s/x\\1x/g}", "/home/rexresxion-tests"}, + {"${HOME:s/(s+)/_\\1_/g}", "/home/regre_ss_ion-te_s_t_s_"}, + {"${HOME:s/\\x65/\\x45/g}", "/homE/rEgrEssion-tEsts"}, + {"${HOME:s/(s*)/x\\1X/g}", + "xXxXxXxXxXxXxXxXxXxXxXxssXxXxXxXxXxXxXxsXxXxsX"}, + {"${HOME:s/./\\\\/g}", + "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"} }; - -int main(int argc, char** argv) - { - const struct test_case tests[] = - { - { "$HOME", "/home/regression-tests" }, - { "${FOO}", "os" }, - { "${BAR}", "type" }, - { "${${FOO:u}${BAR:u}:l:u}", "REGRESSION-OS" }, - { "${UNDEFINED}", "${UNDEFINED}" }, - { "${OSTYPE:#}", "13" }, - { "${EMPTY:-test${FOO}test}", "testostest" }, - { "${EMPTY:-test${FOO:u}test}", "testOStest" }, - { "${TERM:-test${FOO}test}", "regression-term" }, - { "${EMPTY:+FOO}", "" }, - { "${HOME:+test${FOO}test}", "testostest" }, - { "${HOME:+${OS${BAR:u}}}", "regression-os" }, - { "${HOME:+OS${UNDEFINED:u}}", "OS${UNDEFINED:u}" }, - { "${UNDEFINED:+OS${BAR:u}}", "${UNDEFINED:+OS${BAR:u}}" }, - { "${HOME:*heinz}", "" }, - { "${EMPTY:*claus}", "claus" }, - { "${TERM}", "regression-term" }, - { "${HOME:s/reg/bla/}", "/home/blaression-tests" }, - { "${HOME:s/e/bla/}", "/hombla/regression-tests" }, - { "${HOME:s/e/bla/g}", "/hombla/rblagrblassion-tblasts" }, - { "${HOME:s/\\//_/g}", "_home_regression-tests" }, - { "${HOME:s/[eso]/_/g}", "/h_m_/r_gr___i_n-t__t_" }, - { "${HOME:s/[esO]/_/g}", "/hom_/r_gr___ion-t__t_" }, - { "${HOME:s/[esO]/_/gi}", "/h_m_/r_gr___i_n-t__t_" }, - { "${OSTYPE:s/^[re]/_/g}", "_egression-os" }, - { "${EMPTY:s/^[re]/_/g}", "" }, - { "${HOME:s/.*/heinz/}", "heinz" }, - { "${HOME:s/e/bla/t}", "/hombla/regression-tests" }, - { "${HOME:s/E/bla/t}", "/home/regression-tests" }, - { "${HOME:s/E/bla/ti}", "/hombla/regression-tests" }, - { "${HOME:s/E/bla/tig}", "/hombla/rblagrblassion-tblasts" }, - { "${HOME:o1-5}", "home/" }, - { "${HOME:o1,5}", "home" }, - { "${HOME:o5,}", "/regression-tests" }, - { "${HOME:o5-}", "/regression-tests" }, - { "${HOME:o7,13}", "egress" }, - { "${HOME:y/a-z/A-YZ/}", "/HOME/REGRESSION-TESTS" }, - { "${HOME:y/e-g/a-c/}", "/homa/racrassion-tasts" }, - { "${FOO:p/15/../l}", "os............." }, - { "${FOO:p/15/12345/l}", "os1234512345123" }, - { "${FOO:p/15/../r}", ".............os" }, - { "${FOO:p/15/12345/r}", "1234512345123os" }, - { "${FOO:p/15/../c}", "......os......." }, - { "${FOO:p/15/12345/c}", "123451os1234512" }, - { "${FOO:s/os/\\x{4F}\\123/g}", "OS" }, - { "${FOO:s/os/\\1\\x4F\\123/t}", "\\1OS" }, - { "${HOME:s/g(res)s/x\\1x/g}", "/home/rexresxion-tests" }, - { "${HOME:s/(s+)/_\\1_/g}", "/home/regre_ss_ion-te_s_t_s_" }, - { "${HOME:s/\\x65/\\x45/g}", "/homE/rEgrEssion-tEsts" }, - { "${HOME:s/(s*)/x\\1X/g}", "xXxXxXxXxXxXxXxXxXxXxXxssXxXxXxXxXxXxXxsXxXxsX" }, - { "${HOME:s/./\\\\/g}", "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" } - }; - char* tmp; - size_t tmp_len; + char *tmp; + size_t tmp_len; var_rc_t rc; - size_t i; - char buffer[1024]; + size_t i; + char buffer[1024]; if (setenv("HOME", "/home/regression-tests", 1) != 0 || - setenv("OSTYPE", "regression-os", 1) != 0 || - setenv("TERM", "regression-term", 1) != 0 || - setenv("FOO", "os", 1) != 0 || - setenv("BAR", "type", 1) != 0 || - setenv("EMPTY", "", 1) != 0) - { - printf("Failed to set the environment: %s.\n", strerror(errno)); - return 1; - } + setenv("OSTYPE", "regression-os", 1) != 0 || + setenv("TERM", "regression-term", 1) != 0 || + setenv("FOO", "os", 1) != 0 || + setenv("BAR", "type", 1) != 0 || setenv("EMPTY", "", 1) != 0) { + printf("Failed to set the environment: %s.\n", strerror(errno)); + return 1; + } unsetenv("UNDEFINED"); - for (i = 0; i < sizeof(tests) / sizeof(struct test_case); ++i) - { + for (i = 0; i < sizeof(tests) / sizeof(struct test_case); ++i) { #ifdef DEBUG - printf("Test case #%02d: Original input is '%s'.\n", i, tests[i].input); + printf("Test case #%02d: Original input is '%s'.\n", i, + tests[i].input); #endif - rc = var_unescape(tests[i].input, strlen(tests[i].input), buffer, 0); - if (rc != VAR_OK) - { - printf("Test case #%d: First var_unescape() failed with return code %d.\n", i, rc); - return 1; - } + rc = var_unescape(tests[i].input, strlen(tests[i].input), buffer, + 0); + if (rc != VAR_OK) { + printf + ("Test case #%d: First var_unescape() failed with return code %d.\n", + i, rc); + return 1; + } #ifdef DEBUG - printf("Test case #%02d: Unescaped input is '%s'.\n", i, buffer); + printf("Test case #%02d: Unescaped input is '%s'.\n", i, buffer); #endif - rc = var_expand(buffer, strlen(buffer), &tmp, &tmp_len, - &env_lookup, NULL, - NULL, 0); - if (rc != VAR_OK) - { - printf("Test case #%d: var_expand() failed with return code %d.\n", i, rc); - return 1; - } + rc = var_expand(buffer, strlen(buffer), &tmp, &tmp_len, + &env_lookup, NULL, NULL, 0); + if (rc != VAR_OK) { + printf + ("Test case #%d: var_expand() failed with return code %d.\n", + i, rc); + return 1; + } #ifdef DEBUG - printf("Test case #%02d: Expanded output is '%s'.\n", i, tmp); + printf("Test case #%02d: Expanded output is '%s'.\n", i, tmp); #endif - if (tmp_len != strlen(tests[i].expected) || tmp == NULL || memcmp(tests[i].expected, tmp, tmp_len) != 0) - { - printf("Test case #%d: Expected result '%s' but got '%s'.\n", i, tests[i].expected, tmp); - return 1; - } - free(tmp); - } + if (tmp_len != strlen(tests[i].expected) || tmp == NULL + || memcmp(tests[i].expected, tmp, tmp_len) != 0) { + printf("Test case #%d: Expected result '%s' but got '%s'.\n", + i, tests[i].expected, tmp); + return 1; + } + free(tmp); + } return 0; - } +}