--- var.c 2002/03/07 09:08:11 1.84
+++ var.c 2002/03/07 09:14:05 1.85
@@ -845,6 +845,7 @@
tokenbuf_t tmp;
const char *p;
int case_insensitive = 0;
+ int multiline = 0;
int global = 0;
int no_regex = 0;
int rc;
@@ -852,19 +853,22 @@
if (search->begin == search->end)
return VAR_ERR_EMPTY_SEARCH_STRING;
- for (p = flags->begin; p != flags->end; ++p) {
+ 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_ERR_UNKNOWN_REPLACE_FLAG;
+ case 'm':
+ multiline = 1;
+ break;
+ case 'i':
+ case_insensitive = 1;
+ break;
+ case 'g':
+ global = 1;
+ break;
+ case 't':
+ no_regex = 1;
+ break;
+ default:
+ return VAR_ERR_UNKNOWN_REPLACE_FLAG;
}
}
@@ -916,7 +920,10 @@
}
/* compile the pattern. */
- rc = regcomp(&preg, tmp.begin, REG_NEWLINE|REG_EXTENDED|((case_insensitive)?REG_ICASE:0));
+ rc = regcomp(&preg, tmp.begin,
+ ( REG_EXTENDED
+ | (multiline ? REG_NEWLINE : 0)
+ | (case_insensitive ? REG_ICASE : 0)));
tokenbuf_free(&tmp);
if (rc != 0) {
tokenbuf_free(&mydata);
@@ -925,31 +932,41 @@
/* match the pattern and create the result string in the tmp buffer */
tokenbuf_append(&tmp, "", 0);
- for (p = mydata.begin; p != mydata.end; ) {
+ for (p = mydata.begin; p < mydata.end; ) {
if (p == mydata.begin || p[-1] == '\n')
regexec_flag = 0;
else
regexec_flag = REG_NOTBOL;
rc = regexec(&preg, p, sizeof(pmatch) / sizeof(regmatch_t), pmatch, regexec_flag);
- if (rc != 0 || p + pmatch[0].rm_so == mydata.end) {
+ /* XXX */
+ if (rc != 0) {
+ /* no (more) matching */
tokenbuf_append(&tmp, p, mydata.end - p);
break;
- } else {
- /* create replace string */
- rc = parse_regex_replace(var, ctx, p, replace, pmatch, &myreplace);
- if (rc != VAR_OK) {
+ }
+ else if ( multiline
+ && (p + pmatch[0].rm_so) == mydata.end
+ && (pmatch[0].rm_eo - pmatch[0].rm_so) == 0) {
+ /* special case: found empty pattern (usually /^/ or /$/ only)
+ in multi-line at end of data (after the last newline) */
+ tokenbuf_append(&tmp, p, mydata.end - p);
+ break;
+ }
+ else {
+ /* append prolog string */
+ if (!tokenbuf_append(&tmp, p, pmatch[0].rm_so)) {
regfree(&preg);
tokenbuf_free(&tmp);
tokenbuf_free(&mydata);
- return rc;
+ return VAR_ERR_OUT_OF_MEMORY;
}
- /* append prolog string */
- if (!tokenbuf_append(&tmp, p, pmatch[0].rm_so)) {
+ /* create replace string */
+ rc = parse_regex_replace(var, ctx, p, replace, pmatch, &myreplace);
+ if (rc != VAR_OK) {
regfree(&preg);
tokenbuf_free(&tmp);
tokenbuf_free(&mydata);
- tokenbuf_free(&myreplace);
- return VAR_ERR_OUT_OF_MEMORY;
+ return rc;
}
/* append replace string */
if (!tokenbuf_append(&tmp, myreplace.begin, myreplace.end - myreplace.begin)) {
@@ -959,19 +976,26 @@
tokenbuf_free(&myreplace);
return VAR_ERR_OUT_OF_MEMORY;
}
+ tokenbuf_free(&myreplace);
+ /* skip now processed data */
p += pmatch[0].rm_eo;
- /* XXX??? */
+ /* if pattern matched an empty part (think about
+ anchor-only regular expressions like /^/ or /$/) we
+ skip the next character to make sure we do not enter
+ an infinitive loop in matching */
if ((pmatch[0].rm_eo - pmatch[0].rm_so) == 0) {
+ if (p >= mydata.end)
+ break;
if (!tokenbuf_append(&tmp, p, 1)) {
regfree(&preg);
tokenbuf_free(&tmp);
tokenbuf_free(&mydata);
- tokenbuf_free(&myreplace);
return VAR_ERR_OUT_OF_MEMORY;
}
p++;
}
- tokenbuf_free(&myreplace);
+ /* append prolog string and stop processing if we
+ do not perform the search & replace globally */
if (!global) {
if (!tokenbuf_append(&tmp, p, mydata.end - p)) {
regfree(&preg);
|