Subject: make(1) variables: sort and disorder [patch]
To: None <tech-userlevel@netbsd.org, tech-pkg@netbsd.org>
From: Mike M. Volokhov <mishka@apk.od.ua>
List: tech-pkg
Date: 05/30/2005 17:17:40
--Signature=_Mon__30_May_2005_17_17_40_+0300_ISM7I/0r.vpVH5Mq
Content-Type: multipart/mixed;
 boundary="Multipart=_Mon__30_May_2005_17_17_40_+0300_LTWT7+Ti6v6KcZyz"


--Multipart=_Mon__30_May_2005_17_17_40_+0300_LTWT7+Ti6v6KcZyz
Content-Type: text/plain; charset=US-ASCII
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Greetings!

[Excuse me please for cross-post, but this change is much more make-
specific rather pkgsrc.]

All pkgsrc users have used some predefined list of distribution sites,
known as MASTER_SITE_FOO. The problem is that list is hardcoded and
thus very static, which results in the following caveats:

1) The load on first site at list is dramatically huge, when second and
especially rest mirrors often doesn't used at all.

2) When very first sites is down, user should always wait many seconds
before trying other sites at the list. This problem has been appeared
recently with SourceForge.net mirrors.

To change this behaviour, I've modified make(1) program to provide a
new variable modifier (:X) which is designed to disorder all words in
variable, opposite to :O. For example:

	LIST=3D		xen i386 alpha amd64 vax evbsh5
	ORDERED=3D	${LIST:O}
	DISORDERED=3D	${LIST:O:X}
	INTERMIXED=3D	${LIST:X}
	STATIC_MIX:=3D	${LIST:X}

In this case, variables DISORDERED and INTERMIXED will produce
different results each time they used. I.e the following code:

	.for i in 1 2 3 4 5 6 7 8 9
		@echo "${INTERMIXED}"
	.endfor

will produce a nine different lines.

Please take a look to attached make-intermix.patch. The
bsd.sites.mk.patch modifies MASTER_SITE_SOURCEFORGE variable in a
manner described above (I've left other lists unchanged because I'm not
sure they should be).

--
Mishka.

--Multipart=_Mon__30_May_2005_17_17_40_+0300_LTWT7+Ti6v6KcZyz
Content-Type: text/plain;
 name="make-intermix.patch"
Content-Disposition: attachment;
 filename="make-intermix.patch"
Content-Transfer-Encoding: quoted-printable

Index: make.1
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/home/mishka/NetBSD-CVS/src/usr.bin/make/make.1,v
retrieving revision 1.107
diff -u -r1.107 make.1
--- make.1	8 May 2005 00:38:47 -0000	1.107
+++ make.1	30 May 2005 13:35:30 -0000
@@ -664,6 +664,9 @@
 .Ar pattern .
 .It Cm \&:O
 Order every word in variable alphabetically.
+.It Cm \&:X
+Disorder every word in variable, opposite to
+.Ql Cm \&:O .
 .It Cm \&:Q
 Quotes every shell meta-character in the variable, so that it can be passed
 safely through recursive invocations of
Index: var.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/home/mishka/NetBSD-CVS/src/usr.bin/make/var.c,v
retrieving revision 1.92
diff -u -r1.92 var.c
--- var.c	16 Feb 2005 15:11:53 -0000	1.92
+++ var.c	30 May 2005 13:35:30 -0000
@@ -130,6 +130,7 @@
 #include    <ctype.h>
 #include    <stdlib.h>
 #include    <limits.h>
+#include    <sys/time.h>
=20
 #include    "make.h"
 #include    "buf.h"
@@ -287,7 +288,9 @@
     Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer, Clien=
tData),
     ClientData);
 static char *VarSort(const char *);
+static char *VarUnsort(const char *);
 static char *VarUniq(const char *);
+static int VarNumbCompare(const void *, const void *);
 static int VarWordCompare(const void *, const void *);
 static void VarPrintVar(ClientData);
=20
@@ -1587,6 +1590,83 @@
 }
