shithub: mc

Download patch

ref: c212e703cdde390fc26e18bbe0f7e96bc6546647
parent: 968a619a87998e26aca1498e42a296d1e9d5a5e7
author: Ori Bernstein <[email protected]>
date: Thu Aug 14 06:40:32 EDT 2014

Add path joining and normalization functions.

--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -26,6 +26,7 @@
     now.myr \
     option.myr \
     optparse.myr \
+    pathjoin.myr \
     rand.myr \
     resolve.myr \
     result.myr \
--- /dev/null
+++ b/libstd/pathjoin.myr
@@ -1,0 +1,85 @@
+use "alloc.use"
+use "strjoin.use"
+use "strsplit.use"
+use "sleq.use"
+use "sldup.use"
+use "slcp.use"
+use "die.use"
+use "fmt.use"
+
+pkg std =
+	const pathcat	: (a : byte[:], b : byte[:] -> byte[:])
+	const pathjoin	: (p : byte[:][:] -> byte[:])
+	const pathnorm	: (p : byte[:] -> byte[:])
+;;
+
+const pathcat = {a, b
+	-> pathjoin([a, b][:])
+}
+
+const pathjoin = {l
+	var p, q
+
+	p = strjoin(l, "/")
+	q = pathnorm(p)
+	slfree(p)
+	-> q
+}
+
+const pathnorm = {p
+	var comps
+	var i, del, dst
+	var s, ret
+
+	comps = strsplit(p, "/")
+	/* "." is a no-op component, so we drop it */
+	for i = 0; i < comps.len; i++
+		if sleq(comps[i], ".")
+			comps[i] = ""
+		;;
+	;;
+
+	/* then, resolve '..' by cancelling out previous components */
+	for i = 0; i < comps.len; i++
+		if !sleq(comps[i], "..")
+			continue
+		;;
+		for del = 1; del <= i; del++
+			if comps[i - del].len > 0 && !sleq(comps[i-del], "..")
+				comps[i - del] = ""
+				comps[i] = ""
+				break
+			;;
+		;;
+	;;
+
+	/* clear out the path nodes we decided to drop */
+	dst = 0
+	for i = 0; i < comps.len; i++
+		if comps[i].len > 0
+			comps[dst++] = comps[i]
+		;;
+	;;
+	comps = comps[:dst]
+
+	/* and reassemble */
+	if p.len > 0 && sleq(p[:1], "/")
+		/* /.. is just / */
+		for i = 0; i < comps.len; i++
+			if !sleq(comps[i], "..")
+				break
+			;;
+		;;
+		s = strjoin(comps[i:], "/")
+		ret = fmt("/%s", s)
+		slfree(s)
+	elif comps.len == 0
+		/* empty paths become '.' */
+		ret = sldup(".")
+	else
+		ret = strjoin(comps, "/")
+	;;
+	slfree(comps)
+	-> ret
+}
+
--- a/myrbuild/myrbuild.c
+++ b/myrbuild/myrbuild.c
@@ -419,8 +419,6 @@
             die("Unknown file type %s", files[i]);
         lappend(&args, &nargs, strdup(buf));
     }
-    snprintf(buf, sizeof buf, "-L%s%s", Instroot, "/lib/myr");
-    lappend(&args, &nargs, strdup(buf));
 
     /* ld -T ldscript -o outfile foo.o bar.o baz.o -L/path1 -L/path2 */
     for (i = 0; i < nincpaths; i++) {
@@ -427,6 +425,8 @@
         snprintf(buf, sizeof buf, "-L%s", incpaths[i]);
         lappend(&args, &nargs, strdup(buf));
     }
+    snprintf(buf, sizeof buf, "-L%s%s", Instroot, "/lib/myr");
+    lappend(&args, &nargs, strdup(buf));
 
     /* ld -T ldscript -o outfile foo.o bar.o baz.o -L/path1 -L/path2 -llib1 -llib2*/
     addlibs(&args, &nargs, libgraph);
--- /dev/null
+++ b/test/stdpathnorm.myr
@@ -1,0 +1,38 @@
+use std
+
+const main = {
+	/* untouched */
+	std.put("%s\n", std.pathnorm("foo"))
+	std.put("%s\n", std.pathnorm("foo/bar"))
+	std.put("%s\n", std.pathnorm("/foo/bar"))
+	std.put("%s\n", std.pathnorm("."))
+
+	/* empty path becomes "." */
+	std.put("%s\n", std.pathnorm("."))
+
+	/* delete //, trailing / */
+	std.put("%s\n", std.pathnorm("foo/"))
+	std.put("%s\n", std.pathnorm("foo//bar/baz"))
+	std.put("%s\n", std.pathnorm("//foo//bar/"))
+
+	/* delete '.' */
+	std.put("%s\n", std.pathnorm("foo/./bar"))
+	std.put("%s\n", std.pathnorm("/foo/bar/."))
+	std.put("%s\n", std.pathnorm("./foo/bar/."))
+
+	/* elide '..' */
+	std.put("%s\n", std.pathnorm("/../foo/bar"))
+	std.put("%s\n", std.pathnorm("../../foo/bar"))
+	std.put("%s\n", std.pathnorm("foo/bar/.."))
+	std.put("%s\n", std.pathnorm("foo/bar/../.."))
+	std.put("%s\n", std.pathnorm("foo/../bar/../.."))
+	std.put("%s\n", std.pathnorm("/foo/../bar/../.."))
+
+	/* mix all of the above */
+	std.put("%s\n", std.pathnorm("/../foo//bar"))
+	std.put("%s\n", std.pathnorm("..//../foo/bar"))
+	std.put("%s\n", std.pathnorm("foo//./bar/.."))
+	std.put("%s\n", std.pathnorm("foo/bar/.././.."))
+	std.put("%s\n", std.pathnorm("//foo/../bar/../.."))
+	std.put("%s\n", std.pathnorm("foo/../bar/../.."))
+}
--- a/test/tests
+++ b/test/tests
@@ -129,6 +129,7 @@
 B strjoin	C
 B stdslcp	C
 B stdfmtpad	C
+B stdpathnorm	C
 B bigint	C
 B exporttrait
 # B local-labels	E	10 ## BUGGERED