Index: ossp-pkg/var/var.c RCS File: /v/ossp/cvs/ossp-pkg/var/var.c,v rcsdiff -q -kk '-r1.74' '-r1.75' -u '/v/ossp/cvs/ossp-pkg/var/var.c,v' 2>/dev/null --- var.c 2002/03/02 12:29:05 1.74 +++ var.c 2002/03/04 11:37:34 1.75 @@ -213,15 +213,15 @@ output->buffer_size = TOKENBUF_INITIAL_BUFSIZE; } - /* Does the token contain text, but no buffer has been allocated yet? */ + /* 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 + /* 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 + /* ok, so copy the contents of output into an allocated buffer so that we can append that way. */ if ((tmp = malloc(output->end - output->begin + len + 1)) == NULL) return 0; @@ -232,7 +232,7 @@ output->buffer_size += len + 1; } - /* Does the token fit into the current buffer? If not, realloc a + /* 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; @@ -246,7 +246,7 @@ output->buffer_size = new_size; } - /* Append the data at the end of the current buffer. */ + /* append the data at the end of the current buffer. */ memcpy((char *)output->end, data, len); output->end += len; *((char *)output->end) = NUL; @@ -271,28 +271,15 @@ return; } -static size_t -tokenbuf_toint( - tokenbuf_t *number) -{ - const char *p; - size_t num; - - num = 0; - for (p = number->begin; p != number->end; ++p) { - num *= 10; - num += *p - '0'; - } - return num; -} - /* ** -** ==== ESCAPE SEQUENCE FUNCTIONS ==== +** ==== CHARACTER CLASS EXPANSION ==== ** */ -static void expand_range(char a, char b, char_class_t class) +static void +expand_range( + char a, char b, char_class_t class) { do { class[(int)a] = 1; @@ -301,18 +288,17 @@ return; } -static var_rc_t expand_character_class(const char *desc, char_class_t class) +static var_rc_t +expand_character_class( + const char *desc, char_class_t class) { size_t i; - /* Clear the class array. */ - + /* clear the class array. */ for (i = 0; i < 256; ++i) class[i] = 0; - /* Walk through the class description and set the appropriate - entries in the array. */ - + /* walk through class description and set appropriate entries in array */ while (*desc != NUL) { if (desc[1] == '-' && desc[2] != NUL) { if (desc[0] > desc[2]) @@ -321,14 +307,21 @@ desc += 3; } else { class[(int) *desc] = 1; - ++desc; + desc++; } } - return VAR_OK; } -static int isoct(char c) +/* +** +** ==== ESCAPE SEQUENCE EXPANSION FUNCTIONS ==== +** +*/ + +static int +expand_isoct( + char c) { if (c >= '0' && c <= '7') return 1; @@ -336,33 +329,39 @@ 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_ERR_INCOMPLETE_OCTAL; - if (!isoct(**src) || !isoct((*src)[1]) || !isoct((*src)[2])) + if ( !expand_isoct(**src) + || !expand_isoct((*src)[1]) + || !expand_isoct((*src)[2])) return VAR_ERR_INVALID_OCTAL; c = **src - '0'; if (c > 3) return VAR_ERR_OCTAL_TOO_LARGE; c *= 8; - ++(*src); + (*src)++; c += **src - '0'; c *= 8; - ++(*src); + (*src)++; c += **src - '0'; **dst = (char) c; - ++(*dst); + (*dst)++; return VAR_OK; } -static int ishex(char c) +static int +expand_ishex( + char c) { if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) @@ -371,14 +370,16 @@ 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_ERR_INCOMPLETE_HEX; - if (!ishex(**src) || !ishex((*src)[1])) + if ( !expand_ishex(**src) + || !expand_ishex((*src)[1])) return VAR_ERR_INVALID_HEX; if (**src >= '0' && **src <= '9') @@ -389,7 +390,7 @@ c = **src - 'A' + 10; c = c << 4; - ++(*src); + (*src)++; if (**src >= '0' && **src <= '9') c += **src - '0'; @@ -399,19 +400,20 @@ c += **src - 'A' + 10; **dst = (char) c; - ++(*dst); + (*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)) != VAR_OK) return rc; - ++(*src); + (*src)++; } if (*src == end) return VAR_ERR_INCOMPLETE_GROUPED_HEX; @@ -419,12 +421,14 @@ 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_ERR_INCOMPLETE_HEX; if (**src == '{') { - ++(*src); + (*src)++; return expand_grouped_hex(src, dst, end); } else return expand_simple_hex(src, dst, end); @@ -440,20 +444,6 @@ static int parse_variable(var_t *var, var_parse_t *ctx, const char *begin, const char *end, tokenbuf_t *result); static int parse_numexp (var_t *var, var_parse_t *ctx, const char *begin, const char *end, int *result, int *failed); -/* parse number */ -static int -parse_number( - var_t *var, var_parse_t *ctx, - const char *begin, const char *end) -{ - const char *p; - - /* parse as long as digits are found */ - for (p = begin; p != end && isdigit((int)(*p)); p++) - ; - return (p - begin); -} - /* parse substitution text */ static int parse_substext( @@ -473,7 +463,7 @@ return (p - begin); } -/* parse expression? XXX text */ +/* parse expression text */ static int parse_exptext( var_t *var, var_parse_t *ctx, @@ -495,6 +485,7 @@ return (p - begin); } +/* parse expression or variable */ static int parse_exptext_or_variable( var_t *var, var_parse_t *ctx, @@ -507,11 +498,10 @@ tokenbuf_init(result); tokenbuf_init(&tmp); - if (begin == end) return 0; - do { + /* try to parse expression text */ rc = parse_exptext(var, ctx, p, end); if (rc < 0) goto error_return; @@ -523,6 +513,7 @@ p += rc; } + /* try to parse variable construct */ rc = parse_variable(var, ctx, p, end, &tmp); if (rc < 0) goto error_return; @@ -537,14 +528,15 @@ } while (rc > 0); tokenbuf_free(&tmp); - return p - begin; + return (p - begin); - error_return: + error_return: tokenbuf_free(&tmp); tokenbuf_free(result); return rc; } +/* parse substitution text or variable */ static int parse_substext_or_variable( var_t *var, var_parse_t *ctx, @@ -557,11 +549,10 @@ tokenbuf_init(result); tokenbuf_init(&tmp); - if (begin == end) return 0; - do { + /* try to parse substitution text */ rc = parse_substext(var, ctx, p, end); if (rc < 0) goto error_return; @@ -573,6 +564,7 @@ p += rc; } + /* try to parse substiution text */ rc = parse_variable(var, ctx, p, end, &tmp); if (rc < 0) goto error_return; @@ -587,20 +579,24 @@ } while (rc > 0); tokenbuf_free(&tmp); - return p - begin; + return (p - begin); - error_return: + error_return: tokenbuf_free(&tmp); tokenbuf_free(result); return rc; } +/* parse class description */ static int -parse_class_description(tokenbuf_t *src, tokenbuf_t *dst) +parse_class_description( + var_t *var, var_parse_t *ctx, + tokenbuf_t *src, tokenbuf_t *dst) { unsigned char c, d; - const char *p = src->begin; + const char *p; + p = src->begin; while (p != src->end) { if ((src->end - p) >= 3 && p[1] == '-') { if (*p > p[2]) @@ -619,120 +615,19 @@ return VAR_OK; } -static int -op_transpose( - tokenbuf_t *data, - tokenbuf_t *search, - tokenbuf_t *replace) -{ - tokenbuf_t srcclass, dstclass; - const char *p; - int rc; - size_t i; - - tokenbuf_init(&srcclass); - tokenbuf_init(&dstclass); - - if ((rc = parse_class_description(search, &srcclass)) != VAR_OK) - goto error_return; - if ((rc = parse_class_description(replace, &dstclass)) != VAR_OK) - goto error_return; - - if (srcclass.begin == srcclass.end) { - rc = VAR_ERR_EMPTY_TRANSPOSE_CLASS; - goto error_return; - } - if ((srcclass.end - srcclass.begin) != (dstclass.end - dstclass.begin)) { - rc = VAR_ERR_TRANSPOSE_CLASSES_MISMATCH; - goto error_return; - } - - if (data->buffer_size == 0) { - tokenbuf_t tmp; - if (!tokenbuf_assign(&tmp, data->begin, data->end - data->begin)) { - rc = VAR_ERR_OUT_OF_MEMORY; - goto error_return; - } - tokenbuf_move(&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; - } - } - } - - tokenbuf_free(&srcclass); - tokenbuf_free(&dstclass); - return VAR_OK; - - error_return: - tokenbuf_free(search); - tokenbuf_free(replace); - tokenbuf_free(&srcclass); - tokenbuf_free(&dstclass); - return rc; -} - -static int -op_cut_out_offset( - tokenbuf_t *data, - tokenbuf_t *number1, - tokenbuf_t *number2, - int isrange) -{ - tokenbuf_t res; - const char *p; - size_t num1; - size_t num2; - - num1 = tokenbuf_toint(number1); - num2 = tokenbuf_toint(number2); - - /* Determine begin of result string. */ - if ((data->end - data->begin) < num1) - return VAR_ERR_OFFSET_OUT_OF_BOUNDS; - else - p = data->begin + num1; - - /* If num2 is zero, we copy the rest from there. */ - if (num2 == 0) { - if (!tokenbuf_assign(&res, p, data->end - p)) - return VAR_ERR_OUT_OF_MEMORY; - } else { - /* OK, then use num2. */ - if (isrange) { - if ((p + num2) > data->end) - return VAR_ERR_RANGE_OUT_OF_BOUNDS; - if (!tokenbuf_assign(&res, p, num2)) - return VAR_ERR_OUT_OF_MEMORY; - } else { - if (num2 < num1) - return VAR_ERR_OFFSET_LOGIC; - if ((data->begin + num2) > data->end) - return VAR_ERR_RANGE_OUT_OF_BOUNDS; - if (!tokenbuf_assign(&res, p, num2 - num1 + 1)) - return VAR_ERR_OUT_OF_MEMORY; - } - } - tokenbuf_free(data); - tokenbuf_move(&res, data); - return VAR_OK; -} - +/* parse regex replace part */ static int parse_regex_replace( + var_t *var, var_parse_t *ctx, const char *data, tokenbuf_t *orig, regmatch_t *pmatch, tokenbuf_t *expanded) { - const char *p = orig->begin; + const char *p; size_t i; + p = orig->begin; tokenbuf_init(expanded); while (p != orig->end) { @@ -761,7 +656,7 @@ return VAR_ERR_SUBMATCH_OUT_OF_RANGE; } if (!tokenbuf_append(expanded, data + pmatch[i].rm_so, - pmatch[i].rm_eo - pmatch[i].rm_so)) { + pmatch[i].rm_eo - pmatch[i].rm_so)) { tokenbuf_free(expanded); return VAR_ERR_OUT_OF_MEMORY; } @@ -777,8 +672,65 @@ return VAR_OK; } +/* operation: transpose */ +static int +op_transpose( + var_t *var, var_parse_t *ctx, + tokenbuf_t *data, + tokenbuf_t *search, + tokenbuf_t *replace) +{ + tokenbuf_t srcclass, dstclass; + const char *p; + int rc; + size_t i; + + tokenbuf_init(&srcclass); + tokenbuf_init(&dstclass); + if ((rc = parse_class_description(var, ctx, search, &srcclass)) != VAR_OK) + goto error_return; + if ((rc = parse_class_description(var, ctx, replace, &dstclass)) != VAR_OK) + goto error_return; + if (srcclass.begin == srcclass.end) { + rc = VAR_ERR_EMPTY_TRANSPOSE_CLASS; + goto error_return; + } + if ((srcclass.end - srcclass.begin) != (dstclass.end - dstclass.begin)) { + rc = VAR_ERR_TRANSPOSE_CLASSES_MISMATCH; + goto error_return; + } + if (data->buffer_size == 0) { + tokenbuf_t tmp; + if (!tokenbuf_assign(&tmp, data->begin, data->end - data->begin)) { + rc = VAR_ERR_OUT_OF_MEMORY; + goto error_return; + } + tokenbuf_move(&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; + } + } + } + tokenbuf_free(&srcclass); + tokenbuf_free(&dstclass); + return VAR_OK; + + error_return: + tokenbuf_free(search); + tokenbuf_free(replace); + tokenbuf_free(&srcclass); + tokenbuf_free(&dstclass); + return rc; +} + +/* operation: search & replace */ static int op_search_and_replace( + var_t *var, var_parse_t *ctx, tokenbuf_t *data, tokenbuf_t *search, tokenbuf_t *replace, @@ -815,11 +767,9 @@ for (p = data->begin; p != data->end;) { if (case_insensitive) - rc = strncasecmp(p, search->begin, - search->end - search->begin); + rc = strncasecmp(p, search->begin, search->end - search->begin); else - rc = strncmp(p, search->begin, - search->end - search->begin); + rc = strncmp(p, search->begin, search->end - search->begin); if (rc != 0) { /* no match, copy character */ if (!tokenbuf_append(&tmp, p, 1)) { @@ -828,8 +778,7 @@ } ++p; } else { - tokenbuf_append(&tmp, replace->begin, - replace->end - replace->begin); + tokenbuf_append(&tmp, replace->begin, replace->end - replace->begin); p += search->end - search->begin; if (!global) { if (!tokenbuf_append(&tmp, p, data->end - p)) { @@ -861,7 +810,7 @@ } /* Compile the pattern. */ - rc = regcomp(&preg, tmp.begin, REG_NEWLINE | REG_EXTENDED|((case_insensitive)?REG_ICASE:0)); + rc = regcomp(&preg, tmp.begin, REG_NEWLINE|REG_EXTENDED|((case_insensitive)?REG_ICASE:0)); tokenbuf_free(&tmp); if (rc != 0) { tokenbuf_free(&mydata); @@ -879,7 +828,7 @@ tokenbuf_append(&tmp, p, mydata.end - p); break; } else { - rc = parse_regex_replace(p, replace, pmatch, &myreplace); + rc = parse_regex_replace(var, ctx, p, replace, pmatch, &myreplace); if (rc != VAR_OK) { regfree(&preg); tokenbuf_free(&tmp); @@ -887,8 +836,7 @@ return rc; } if (!tokenbuf_append(&tmp, p, pmatch[0].rm_so) || - !tokenbuf_append(&tmp, myreplace.begin, - myreplace.end - myreplace.begin)) { + !tokenbuf_append(&tmp, myreplace.begin, myreplace.end - myreplace.begin)) { regfree(&preg); tokenbuf_free(&tmp); tokenbuf_free(&mydata); @@ -921,7 +869,6 @@ } } } - regfree(&preg); tokenbuf_free(data); tokenbuf_move(&tmp, data); @@ -931,53 +878,90 @@ return VAR_OK; } +/* operation: offset substring */ +static int +op_offset( + var_t *var, var_parse_t *ctx, + tokenbuf_t *data, + int num1, + int num2, + int isrange) +{ + tokenbuf_t res; + const char *p; + + /* determine begin of result string */ + if ((data->end - data->begin) < num1) + return VAR_ERR_OFFSET_OUT_OF_BOUNDS; + p = data->begin + num1; + + /* if num2 is zero, we copy the rest from there. */ + if (num2 == 0) { + if (!tokenbuf_assign(&res, p, data->end - p)) + return VAR_ERR_OUT_OF_MEMORY; + } else { + /* ok, then use num2. */ + if (isrange) { + if ((p + num2) > data->end) + return VAR_ERR_RANGE_OUT_OF_BOUNDS; + if (!tokenbuf_assign(&res, p, num2)) + return VAR_ERR_OUT_OF_MEMORY; + } else { + if (num2 < num1) + return VAR_ERR_OFFSET_LOGIC; + if ((data->begin + num2) > data->end) + return VAR_ERR_RANGE_OUT_OF_BOUNDS; + if (!tokenbuf_assign(&res, p, num2 - num1 + 1)) + return VAR_ERR_OUT_OF_MEMORY; + } + } + tokenbuf_free(data); + tokenbuf_move(&res, data); + return VAR_OK; +} + /* operation: padding */ static int op_padding( + var_t *var, var_parse_t *ctx, tokenbuf_t *data, - tokenbuf_t *widthstr, + int width, tokenbuf_t *fill, char position) { tokenbuf_t result; - size_t width; int i; - width = tokenbuf_toint(widthstr); if (fill->begin == fill->end) return VAR_ERR_EMPTY_PADDING_FILL_STRING; - tokenbuf_init(&result); - if (position == 'l') { + /* left padding */ i = width - (data->end - data->begin); if (i > 0) { i = i / (fill->end - fill->begin); while (i > 0) { - if (!tokenbuf_append - (data, fill->begin, fill->end - fill->begin)) + if (!tokenbuf_append(data, fill->begin, fill->end - fill->begin)) return VAR_ERR_OUT_OF_MEMORY; i--; } - i = (width - (data->end - data->begin)) - % (fill->end - fill->begin); + i = (width - (data->end - data->begin)) % (fill->end - fill->begin); if (!tokenbuf_append(data, fill->begin, i)) return VAR_ERR_OUT_OF_MEMORY; } } else if (position == 'r') { + /* right padding */ i = width - (data->end - data->begin); if (i > 0) { i = i / (fill->end - fill->begin); while (i > 0) { - if (!tokenbuf_append - (&result, fill->begin, fill->end - fill->begin)) { + if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } i--; } - i = (width - (data->end - data->begin)) - % (fill->end - fill->begin); + i = (width - (data->end - data->begin)) % (fill->end - fill->begin); if (!tokenbuf_append(&result, fill->begin, i)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; @@ -986,14 +970,15 @@ tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } - + /* move string from temporary buffer to data buffer */ tokenbuf_free(data); tokenbuf_move(&result, data); } } else if (position == 'c') { + /* centered padding */ i = (width - (data->end - data->begin)) / 2; if (i > 0) { - /* Create the prefix. */ + /* create the prefix */ i = i / (fill->end - fill->begin); while (i > 0) { if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) { @@ -1008,19 +993,16 @@ tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } - - /* Append the actual data string. */ + /* append the actual data string */ if (!tokenbuf_append(&result, data->begin, data->end - data->begin)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } - - /* Append the suffix. */ + /* append the suffix */ i = width - (result.end - result.begin); i = i / (fill->end - fill->begin); while (i > 0) { - if (!tokenbuf_append - (&result, fill->begin, fill->end - fill->begin)) { + if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } @@ -1031,17 +1013,35 @@ tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } - - /* Move string from temporary buffer to data buffer. */ + /* move string from temporary buffer to data buffer */ tokenbuf_free(data); tokenbuf_move(&result, data); } } - return VAR_OK; } -/* XXX */ +/* parse an integer number ("123") */ +static int +parse_integer( + var_t *var, var_parse_t *ctx, + const char *begin, const char *end, + int *result) +{ + const char *p; + int num; + + p = begin; + num = 0; + while (isdigit(*p) && p != end) { + num *= 10; + num += (*p - '0'); + p++; + } + if (result != NULL) + *result = num; + return (p - begin); +} /* parse an operation (":x...") */ static int @@ -1054,6 +1054,7 @@ tokenbuf_t tmptokbuf; tokenbuf_t search, replace, flags; tokenbuf_t number1, number2; + int num1, num2; int isrange; int rc; char *ptr; @@ -1110,12 +1111,13 @@ case 'o': { /* cut out substring of value. */ p++; - rc = parse_number(var, ctx, p, end); + rc = parse_integer(var, ctx, p, end, &num1); if (rc == 0) { rc = VAR_ERR_MISSING_START_OFFSET; goto error_return; } - tokenbuf_set(&number1, p, p + rc, 0); + else if (rc < 0) + goto error_return; p += rc; if (*p == ',') { isrange = 0; @@ -1127,11 +1129,10 @@ rc = VAR_ERR_INVALID_OFFSET_DELIMITER; goto error_return; } - rc = parse_number(var, ctx, p, end); - tokenbuf_set(&number2, p, p + rc, 0); + rc = parse_integer(var, ctx, p, end, &num2); p += rc; if (data->begin != NULL) { - rc = op_cut_out_offset(data, &number1, &number2, isrange); + rc = op_offset(var, ctx, data, num1, num2, isrange); if (rc < 0) goto error_return; } @@ -1238,7 +1239,7 @@ tokenbuf_set(&flags, p, p + rc, 0); p += rc; if (data->begin != NULL) { - rc = op_search_and_replace(data, &search, &replace, &flags); + rc = op_search_and_replace(var, ctx, data, &search, &replace, &flags); if (rc < 0) goto error_return; } @@ -1269,7 +1270,7 @@ } else p++; if (data->begin) { - rc = op_transpose(data, &search, &replace); + rc = op_transpose(var, ctx, data, &search, &replace); if (rc < 0) goto error_return; } @@ -1281,12 +1282,11 @@ if (*p != '/') return VAR_ERR_MALFORMATTED_PADDING; p++; - rc = parse_number(var, ctx, p, end); + rc = parse_integer(var, ctx, p, end, &num1); if (rc == 0) { rc = VAR_ERR_MISSING_PADDING_WIDTH; goto error_return; } - tokenbuf_set(&number1, p, p + rc, 0); p += rc; if (*p != '/') { rc = VAR_ERR_MALFORMATTED_PADDING; @@ -1308,7 +1308,7 @@ } p++; if (data->begin) { - rc = op_padding(data, &number1, &replace, p[-1]); + rc = op_padding(var, ctx, data, num1, &replace, p[-1]); if (rc < 0) goto error_return; } @@ -1339,25 +1339,6 @@ return rc; } -/* parse an integer number ("123") */ -static int -parse_integer( - var_t *var, var_parse_t *ctx, - const char *begin, const char *end, - int *result) -{ - const char *p; - - p = begin; - (*result) = 0; - while (isdigit(*p) && p != end) { - (*result) *= 10; - (*result) += (*p - '0'); - p++; - } - return (p - begin); -} - /* parse numerical expression operand */ static int parse_numexp_operand(