=20
=20
+static int
+VarNumbCompare(const void *a, const void *b)
+{
+	if (*(int *)a > *(int *)b)
+		return 1;	/* not reachable */
+	else if (*(int *)a < *(int *)b)
+		return -1;	/* not reachable */
+	return 0;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarUnsort --
+ *	Disorder the words in the string.
+ *
+ * Input:
+ *	str		String whose words should be disordered
+ *
+ * Results:
+ *	A string containing the words disordered
+ *
+ * Side Effects:
+ *	None.
+ *
+ *-----------------------------------------------------------------------
+ */
+static char *
+VarUnsort(const char *str)
+{
+    Buffer  	  buf;	    	    /* Buffer for the new string */
+    char **av;			    /* word list [first word does not count] */
+    char *as;			    /* word list memory */
+    int ac, i;
+    struct ai {
+	int rnd;  /* this must be placed first, see VarNumbCompare */
+	char *avi;
+    } *ai =3D NULL;		    /* array of indexes to disorder */
+    struct timeval rightnow;
+
+    buf =3D Buf_Init(0);
+
+    av =3D brk_string(str, &ac, FALSE, &as);
+    ai =3D emalloc(ac * sizeof(struct ai));
+
+    if (ac > 0) {
+	/* intermixed variable should return different values each time */
+	gettimeofday(&rightnow, NULL);
+	srandom(rightnow.tv_sec + rightnow.tv_usec);
+
+	for (i =3D 0; i < ac; i++) {
+		ai[i].rnd =3D random();
+		ai[i].avi =3D av[i];
+	}
+
+	/* sorting ai by the first field will results in disorder of second */
+	qsort(ai, ac, sizeof(struct ai), VarNumbCompare);
+
+	for (i =3D 0; i < ac; i++)
+		av[i] =3D ai[i].avi;
+    }
+
+    for (i =3D 0; i < ac; i++) {
+	Buf_AddBytes(buf, strlen(av[i]), (Byte *) av[i]);
+	if (i !=3D ac - 1)
+	    Buf_AddByte (buf, ' ');
+    }
+
+    free(ai);
+    free(as);
+    free(av);
+
+    Buf_AddByte (buf, '\0');
+    as =3D (char *)Buf_GetAll (buf, (int *)NULL);
+    Buf_Destroy(buf, FALSE);
+    return (as);
+}
+
 /*-
  *-----------------------------------------------------------------------
  * VarUniq --
@@ -2150,6 +2230,7 @@
      *  	  :R	    	Substitute the root of each word
      *  	  	    	(pathname minus the suffix).
      *		  :O		("Order") Sort words in variable.
+     *		  :X		("intermiX") Disorder words in variable.
      *		  :u		("uniq") Remove adjacent duplicate words.
      *		  :tu		Converts the variable contents to uppercase.
      *		  :tl		Converts the variable contents to lowercase.
@@ -3014,6 +3095,14 @@
 			break;
 		    }
 		    /*FALLTHRU*/
+		case 'X':
+		    if (tstr[1] =3D=3D endc || tstr[1] =3D=3D ':') {
+			newStr =3D VarUnsort(nstr);
+			cp =3D tstr + 1;
+			termc =3D *cp;
+			break;
+		    }
+		    /*FALLTHRU*/
 		case 'u':
 		    if (tstr[1] =3D=3D endc || tstr[1] =3D=3D ':') {
 			newStr =3D VarUniq(nstr);

--Multipart=_Mon__30_May_2005_17_17_40_+0300_LTWT7+Ti6v6KcZyz
Content-Type: text/plain;
 name="bsd.sites.mk.patch"
Content-Disposition: attachment;
 filename="bsd.sites.mk.patch"
Content-Transfer-Encoding: quoted-printable

Index: bsd.sites.mk
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/home/mishka/NetBSD-CVS/pkgsrc/mk/bsd.sites.mk,v
retrieving revision 1.37
diff -u -r1.37 bsd.sites.mk
--- bsd.sites.mk	11 May 2005 15:52:14 -0000	1.37
+++ bsd.sites.mk	30 May 2005 13:46:07 -0000
@@ -91,7 +91,7 @@
 	ftp://ftp.dit.upm.es/linux/gnome/ \
 	ftp://ftp.mirror.ac.uk/sites/ftp.gnome.org/pub/
=20
-MASTER_SITE_SOURCEFORGE+=3D	\
+_MASTER_SITE_SOURCEFORGE+=3D	\
 	http://cogent.dl.sourceforge.net/sourceforge/ \
 	http://easynews.dl.sourceforge.net/sourceforge/ \
 	http://heanet.dl.sourceforge.net/sourceforge/ \
@@ -106,6 +106,7 @@
 #	ftp://ftp2.sourceforge.net/pub/sourceforge/
 #	ftp://ftp.tuwien.ac.at/linux/sourceforge/
 #	http://sf.gds.tuwien.ac.at/
+MASTER_SITE_SOURCEFORGE=3D	${_MASTER_SITE_SOURCEFORGE:X}
=20
 MASTER_SITE_SUSE+=3D	\
 	ftp://rpmfind.net/linux/SuSE-Linux/${MACHINE_ARCH}/update/${SUSE_VERSION}=
/ \

--Multipart=_Mon__30_May_2005_17_17_40_+0300_LTWT7+Ti6v6KcZyz--

--Signature=_Mon__30_May_2005_17_17_40_+0300_ISM7I/0r.vpVH5Mq
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (NetBSD)

iD8DBQFCmyCJHwrNSUJZSkURAlrwAJ4yfwcyE+/Ttpq0UoXjYaujeoBFRACeMb0i
DbXmp65oloElZGANDhX63v4=
=CO+X
-----END PGP SIGNATURE-----

--Signature=_Mon__30_May_2005_17_17_40_+0300_ISM7I/0r.vpVH5Mq--