Index: ossp-pkg/var/var.c RCS File: /v/ossp/cvs/ossp-pkg/var/var.c,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/var/var.c,v' 2>/dev/null --- var.c 2001/11/13 13:32:58 1.6 +++ var.c 2001/11/13 14:36:55 1.7 @@ -340,6 +340,13 @@ return VAR_INCOMPLETE_NAMED_CHARACTER; switch (*src) { + case '\\': + if (!unescape_all) + { + *dst++ = '\\'; + } + *dst++ = '\\'; + break; case 'n': *dst++ = '\n'; break; @@ -925,6 +932,67 @@ return VAR_OK; } +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; + } + } + + return VAR_OK; + } + static int search_and_replace(tokenbuf* data, tokenbuf* search, tokenbuf* replace, tokenbuf* flags) { const char* p; @@ -936,24 +1004,18 @@ if (search->begin == search->end) return VAR_EMPTY_SEARCH_STRING; - printf("Search '%s' in '%s' and replace it with '%s'.\n", - search->begin, data->begin, replace->begin); - for (p = flags->begin; p != flags->end; ++p) { switch (tolower(*p)) { case 'i': case_insensitive = 1; - printf("case_insensitive = 1;\n"); break; case 'g': global = 1; - printf("global = 1;\n"); break; case 't': no_regex = 1; - printf("no_regex = 1;\n"); break; default: return VAR_UNKNOWN_REPLACE_FLAG; @@ -1003,8 +1065,9 @@ { tokenbuf tmp; tokenbuf mydata; + tokenbuf myreplace; regex_t preg; - regmatch_t pmatch[33]; + regmatch_t pmatch[10]; int regexec_flag; /* Copy the pattern and the data to our own buffer to make @@ -1020,9 +1083,6 @@ /* Compile the pattern. */ - printf("data is.................: '%s'\n", mydata.begin); - printf("regex search pattern is.: '%s'\n", tmp.begin); - printf("regex replace pattern is: '%s'\n", replace->begin); rc = regcomp(&preg, tmp.begin, REG_EXTENDED | ((case_insensitive) ? REG_ICASE : 0)); free_tokenbuf(&tmp); if (rc != 0) @@ -1030,7 +1090,6 @@ free_tokenbuf(&mydata); return VAR_INVALID_REGEX_IN_REPLACE; } - printf("Subexpression in pattern: '%d'\n", preg.re_nsub); /* Match the pattern and create the result string in the tmp buffer. */ @@ -1043,22 +1102,33 @@ regexec_flag = REG_NOTBOL; if (regexec(&preg, p, sizeof(pmatch) / sizeof(regmatch_t), pmatch, regexec_flag) == REG_NOMATCH) { - printf("No match; appending remainder ('%s') to output string.\n", p); 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, replace->begin, replace->end - replace->begin)) + !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; + { + p += (pmatch[0].rm_eo > 0) ? pmatch[0].rm_eo : 1; + free_tokenbuf(&myreplace); + } if (!global) { append_to_tokenbuf(&tmp, p, mydata.end - p); Index: ossp-pkg/var/var.h RCS File: /v/ossp/cvs/ossp-pkg/var/var.h,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/var/var.h,v' 2>/dev/null --- var.h 2001/11/13 12:46:24 1.3 +++ var.h 2001/11/13 14:36:55 1.4 @@ -37,6 +37,8 @@ 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, Index: ossp-pkg/var/var_test.c RCS File: /v/ossp/cvs/ossp-pkg/var/var_test.c,v rcsdiff -q -kk '-r1.5' '-r1.6' -u '/v/ossp/cvs/ossp-pkg/var/var_test.c,v' 2>/dev/null --- var_test.c 2001/11/13 13:33:28 1.5 +++ var_test.c 2001/11/13 14:36:55 1.6 @@ -3,7 +3,7 @@ #include #include "var.h" -int env_lookup(void* context, +static int env_lookup(void* context, const char* varname, size_t name_len, const char** data, size_t* data_len, size_t* buffer_size) { @@ -81,12 +81,13 @@ { "${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" } + { "${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}", "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" } }; - /* - { "${HOME:s/g(res)s/x\\\\1x/g}","/homE/rEgrEssion-tEsts" } - { "${HOME:s/\\x65/\\x45/g}", "/home/regression-tests" } - */ char* tmp; size_t tmp_len; var_rc_t rc; @@ -135,15 +136,6 @@ printf("Test case #%d: Expected result '%s' but got '%s'.\n", i, tests[i].expected, tmp); return 1; } - rc = var_unescape(tests[i].input, strlen(tests[i].input), buffer, 1); - if (rc != VAR_OK) - { - printf("Test case #%d: Second var_unescape() failed with return code %d.\n", i, rc); - return 1; - } -#ifdef DEBUG - printf("Test case #%02d: Unescaped output is '%s'.\n\n", i, tmp); -#endif free(tmp); }