ref: 7db55ba13f856c868b23a83dc3e10fa9fbc5fa3b
parent: 1951e01288b48817b8cb5e9b789f4f9fb01527b7
author: Arnold D. Robbins <arnold@skeeve.com>
date: Fri Dec 27 07:02:52 EST 2019
Bug fix in interval expressions.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2019-12-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * b.c (replace_repeat): Fix a bug whereby a{0,3} could match+ four a's. Thanks to Anonymous AWK fan <awkfan77@mailfence.com>
+ for the report. Also, minor code formatting cleanups.
+ * testdir/T.int-expr: New file.
+
2019-12-11 Arnold D. Robbins <arnold@skeeve.com>
* README: Renamed to ...
--- a/FIXES
+++ b/FIXES
@@ -25,6 +25,10 @@
This file lists all bug fixes, changes, etc., made since the AWK book
was sent to the printers in August, 1987.
+December 27, 2019:
+ Fix a bug whereby a{0,3} could match four a's. Thanks to+ "Anonymous AWK fan" for the report.
+
December 11, 2019:
Further printf-related fixes for 32 bit systems.
Thanks again to Christos Zoulas.
--- a/b.c
+++ b/b.c
@@ -908,7 +908,7 @@
int i, j;
uschar *buf = 0;
int ret = 1;
- int init_q = (firstnum == 0); /* first added char will be ? */
+ bool init_q = (firstnum == 0); /* first added char will be ? */
int n_q_reps = secondnum-firstnum; /* m>n, so reduce until {1,m-n} left */int prefix_length = reptok - basestr; /* prefix includes first rep */
int suffix_length = strlen((const char *) reptok) - reptoklen; /* string after rep specifier */
@@ -935,7 +935,7 @@
buf[j++] = '(';buf[j++] = ')';
}
- for (i=1; i < firstnum; i++) { /* copy x reps */+ for (i = 1; i < firstnum; i++) { /* copy x reps */memcpy(&buf[j], atom, atomlen);
j += atomlen;
}
@@ -944,7 +944,7 @@
} else if (special_case == REPEAT_WITH_Q) {if (init_q)
buf[j++] = '?';
- for (i = 0; i < n_q_reps; i++) { /* copy x? reps */+ for (i = init_q; i < n_q_reps; i++) { /* copy x? reps */memcpy(&buf[j], atom, atomlen);
j += atomlen;
buf[j++] = '?';
@@ -1166,15 +1166,17 @@
if (commafound) { if (digitfound) { /* {n,m} */m = num;
- if (m<n)
+ if (m < n)
FATAL("illegal repetition expression: class %.20s",lastre);
- if ((n==0) && (m==1)) {+ if (n == 0 && m == 1) {return QUEST;
}
} else { /* {n,} */- if (n==0) return STAR;
- if (n==1) return PLUS;
+ if (n == 0)
+ return STAR;
+ else if (n == 1)
+ return PLUS;
}
} else { if (digitfound) { /* {n} same as {n,n} */@@ -1187,7 +1189,7 @@
}
if (repeat(starttok, prestr-starttok, lastatom,
startreptok - lastatom, n, m) > 0) {- if ((n==0) && (m==0)) {+ if (n == 0 && m == 0) {return EMPTYRE;
}
/* must rescan input for next token */
@@ -1313,7 +1315,7 @@
for (i = 0; i <= f->accept; i++) {xfree(f->re[i].lfollow);
if (f->re[i].ltype == CCL || f->re[i].ltype == NCCL)
- xfree((f->re[i].lval.np));
+ xfree(f->re[i].lval.np);
}
xfree(f->restr);
xfree(f->out);
--- a/main.c
+++ b/main.c
@@ -22,7 +22,7 @@
THIS SOFTWARE.
****************************************************************/
-const char *version = "version 20191211";
+const char *version = "version 20191227";
#define DEBUG
#include <stdio.h>
--- /dev/null
+++ b/testdir/T.int-expr
@@ -1,0 +1,82 @@
+echo T.int-expr: test interval expressions
+
+awk=${awk-../a.out}+
+rm -f foo
+
+cat << \EOF > prog
+NF == 0 { next }+$1 == "pat" { pattern = $2; next }+{+ check = ($1 ~ pattern)
+ printf("%s ~ /%s/ -> should be %d, is %d\n", $1, pattern, $2, check)+}
+EOF
+
+cat << \EOF > foo.in
+pat ab{0}c+ac 1
+abc 0
+
+pat ab{1}c+ac 0
+abc 1
+abbc 0
+
+pat ab{1,}c+ac 0
+abc 1
+abbc 1
+abbbc 1
+abbbbc 1
+
+pat ab{0,1}c+ac 1
+abc 1
+abbc 0
+
+pat ab{0,3}c+ac 1
+abc 1
+abbc 1
+abbbc 1
+abbbbc 0
+
+pat ab{1,3}c+ac 0
+abc 1
+abbc 1
+abbbc 1
+abbbbc 0
+EOF
+
+cat << \EOF > foo1
+ac ~ /ab{0}c/ -> should be 1, is 1+abc ~ /ab{0}c/ -> should be 0, is 0+ac ~ /ab{1}c/ -> should be 0, is 0+abc ~ /ab{1}c/ -> should be 1, is 1+abbc ~ /ab{1}c/ -> should be 0, is 0+ac ~ /ab{1,}c/ -> should be 0, is 0+abc ~ /ab{1,}c/ -> should be 1, is 1+abbc ~ /ab{1,}c/ -> should be 1, is 1+abbbc ~ /ab{1,}c/ -> should be 1, is 1+abbbbc ~ /ab{1,}c/ -> should be 1, is 1+ac ~ /ab{0,1}c/ -> should be 1, is 1+abc ~ /ab{0,1}c/ -> should be 1, is 1+abbc ~ /ab{0,1}c/ -> should be 0, is 0+ac ~ /ab{0,3}c/ -> should be 1, is 1+abc ~ /ab{0,3}c/ -> should be 1, is 1+abbc ~ /ab{0,3}c/ -> should be 1, is 1+abbbc ~ /ab{0,3}c/ -> should be 1, is 1+abbbbc ~ /ab{0,3}c/ -> should be 0, is 0+ac ~ /ab{1,3}c/ -> should be 0, is 0+abc ~ /ab{1,3}c/ -> should be 1, is 1+abbc ~ /ab{1,3}c/ -> should be 1, is 1+abbbc ~ /ab{1,3}c/ -> should be 1, is 1+abbbbc ~ /ab{1,3}c/ -> should be 0, is 0+EOF
+
+
+$awk -f prog foo.in > foo2
+diff foo1 foo2 || echo 'BAD: T.int-expr (1)'
+rm -f prog
--
⑨