summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ocamlbuild/pathname.ml30
-rw-r--r--ocamlbuild/pathname.mli1
2 files changed, 31 insertions, 0 deletions
diff --git a/ocamlbuild/pathname.ml b/ocamlbuild/pathname.ml
index c6410336f..e148a7d75 100644
--- a/ocamlbuild/pathname.ml
+++ b/ocamlbuild/pathname.ml
@@ -55,8 +55,38 @@ let is_directory x =
let readdir x = Outcome.good (sys_readdir x)
let dir_seps = ['/';'\\'] (* FIXME add more *)
+let not_normal_form_re = Glob.parse "<**/{,.,..}/**>"
+
let parent x = concat parent_dir_name x
+let split p =
+ let rec go p acc =
+ let dir = dirname p in
+ if dir = p then dir, acc
+ else go dir (basename p :: acc)
+ in go p []
+
+let join root paths =
+ let root = if root = current_dir_name then "" else root in
+ List.fold_left (/) root paths
+
+let _H1 = assert (current_dir_name = ".")
+let _H2 = assert (parent_dir_name = "..")
+
+(* Use H1, H2 *)
+let rec normalize_list = function
+ | [] -> []
+ | "." :: xs -> normalize_list xs
+ | ".." :: _ -> failwith "Pathname.normalize_list: .. is forbidden here"
+ | _ :: ".." :: xs -> normalize_list xs
+ | x :: xs -> x :: normalize_list xs
+
+let normalize x =
+ if Glob.eval not_normal_form_re x then
+ let root, paths = split x in
+ join root (normalize_list paths)
+ else x
+
(* [is_prefix x y] is [x] a pathname prefix of [y] *)
let is_prefix x y =
let lx = String.length x and ly = String.length y in
diff --git a/ocamlbuild/pathname.mli b/ocamlbuild/pathname.mli
index 63deaf9cf..281d201fc 100644
--- a/ocamlbuild/pathname.mli
+++ b/ocamlbuild/pathname.mli
@@ -13,3 +13,4 @@
(* Original author: Nicolas Pouillard *)
include Signatures.PATHNAME
val link_to_dir : t -> t -> bool
+val normalize : t -> t