aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--eval.c114
-rw-r--r--test/ChangeLog5
-rw-r--r--test/Makefile.am15
-rw-r--r--test/Makefile.in21
-rw-r--r--test/Maketests6
-rw-r--r--test/posix_compare.awk47
-rw-r--r--test/posix_compare.ok12
8 files changed, 157 insertions, 68 deletions
diff --git a/ChangeLog b/ChangeLog
index 26dfd0e2..eac3a124 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2020-07-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * eval.c (posix_compare): Rewrite contributed by
+ Michael Builov <mbuilov@gmail.com>.
+
2020-06-29 Arnold D. Robbins <arnold@skeeve.com>
* debug.c: Cleanup messages. Error messages start with lower
diff --git a/eval.c b/eval.c
index c6c37b8c..a66eaf37 100644
--- a/eval.c
+++ b/eval.c
@@ -503,79 +503,81 @@ genflags2str(int flagval, const struct flagtab *tab)
static int
posix_compare(NODE *s1, NODE *s2)
{
- int ret = 0;
- char save1, save2;
- size_t l = 0;
+ int ret;
+
+ if (gawk_mb_cur_max == 1) {
+ char save1, save2;
+ const char *p1, *p2;
- save1 = s1->stptr[s1->stlen];
- s1->stptr[s1->stlen] = '\0';
+ save1 = s1->stptr[s1->stlen];
+ s1->stptr[s1->stlen] = '\0';
- save2 = s2->stptr[s2->stlen];
- s2->stptr[s2->stlen] = '\0';
+ save2 = s2->stptr[s2->stlen];
+ s2->stptr[s2->stlen] = '\0';
- if (gawk_mb_cur_max == 1) {
- if (strlen(s1->stptr) == s1->stlen && strlen(s2->stptr) == s2->stlen)
- ret = strcoll(s1->stptr, s2->stptr);
- else {
- char b1[2], b2[2];
- char *p1, *p2;
- size_t i;
-
- if (s1->stlen < s2->stlen)
- l = s1->stlen;
- else
- l = s2->stlen;
-
- b1[1] = b2[1] = '\0';
- for (i = ret = 0, p1 = s1->stptr, p2 = s2->stptr;
- ret == 0 && i < l;
- p1++, p2++) {
- b1[0] = *p1;
- b2[0] = *p2;
- ret = strcoll(b1, b2);
+ p1 = s1->stptr;
+ p2 = s2->stptr;
+
+ for (;;) {
+ size_t len;
+
+ ret = strcoll(p1, p2);
+ if (ret != 0)
+ break;
+
+ len = strlen(p1);
+ p1 += len + 1;
+ p2 += len + 1;
+
+ if (p1 == s1->stptr + s1->stlen + 1) {
+ if (p2 != s2->stptr + s2->stlen + 1)
+ ret = -1;
+ break;
+ }
+ if (p2 == s2->stptr + s2->stlen + 1) {
+ ret = 1;
+ break;
}
}
- /*
- * Either worked through the strings or ret != 0.
- * In either case, ret will be the right thing to return.
- */
+
+ s1->stptr[s1->stlen] = save1;
+ s2->stptr[s2->stlen] = save2;
}
#if ! defined(__DJGPP__)
else {
/* Similar logic, using wide characters */
+ const wchar_t *p1, *p2;
+
(void) force_wstring(s1);
(void) force_wstring(s2);
- if (wcslen(s1->wstptr) == s1->wstlen && wcslen(s2->wstptr) == s2->wstlen)
- ret = wcscoll(s1->wstptr, s2->wstptr);
- else {
- wchar_t b1[2], b2[2];
- wchar_t *p1, *p2;
- size_t i;
-
- if (s1->wstlen < s2->wstlen)
- l = s1->wstlen;
- else
- l = s2->wstlen;
-
- b1[1] = b2[1] = L'\0';
- for (i = ret = 0, p1 = s1->wstptr, p2 = s2->wstptr;
- ret == 0 && i < l;
- p1++, p2++) {
- b1[0] = *p1;
- b2[0] = *p2;
- ret = wcscoll(b1, b2);
+ p1 = s1->wstptr;
+ p2 = s2->wstptr;
+
+ for (;;) {
+ size_t len;
+
+ ret = wcscoll(p1, p2);
+ if (ret != 0)
+ break;
+
+ len = wcslen(p1);
+ p1 += len + 1;
+ p2 += len + 1;
+
+ if (p1 == s1->wstptr + s1->wstlen + 1) {
+ if (p2 != s2->wstptr + s2->wstlen + 1)
+ ret = -1;
+ break;
+ }
+ if (p2 == s2->wstptr + s2->wstlen + 1) {
+ ret = 1;
+ break;
}
}
- /*
- * Either worked through the strings or ret != 0.
- * In either case, ret will be the right thing to return.
- */
}
#endif
- s1->stptr[s1->stlen] = save1;
- s2->stptr[s2->stlen] = save2;
return ret;
}
diff --git a/test/ChangeLog b/test/ChangeLog
index 9b043559..bf033534 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+2020-07-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (EXTRA_DIST): New test, posix_compare.
+ * posix_compare.awk, posix_compare.ok: New files.
+
2020-06-29 Arnold D. Robbins <arnold@skeeve.com>
* dbugeval2.ok, dbugtypedre1.ok, dbugtypedre2.ok, symtab10.ok,
diff --git a/test/Makefile.am b/test/Makefile.am
index 3c241aae..9be24a4c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -905,11 +905,13 @@ EXTRA_DIST = \
pipeio2.awk \
pipeio2.in \
pipeio2.ok \
+ posix2008sub.awk \
+ posix2008sub.ok \
+ posix_compare.awk \
+ posix_compare.ok \
posix.awk \
posix.in \
posix.ok \
- posix2008sub.awk \
- posix2008sub.ok \
poundbang.awk \
prdupval.awk \
prdupval.in \
@@ -1366,7 +1368,7 @@ BASIC_TESTS = \
octsub ofmt ofmta ofmtbig ofmtfidl ofmts ofmtstrnum ofs1 onlynl \
opasnidx opasnslf \
paramasfunc1 paramasfunc2 paramdup paramres paramtyp paramuninitglobal \
- parse1 parsefld parseme pcntplus posix2008sub prdupval prec printf0 \
+ parse1 parsefld parseme pcntplus posix_compare posix2008sub prdupval prec printf0 \
printf1 printfchar prmarscl prmreuse prt1eval prtoeval \
rand randtest range1 range2 readbuf rebrackloc rebt8b1 rebuild redfilnm regeq \
regexpbrack regexpbrack2 regexprange regrange reindops reparse resplit \
@@ -1467,7 +1469,7 @@ NEED_MPFR = mpfrbigint mpfrbigint2 mpfrexprange mpfrfield mpfrieee mpfrmemok1 \
NEED_NONDEC = mpfrbigint2 nondec2 intarray forcenum
# List of tests that need --posix
-NEED_POSIX = escapebrace printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix
+NEED_POSIX = escapebrace printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix posix_compare
# List of tests that need --pretty-print
NEED_PRETTY = nsprof1 nsprof2 \
@@ -1502,8 +1504,9 @@ NEED_LOCALE_C = \
NEED_LOCALE_EN = \
backbigs1 backsmalls1 backsmalls2 concat4 dfamb1 ignrcas2 lc_num1 \
- mbfw1 mbprintf1 mbprintf3 mbprintf4 mbstr1 mbstr2 printhuge reint2 \
- rri1 subamp subi18n wideidx wideidx2 widesub widesub2 widesub3 widesub4
+ mbfw1 mbprintf1 mbprintf3 mbprintf4 mbstr1 mbstr2 posix_compare \
+ printhuge reint2 rri1 subamp subi18n wideidx wideidx2 \
+ widesub widesub2 widesub3 widesub4
# Unused at the moment, since nlstringtest has additional stufff it does
# NEED_LOCALE_FR =
diff --git a/test/Makefile.in b/test/Makefile.in
index c4b72106..fae611a4 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1168,11 +1168,13 @@ EXTRA_DIST = \
pipeio2.awk \
pipeio2.in \
pipeio2.ok \
+ posix2008sub.awk \
+ posix2008sub.ok \
+ posix_compare.awk \
+ posix_compare.ok \
posix.awk \
posix.in \
posix.ok \
- posix2008sub.awk \
- posix2008sub.ok \
poundbang.awk \
prdupval.awk \
prdupval.in \
@@ -1629,7 +1631,7 @@ BASIC_TESTS = \
octsub ofmt ofmta ofmtbig ofmtfidl ofmts ofmtstrnum ofs1 onlynl \
opasnidx opasnslf \
paramasfunc1 paramasfunc2 paramdup paramres paramtyp paramuninitglobal \
- parse1 parsefld parseme pcntplus posix2008sub prdupval prec printf0 \
+ parse1 parsefld parseme pcntplus posix_compare posix2008sub prdupval prec printf0 \
printf1 printfchar prmarscl prmreuse prt1eval prtoeval \
rand randtest range1 range2 readbuf rebrackloc rebt8b1 rebuild redfilnm regeq \
regexpbrack regexpbrack2 regexprange regrange reindops reparse resplit \
@@ -1729,7 +1731,7 @@ NEED_MPFR = mpfrbigint mpfrbigint2 mpfrexprange mpfrfield mpfrieee mpfrmemok1 \
NEED_NONDEC = mpfrbigint2 nondec2 intarray forcenum
# List of tests that need --posix
-NEED_POSIX = escapebrace printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix
+NEED_POSIX = escapebrace printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix posix_compare
# List of tests that need --pretty-print
NEED_PRETTY = nsprof1 nsprof2 \
@@ -1767,8 +1769,9 @@ NEED_LOCALE_C = \
NEED_LOCALE_EN = \
backbigs1 backsmalls1 backsmalls2 concat4 dfamb1 ignrcas2 lc_num1 \
- mbfw1 mbprintf1 mbprintf3 mbprintf4 mbstr1 mbstr2 printhuge reint2 \
- rri1 subamp subi18n wideidx wideidx2 widesub widesub2 widesub3 widesub4
+ mbfw1 mbprintf1 mbprintf3 mbprintf4 mbstr1 mbstr2 posix_compare \
+ printhuge reint2 rri1 subamp subi18n wideidx wideidx2 \
+ widesub widesub2 widesub3 widesub4
# Unused at the moment, since nlstringtest has additional stufff it does
@@ -3672,6 +3675,12 @@ pcntplus:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+posix_compare:
+ @echo $@
+ @[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=en_US.UTF-8; export GAWKLOCALE; \
+ AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
posix2008sub:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 1c54a7cf..f7aaa152 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -798,6 +798,12 @@ pcntplus:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+posix_compare:
+ @echo $@
+ @[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=en_US.UTF-8; export GAWKLOCALE; \
+ AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
posix2008sub:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/posix_compare.awk b/test/posix_compare.awk
new file mode 100644
index 00000000..dcef124d
--- /dev/null
+++ b/test/posix_compare.awk
@@ -0,0 +1,47 @@
+function print_str(str, i, n, chars, result)
+{
+ n = split(str, chars, "")
+ result = ""
+ for (i = 1; i <= n; i++) {
+ if (chars[i] == "\0")
+ result = result "\\0"
+ else
+ result = result chars[i]
+ }
+
+ return result
+}
+
+function do_compare(left, comp, right)
+{
+ if (comp == "<")
+ return left < right ? "TRUE" : "FALSE"
+
+ return left > right ? "TRUE" : "FALSE"
+}
+
+
+BEGIN {
+ left[1] = "abc\0z1"; compare[1] = "<"; right[1] = "abc\0z2"; expected[1] = "TRUE"
+ left[2] = "abc\0z2"; compare[2] = "<"; right[2] = "abc\0z2"; expected[2] = "FALSE"
+ left[3] = "abc\0z3"; compare[3] = "<"; right[3] = "abc\0z2"; expected[3] = "FALSE"
+ left[4] = "abc\0z1"; compare[4] = ">"; right[4] = "abc\0z2"; expected[4] = "FALSE"
+ left[5] = "abc\0z2"; compare[5] = ">"; right[5] = "abc\0z2"; expected[5] = "FALSE"
+ left[6] = "abc\0z3"; compare[6] = ">"; right[6] = "abc\0z2"; expected[6] = "TRUE"
+ left[7] = "abc\0z1"; compare[7] = "<"; right[7] = "abc\0z21"; expected[7] = "TRUE"
+ left[8] = "abc\0z2"; compare[8] = "<"; right[8] = "abc\0z21"; expected[8] = "TRUE"
+ left[9] = "abc\0z3"; compare[9] = "<"; right[9] = "abc\0z21"; expected[9] = "FALSE"
+ left[10] = "abc\0z11"; compare[10] = ">"; right[10] = "abc\0z2"; expected[10] = "FALSE"
+ left[11] = "abc\0z21"; compare[11] = ">"; right[11] = "abc\0z2"; expected[11] = "TRUE"
+ left[12] = "abc\0z31"; compare[12] = ">"; right[12] = "abc\0z2"; expected[12] = "TRUE"
+
+ l = 12
+ for (i = 1; i <= l; i++) {
+ result = do_compare(left[i], compare[i], right[i])
+ lstr = print_str(left[i])
+ rstr = print_str(right[i])
+
+ printf("\"%s\" %s \"%s\": Expecting %s: Got %s\n",
+ lstr, compare[i], rstr, expected[i], result)
+ }
+}
diff --git a/test/posix_compare.ok b/test/posix_compare.ok
new file mode 100644
index 00000000..58dee56b
--- /dev/null
+++ b/test/posix_compare.ok
@@ -0,0 +1,12 @@
+"abc\0z1" < "abc\0z2": Expecting TRUE: Got TRUE
+"abc\0z2" < "abc\0z2": Expecting FALSE: Got FALSE
+"abc\0z3" < "abc\0z2": Expecting FALSE: Got FALSE
+"abc\0z1" > "abc\0z2": Expecting FALSE: Got FALSE
+"abc\0z2" > "abc\0z2": Expecting FALSE: Got FALSE
+"abc\0z3" > "abc\0z2": Expecting TRUE: Got TRUE
+"abc\0z1" < "abc\0z21": Expecting TRUE: Got TRUE
+"abc\0z2" < "abc\0z21": Expecting TRUE: Got TRUE
+"abc\0z3" < "abc\0z21": Expecting FALSE: Got FALSE
+"abc\0z11" > "abc\0z2": Expecting FALSE: Got FALSE
+"abc\0z21" > "abc\0z2": Expecting TRUE: Got TRUE
+"abc\0z31" > "abc\0z2": Expecting TRUE: Got TRUE