Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh I noticed!



details:   https://anonhg.NetBSD.org/src/rev/1462a2069dfb
branches:  trunk
changeset: 823810:1462a2069dfb
user:      kre <kre%NetBSD.org@localhost>
date:      Wed May 10 06:18:43 2017 +0000

description:
I noticed!

POSIX requires that the output of the "set" command (with no args -- it
gives a list of variables, and their values) be sorted according to
the collating sequence defined by the current locale.

Now I'm not aware of any locale where the collating sequence order of
ascii letters, digits, and '_' are any different than they are in the
C locale (and those are the only characters that can occur in variable
names - unless there is perhaps a locale that defines "dictionary" order
as the sort order) but never mind, that isn't the bug...

What "collating sequence order" does mean however, if not "collating
sequence order, except when we happen to have two variable names, where
one name is a prefix of the other (say X and XY) and the first character
of the 'Y' part of the longer name happens to be a digit..."

"set" is not a frequently used command (particularly in scripts where
it matters - that is, the no args form, nothing here alters anything
about any use of set with args) and is already a bit slow (sluggish...)
because of the sort requirement, so let's make it fractionally even
slower, but correct.

diffstat:

 bin/sh/var.c |  33 +++++++++++++++++++++++++++++----
 1 files changed, 29 insertions(+), 4 deletions(-)

diffs (55 lines):

diff -r 32389cf9001b -r 1462a2069dfb bin/sh/var.c
--- a/bin/sh/var.c      Wed May 10 06:08:56 2017 +0000
+++ b/bin/sh/var.c      Wed May 10 06:18:43 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: var.c,v 1.51 2017/05/03 00:39:40 kre Exp $     */
+/*     $NetBSD: var.c,v 1.52 2017/05/10 06:18:43 kre Exp $     */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)var.c      8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: var.c,v 1.51 2017/05/03 00:39:40 kre Exp $");
+__RCSID("$NetBSD: var.c,v 1.52 2017/05/10 06:18:43 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -526,9 +526,34 @@
 {
        const struct var * const *v1 = v_v1;
        const struct var * const *v2 = v_v2;
+       char *t1 = (*v1)->text, *t2 = (*v2)->text;
 
-       /* XXX Will anyone notice we include the '=' of the shorter name? */
-       return strcoll((*v1)->text, (*v2)->text);
+       if (*t1 == *t2) {
+               char *p, *s;
+
+               STARTSTACKSTR(p);
+
+               /*
+                * note: if lengths are equal, strings must be different
+                * so we don't care which string we pick for the \0 in
+                * that case.
+                */
+               if ((strchr(t1, '=') - t1) <= (strchr(t2, '=') - t2)) {
+                       s = t1;
+                       t1 = p;
+               } else {
+                       s = t2;
+                       t2 = p;
+               }
+
+               while (*s && *s != '=') {
+                       STPUTC(*s, p);
+                       s++;
+               }
+               STPUTC('\0', p);
+       }
+
+       return strcoll(t1, t2);
 }
 
 /*



Home | Main Index | Thread Index | Old Index