shithub: mc

Download patch

ref: 7a2073771b362a3597b6812bd26f5cbe4d1d9000
parent: 4efd6777d6644058c97db129288a4ab48fcfd92d
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Jun 13 16:04:31 EDT 2018

Add system-selected tag lists.

	This lightens the requirements for a `./configure` script,
	and allows creating dependent tags based on system features.

--- a/mbld/parse.myr
+++ b/mbld/parse.myr
@@ -42,7 +42,7 @@
 	sel = mksyssel(b, "mbld", 0, "mbld")
 	ok = loadall(b, "bld.proj", "", sel)
 
-	targs = sysselfin(sel)
+	targs = sysselfin(b, sel)
 	for (name, targ) : targs
 		std.slpush(&b.all, name)
 		std.htput(b.targs, name, targ)
@@ -429,9 +429,9 @@
 	| `std.Some (wl, libs): 
 		libdeps = libs
 		for w : wl
-			sysseladd(fsel, w)
+			sysseladd(b, fsel, w)
 		;;
-		inputs = sysselfin(fsel)
+		inputs = sysselfin(b, fsel)
 		std.slfree(wl)
 	| `std.None: failparse(p, "expected list of file names after '{} {}'\n", targ, name)
 	;;
@@ -761,7 +761,7 @@
 	var tn
 
 	tn = std.fmt("{}:{}", p.fdir, name)
-	sysseladdlist(p.targsel, tn, tags, (tn, targ))
+	sysseladdlist(b, p.targsel, tn, tags, (tn, targ))
 	std.slpush(&p.targs, targ)
 }
 
--- a/mbld/syssel.myr
+++ b/mbld/syssel.myr
@@ -1,4 +1,5 @@
 use std
+use bio
 
 use "opts"
 use "types"
@@ -8,15 +9,14 @@
 		file	: byte[:]
 		line	: int
 		targ	: byte[:]
-		sysattrs	: std.htab(byte[:], (int, int, int))#
 		_match	: std.htab(byte[:], (int, int))#
 		_best	: std.htab(byte[:], @a)#
 	;;
 
 	generic mksyssel	: (b : build#, f : byte[:], line : int, targ : byte[:] -> syssel(@a)#)
-	generic sysseladd	: (syssel : syssel(byte[:])#, file : byte[:] -> void)
-	generic sysseladdlist	: (syssel : syssel(@a)#, base : byte[:], attrs : byte[:][:], val : @a -> void)
-	generic sysselfin	: (syssel : syssel(@a)# -> @a[:])
+	generic sysseladd	: (b : build#, syssel : syssel(byte[:])#, file : byte[:] -> void)
+	generic sysseladdlist	: (b : build#, syssel : syssel(@a)#, base : byte[:], attrs : byte[:][:], val : @a -> void)
+	generic sysselfin	: (b : build#, syssel : syssel(@a)# -> @a[:])
 	const addsysattrs	: (sa : build#, tags : byte[:][:] -> void)
 ;;
 
@@ -29,12 +29,11 @@
 		.targ = targ,
 		._match = std.mkht(),
 		._best = std.mkht(),
-		.sysattrs = b.tags
 	])
 	-> syssel
 }
 
-generic sysseladd = {syssel, f
+generic sysseladd = {b, syssel, f
 	var basename, attrs
 	var attrlist
 
@@ -55,38 +54,23 @@
 	;;
 
 	attrlist = std.strsplit(attrs, "-")
-	sysseladdlist(syssel, basename, attrlist, f)
+	sysseladdlist(b, syssel, basename, attrlist, f)
 	std.slfree(attrlist)
 }
 
-generic sysseladdlist = {syssel, base, attrs, val
-	var nmatch, vscore, n, v, s
+generic sysseladdlist = {b, syssel, base, attrs, val
+	var nmatch, vscore, s
 
 	nmatch = 0
 	vscore = 0
 	for a : attrs
-		match std.strfind(a, ":")
-		| `std.Some i:
-			n = a[:i]
-			v = parseversion(a[i+1:])
-		| `std.None:
-			n = a
-			v = (-1, -1, -1)
-		;;
-
-		match std.htget(syssel.sysattrs, n)
-		| `std.None:
+		s = tagscore(b, a)
+		if s < 0
 			nmatch = -1
 			break
-		| `std.Some have:
-			s = versionscore(syssel, have, v)
-			if s < 0
-				nmatch = -1
-				break
-			;;
-			vscore += s
-			nmatch++
 		;;
+		vscore += s
+		nmatch++
 	;;
 	match std.htgetv(syssel._match, base, (-1, -1))
 	| (curbest, curscore):
@@ -97,7 +81,25 @@
 	;;
 }
 
-const versionscore = {syssel, have, want
+const tagscore = {b, tag
+	var n, v
+
+	match std.strfind(tag, ":")
+	| `std.Some i:
+		n = tag[:i]
+		v = parseversion(tag[i+1:])
+	| `std.None:
+		n = tag
+		v = (-1, -1, -1)
+	;;
+
+	match std.htget(b.tags, n)
+	| `std.None:	-> -1
+	| `std.Some cv:	-> versionscore(cv, v)
+	;;
+}
+
+const versionscore = {have, want
 	var s
 
 	s = 0
@@ -123,7 +125,7 @@
 	;;
 }
 
-generic sysselfin = {syssel
+generic sysselfin = {b, syssel
 	var keys, nmatch, ret
 
 	keys = std.htkeys(syssel._match)
@@ -178,7 +180,7 @@
 		for t : tags
 			tag(b, t)
 		;;
-		loadtagfile(b, "bld.tag")
+		loadtagfile(b, "bld.tags")
 	;;
 }
 
@@ -196,20 +198,94 @@
 }
 
 const loadtagfile = {b, tagfile
-	var data, sp
+	var deptags, tagmap, changed
+	var tf, lnum
 
 	if !std.fexists(tagfile)
 		-> void
 	;;
-	data = std.try(std.slurp(tagfile))
-	while true
-		sp = std.strtok(data)
-		for t : sp
-			tag(b, t)
+
+	match bio.open(tagfile, bio.Rd)
+	| `std.Ok f:	tf = f
+	| `std.Err e:	std.fatal("could not open tagfile: {}\n", e)
+	;;
+
+	lnum = 0
+	tagmap = std.mkht()
+	/*
+	 * Parse the list of tags. Each line is in the form of
+	 *
+	 *	tag list ":" tag list
+	 * 
+	 * The left hand side of the tag list describes the tags
+	 * that get added if the tags on the right hand side all
+	 * are present.
+	 */
+	for ln : bio.byline(tf)
+		lnum++
+		match std.strfind(ln, ":")
+		| `std.None:
+			for t : std.bytok(ln)
+				tag(b, t)
+			;;
+			continue
+		| `std.Some idx:
+			if std.strstrip(ln[:idx]).len == 0
+				std.fatal("{}:{}: missing tags before ':'\n", tagfile, lnum)
+			;;
+			deptags = [][:]
+			for d : std.bytok(ln[idx+1:])
+				std.slpush(&deptags, std.sldup(d))
+			;;
+			for t : std.bytok(ln[:idx])
+				match std.htget(tagmap, t)
+				| `std.Some v:
+					std.slpush(&v, deptags)
+					std.htput(tagmap, t, v)
+				| `std.None:
+					std.htput(tagmap, std.sldup(t), std.sldup([deptags][:]))
+				;;
+			;;
 		;;
-		std.slfree(sp)
 	;;
-	std.slfree(data)
+	bio.close(tf)
+	
+	/* 
+	 * Because tags may depend on other tags, we need to iterate
+	 * here until the set of tags reach a fixed point. Each tag
+	 * that we insert may potentially free other tags to be inserted,
+	 * so either we make progress on the finite set of tags, or we
+	 * don't make a change and break out of the loop.
+	 */
+	changed = true
+	while changed
+		changed = false
+		for (k, vss) : std.byhtkeyvals(tagmap)
+			if std.hthas(b.tags, k)
+				continue
+			;;
+			for vs : vss
+				for v : vs
+					if tagscore(b, v) == -1
+						goto next
+					;;
+				;;
+				tag(b, k)
+				changed = true
+:next
+			;;
+		;;
+	;;
+	for (k, vss) : std.byhtkeyvals(tagmap)
+		std.slfree(k)
+		for vs : vss
+			for v : vs
+				std.slfree(v)
+			;;
+			std.slfree(vs)
+		;;
+		std.slfree(vss)
+	;;
 }
 
 const tag  = {b, t
@@ -219,7 +295,6 @@
 		std.htput(b.tags, std.sldup(t), (-1, -1, -1))
 	| `std.Some idx:
 		v = parseversion(t[idx+1:])
-		std.put("version: {} : {}\n", t[:idx], v)
 		std.htput(b.tags, std.sldup(t[:idx]), v)
 	;;