Commits

camlspotter committed 42e62a2 Merge

merge

Comments (0)

Files changed (3)

 (* OASIS_START *)
-(* DO NOT EDIT (digest: 61529f900d7c66a635eb03c94c5c203a) *)
+(* DO NOT EDIT (digest: d842816879e7156bf93e52c5f92f1e9e) *)
 This is the INSTALL file for the planck distribution.
 
 This package uses OASIS to generate its build system. See section OASIS for
 In order to compile this package, you will need:
 * ocaml
 * findlib
-* sexplib (>= 5.2.1)
-* spotlib (>= 1.0.0)
+* sexplib (>= 108.07.00)
+* spotlib (>= 2.0.0)
 * omake
 
 Installing
 ==========
 
-1. Uncompress source directory and got to the root of the package
+1. Uncompress the source archive and go to the root of the package
 2. Run 'ocaml setup.ml -configure'
 3. Run 'ocaml setup.ml -build'
 4. Run 'ocaml setup.ml -install'
 OASIS
 =====
 
-OASIS is a software that helps to write setup.ml using a simple '_oasis'
-configuration file. The generated setup only depends on standard OCaml
-installation, no additional library is required.
+OASIS is a program that generates a setup.ml file using a simple '_oasis'
+configuration file. The generated setup only depends on the standard OCaml
+installation: no additional library is required.
 
 (* OASIS_STOP *)
 OCAML_NATIVE_LINK_FLAGS +=
 
 Subdirs()
+
+setup.ml: _oasis
+	oasis setup
 (* setup.ml generated for the first time by OASIS v0.2.0 *)
 
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 31ee291b017306b79fe8c4a980ed0e2c) *)
+(* DO NOT EDIT (digest: cef0b267827af2c54b8fb09df3311ebf) *)
 (*
-   Regenerated by OASIS v0.2.0
+   Regenerated by OASIS v0.3.0
    Visit http://oasis.forge.ocamlcore.org for more information and
    documentation about functions used in this file.
 *)
 module OASISGettext = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISGettext.ml"
-  
-  let ns_ str = 
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISGettext.ml" *)
+
+  let ns_ str =
     str
-  
-  let s_ str = 
+
+  let s_ str =
     str
-  
+
   let f_ (str : ('a, 'b, 'c, 'd) format4) =
     str
-  
+
   let fn_ fmt1 fmt2 n =
     if n = 1 then
       fmt1^^""
     else
       fmt2^^""
-  
-  let init = 
+
+  let init =
     []
-  
+
 end
 
 module OASISContext = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISContext.ml"
-  
-  open OASISGettext 
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISContext.ml" *)
+
+  open OASISGettext
+
   type level =
     [ `Debug
-    | `Info 
+    | `Info
     | `Warning
     | `Error]
-  
+
   type t =
     {
-      verbose:        bool;
-      debug:          bool;
-      ignore_plugins: bool;
-      printf:         level -> string -> unit; 
+      quiet:                 bool;
+      info:                  bool;
+      debug:                 bool;
+      ignore_plugins:        bool;
+      ignore_unknown_fields: bool;
+      printf:                level -> string -> unit;
     }
-  
-  let printf lvl str = 
-    let beg = 
-      match lvl with 
+
+  let printf lvl str =
+    let beg =
+      match lvl with
         | `Error -> s_ "E: "
         | `Warning -> s_ "W: "
         | `Info  -> s_ "I: "
         | `Debug -> s_ "D: "
     in
-      match lvl with 
-        | `Error ->
-            prerr_endline (beg^str)
-        | _ ->
-            print_endline (beg^str)
-  
+      prerr_endline (beg^str)
+
   let default =
-    ref 
+    ref
       {
-        verbose        = true;
-        debug          = false;
-        ignore_plugins = false;
-        printf         = printf;
+        quiet                 = false;
+        info                  = false;
+        debug                 = false;
+        ignore_plugins        = false;
+        ignore_unknown_fields = false;
+        printf                = printf;
       }
-  
-  let quiet = 
-    {!default with 
-         verbose = false;
-         debug   = false;
-    }
-  
-  
+
+  let quiet =
+    {!default with quiet = true}
+
+
   let args () =
     ["-quiet",
-     Arg.Unit (fun () -> default := {!default with verbose = false}),
+     Arg.Unit (fun () -> default := {!default with quiet = true}),
      (s_ " Run quietly");
-  
+
+     "-info",
+     Arg.Unit (fun () -> default := {!default with info = true}),
+     (s_ " Display information message");
+
+
      "-debug",
      Arg.Unit (fun () -> default := {!default with debug = true}),
      (s_ " Output debug message")]
 end
 
+module OASISString = struct
+(* # 1 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISString.ml" *)
+
+
+
+  (** Various string utilities.
+     
+      Mostly inspired by extlib and batteries ExtString and BatString libraries.
+
+      @author Sylvain Le Gall
+    *)
+
+  let nsplitf str f =
+    if str = "" then
+      []
+    else
+      let buf = Buffer.create 13 in
+      let lst = ref [] in
+      let push () =
+        lst := Buffer.contents buf :: !lst;
+        Buffer.clear buf
+      in
+      let str_len = String.length str in
+        for i = 0 to str_len - 1 do
+          if f str.[i] then
+            push ()
+          else
+            Buffer.add_char buf str.[i]
+        done;
+        push ();
+        List.rev !lst
+
+  (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
+      separator.
+    *)
+  let nsplit str c =
+    nsplitf str ((=) c)
+
+  let find ~what ?(offset=0) str =
+    let what_idx = ref 0 in
+    let str_idx = ref offset in 
+      while !str_idx < String.length str && 
+            !what_idx < String.length what do
+        if str.[!str_idx] = what.[!what_idx] then
+          incr what_idx
+        else
+          what_idx := 0;
+        incr str_idx
+      done;
+      if !what_idx <> String.length what then
+        raise Not_found
+      else 
+        !str_idx - !what_idx
+
+  let sub_start str len = 
+    let str_len = String.length str in
+    if len >= str_len then
+      ""
+    else
+      String.sub str len (str_len - len)
+
+  let sub_end ?(offset=0) str len =
+    let str_len = String.length str in
+    if len >= str_len then
+      ""
+    else
+      String.sub str 0 (str_len - len)
+
+  let starts_with ~what ?(offset=0) str =
+    let what_idx = ref 0 in
+    let str_idx = ref offset in
+    let ok = ref true in
+      while !ok &&
+            !str_idx < String.length str && 
+            !what_idx < String.length what do
+        if str.[!str_idx] = what.[!what_idx] then
+          incr what_idx
+        else
+          ok := false;
+        incr str_idx
+      done;
+      if !what_idx = String.length what then
+        true
+      else 
+        false
+
+  let strip_starts_with ~what str =
+    if starts_with ~what str then
+      sub_start str (String.length what)
+    else
+      raise Not_found
+
+  let ends_with ~what ?(offset=0) str =
+    let what_idx = ref ((String.length what) - 1) in
+    let str_idx = ref ((String.length str) - 1) in
+    let ok = ref true in
+      while !ok &&
+            offset <= !str_idx && 
+            0 <= !what_idx do
+        if str.[!str_idx] = what.[!what_idx] then
+          decr what_idx
+        else
+          ok := false;
+        decr str_idx
+      done;
+      if !what_idx = -1 then
+        true
+      else 
+        false
+
+  let strip_ends_with ~what str =
+    if ends_with ~what str then
+      sub_end str (String.length what)
+    else
+      raise Not_found
+
+  let replace_chars f s =
+    let buf = String.make (String.length s) 'X' in
+      for i = 0 to String.length s - 1 do
+        buf.[i] <- f s.[i]
+      done;
+      buf
+
+end
+
 module OASISUtils = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISUtils.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISUtils.ml" *)
+
+  open OASISGettext
+
   module MapString = Map.Make(String)
-  
+
   let map_string_of_assoc assoc =
     List.fold_left
       (fun acc (k, v) -> MapString.add k v acc)
       MapString.empty
       assoc
-  
+
   module SetString = Set.Make(String)
-  
+
   let set_string_add_list st lst =
-    List.fold_left 
+    List.fold_left
       (fun acc e -> SetString.add e acc)
       st
       lst
-  
+
   let set_string_of_list =
     set_string_add_list
       SetString.empty
-  
-  
-  let compare_csl s1 s2 = 
+
+
+  let compare_csl s1 s2 =
     String.compare (String.lowercase s1) (String.lowercase s2)
-  
-  module HashStringCsl = 
+
+  module HashStringCsl =
     Hashtbl.Make
       (struct
          type t = string
-  
-         let equal s1 s2 = 
+
+         let equal s1 s2 =
              (String.lowercase s1) = (String.lowercase s2)
-  
+
          let hash s =
            Hashtbl.hash (String.lowercase s)
        end)
-  
-  let split sep str =
-    let str_len =
-      String.length str
-    in
-    let rec split_aux acc pos =
-      if pos < str_len then
-        (
-          let pos_sep = 
-            try
-              String.index_from str pos sep
-            with Not_found ->
-              str_len
-          in
-          let part = 
-            String.sub str pos (pos_sep - pos) 
-          in
-          let acc = 
-            part :: acc
-          in
-            if pos_sep >= str_len then
-              (
-                (* Nothing more in the string *)
-                List.rev acc
-              )
-            else if pos_sep = (str_len - 1) then
-              (
-                (* String end with a separator *)
-                List.rev ("" :: acc)
-              )
-            else
-              (
-                split_aux acc (pos_sep + 1)
-              )
-        )
-      else
-        (
-          List.rev acc
-        )
-    in
-      split_aux [] 0
-  
-  
-  let varname_of_string ?(hyphen='_') s = 
+
+  let varname_of_string ?(hyphen='_') s =
     if String.length s = 0 then
       begin
-        invalid_arg "varname_of_string" 
+        invalid_arg "varname_of_string"
       end
     else
       begin
-        let buff = 
-          Buffer.create (String.length s)
+        let buf =
+          OASISString.replace_chars
+            (fun c ->
+               if ('a' <= c && c <= 'z')
+                 ||
+                  ('A' <= c && c <= 'Z')
+                 ||
+                  ('0' <= c && c <= '9') then
+                 c
+               else
+                 hyphen)
+            s;
         in
+        let buf =
           (* Start with a _ if digit *)
           if '0' <= s.[0] && s.[0] <= '9' then
-            Buffer.add_char buff hyphen;
-  
-          String.iter
-            (fun c ->
-               if ('a' <= c && c <= 'z') 
-                 || 
-                  ('A' <= c && c <= 'Z') 
-                 || 
-                  ('0' <= c && c <= '9') then
-                 Buffer.add_char buff c
-               else
-                 Buffer.add_char buff hyphen)
-            s;
-  
-          String.lowercase (Buffer.contents buff)
+            "_"^buf
+          else
+            buf
+        in
+          String.lowercase buf
       end
-  
-  let varname_concat ?(hyphen='_') p s = 
-    let p = 
-      let p_len =
-        String.length p
-      in
-        if p_len > 0 && p.[p_len - 1] = hyphen then
-          String.sub p 0 (p_len - 1)
-        else
-          p
+
+  let varname_concat ?(hyphen='_') p s =
+    let what = String.make 1 hyphen in
+    let p =
+      try
+        OASISString.strip_ends_with ~what p
+      with Not_found ->
+        p
     in
-    let s = 
-      let s_len =
-        String.length s
-      in
-        if s_len > 0 && s.[0] = hyphen then
-          String.sub s 1 (s_len - 1)
-        else
-          s
+    let s =
+      try
+        OASISString.strip_starts_with ~what s
+      with Not_found ->
+        s
     in
-      Printf.sprintf "%s%c%s" p hyphen s
-  
-  
-  let is_varname str = 
+      p^what^s
+
+
+  let is_varname str =
     str = varname_of_string str
-  
-  let failwithf1 fmt a =
-    failwith (Printf.sprintf fmt a)
-  
-  let failwithf2 fmt a b =
-    failwith (Printf.sprintf fmt a b)
-  
-  let failwithf3 fmt a b c =
-    failwith (Printf.sprintf fmt a b c)
-  
-  let failwithf4 fmt a b c d =
-    failwith (Printf.sprintf fmt a b c d)
-  
-  let failwithf5 fmt a b c d e =
-    failwith (Printf.sprintf fmt a b c d e)
-  
+
+  let failwithf fmt = Printf.ksprintf failwith fmt
+
 end
 
 module PropList = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/PropList.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/PropList.ml" *)
+
   open OASISGettext
-  
+
   type name = string
-  
-  exception Not_set of name * string option 
+
+  exception Not_set of name * string option
   exception No_printer of name
   exception Unknown_field of name * name
-  
-  let string_of_exception =
-    function
-      | Not_set (nm, Some rsn) ->
-          Printf.sprintf (f_ "Field '%s' is not set: %s") nm rsn
-      | Not_set (nm, None) ->
-          Printf.sprintf (f_ "Field '%s' is not set") nm
-      | No_printer nm ->
-          Printf.sprintf (f_ "No default printer for value %s") nm
-      | Unknown_field (nm, schm) ->
-          Printf.sprintf (f_ "Field %s is not defined in schema %s") nm schm
-      | e ->
-          raise e
-  
+
+  let () =
+    Printexc.register_printer
+      (function
+         | Not_set (nm, Some rsn) ->
+             Some 
+               (Printf.sprintf (f_ "Field '%s' is not set: %s") nm rsn)
+         | Not_set (nm, None) ->
+             Some 
+               (Printf.sprintf (f_ "Field '%s' is not set") nm)
+         | No_printer nm ->
+             Some
+               (Printf.sprintf (f_ "No default printer for value %s") nm)
+         | Unknown_field (nm, schm) ->
+             Some 
+               (Printf.sprintf (f_ "Field %s is not defined in schema %s") nm schm)
+         | _ ->
+             None)
+
   module Data =
   struct
-  
-    type t = 
+
+    type t =
         (name, unit -> unit) Hashtbl.t
-  
+
     let create () =
       Hashtbl.create 13
-  
+
     let clear t =
       Hashtbl.clear t
-  
-# 59 "/home/gildor/programmation/oasis/src/oasis/PropList.ml"
+
+(* # 71 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/PropList.ml" *)
   end
-  
-  module Schema = 
+
+  module Schema =
   struct
-  
+
     type ('ctxt, 'extra) value =
         {
           get:   Data.t -> string;
           help:  (unit -> string) option;
           extra: 'extra;
         }
-  
+
     type ('ctxt, 'extra) t =
         {
           name:      name;
           order:     name Queue.t;
           name_norm: string -> string;
         }
-  
-    let create ?(case_insensitive=false) nm = 
+
+    let create ?(case_insensitive=false) nm =
       {
         name      = nm;
         fields    = Hashtbl.create 13;
         order     = Queue.create ();
-        name_norm = 
-          (if case_insensitive then 
+        name_norm =
+          (if case_insensitive then
              String.lowercase
            else
              fun s -> s);
       }
-  
-    let add t nm set get extra help = 
-      let key = 
+
+    let add t nm set get extra help =
+      let key =
         t.name_norm nm
       in
-  
+
         if Hashtbl.mem t.fields key then
           failwith
-            (Printf.sprintf 
+            (Printf.sprintf
                (f_ "Field '%s' is already defined in schema '%s'")
                nm t.name);
-        Hashtbl.add 
-          t.fields 
-          key 
+        Hashtbl.add
+          t.fields
+          key
           {
-            set   = set; 
-            get   = get; 
+            set   = set;
+            get   = get;
             help  = help;
             extra = extra;
           };
-        Queue.add nm t.order 
-  
+        Queue.add nm t.order
+
     let mem t nm =
-      Hashtbl.mem t.fields nm 
-  
-    let find t nm = 
+      Hashtbl.mem t.fields nm
+
+    let find t nm =
       try
         Hashtbl.find t.fields (t.name_norm nm)
       with Not_found ->
         raise (Unknown_field (nm, t.name))
-  
+
     let get t data nm =
       (find t nm).get data
-  
+
     let set t data nm ?context x =
-      (find t nm).set 
-        data 
-        ?context 
+      (find t nm).set
+        data
+        ?context
         x
-  
+
     let fold f acc t =
-      Queue.fold 
+      Queue.fold
         (fun acc k ->
            let v =
              find t k
            in
              f acc k v.extra v.help)
-        acc 
+        acc
         t.order
-  
+
     let iter f t =
-      fold 
+      fold
         (fun () -> f)
         ()
         t
-  
-    let name t = 
+
+    let name t =
       t.name
   end
-  
+
   module Field =
   struct
-  
+
     type ('ctxt, 'value, 'extra) t =
         {
           set:    Data.t -> ?context:'ctxt -> 'value -> unit;
           help:   (unit -> string) option;
           extra:  'extra;
         }
-  
-    let new_id = 
+
+    let new_id =
       let last_id =
         ref 0
       in
         fun () -> incr last_id; !last_id
-  
+
     let create ?schema ?name ?parse ?print ?default ?update ?help extra =
       (* Default value container *)
-      let v = 
-        ref None 
+      let v =
+        ref None
       in
-  
+
       (* If name is not given, create unique one *)
-      let nm = 
-        match name with 
+      let nm =
+        match name with
           | Some s -> s
           | None -> Printf.sprintf "_anon_%d" (new_id ())
       in
-  
+
       (* Last chance to get a value: the default *)
-      let default () = 
-        match default with 
+      let default () =
+        match default with
           | Some d -> d
           | None -> raise (Not_set (nm, Some (s_ "no default value")))
       in
-  
+
       (* Get data *)
       let get data =
         (* Get value *)
-        try 
+        try
           (Hashtbl.find data nm) ();
-          match !v with 
-            | Some x -> x 
+          match !v with
+            | Some x -> x
             | None -> default ()
         with Not_found ->
           default ()
       in
-  
+
       (* Set data *)
-      let set data ?context x = 
-        let x = 
-          match update with 
+      let set data ?context x =
+        let x =
+          match update with
             | Some f ->
                 begin
-                  try 
+                  try
                     f ?context (get data) x
                   with Not_set _ ->
                     x
             | None ->
                 x
         in
-          Hashtbl.replace 
-            data 
-            nm 
-            (fun () -> v := Some x) 
+          Hashtbl.replace
+            data
+            nm
+            (fun () -> v := Some x)
       in
-  
+
       (* Parse string value, if possible *)
       let parse =
-        match parse with 
-          | Some f -> 
+        match parse with
+          | Some f ->
               f
           | None ->
               fun ?context s ->
-                failwith 
-                  (Printf.sprintf 
+                failwith
+                  (Printf.sprintf
                      (f_ "Cannot parse field '%s' when setting value %S")
                      nm
                      s)
       in
-  
+
       (* Set data, from string *)
       let sets data ?context s =
         set ?context data (parse ?context s)
       in
-  
+
       (* Output value as string, if possible *)
       let print =
         match print with
           | None ->
               fun _ -> raise (No_printer nm)
       in
-  
+
       (* Get data, as a string *)
       let gets data =
         print (get data)
       in
-  
-        begin 
-          match schema with 
+
+        begin
+          match schema with
             | Some t ->
                 Schema.add t nm sets gets extra help
             | None ->
                 ()
         end;
-  
+
         {
           set   = set;
           get   = get;
           help  = help;
           extra = extra;
         }
-  
-    let fset data t ?context x = 
+
+    let fset data t ?context x =
       t.set data ?context x
-  
+
     let fget data t =
       t.get data
-  
+
     let fsets data t ?context s =
       t.sets data ?context s
-  
+
     let fgets data t =
-      t.gets data 
-  
+      t.gets data
+
   end
-  
+
   module FieldRO =
   struct
-  
+
     let create ?schema ?name ?parse ?print ?default ?update ?help extra =
-      let fld = 
+      let fld =
         Field.create ?schema ?name ?parse ?print ?default ?update ?help extra
       in
         fun data -> Field.fget data fld
-  
+
   end
 end
 
 module OASISMessage = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISMessage.ml"
-  
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISMessage.ml" *)
+
+
   open OASISGettext
   open OASISContext
-  
+
   let generic_message ~ctxt lvl fmt =
-    let cond = 
-      match lvl with 
-        | `Debug -> ctxt.debug
-        | _ -> ctxt.verbose
+    let cond =
+      if ctxt.quiet then
+        false
+      else
+        match lvl with
+          | `Debug -> ctxt.debug
+          | `Info  -> ctxt.info
+          | _ -> true
     in
-      Printf.ksprintf 
-        (fun str -> 
+      Printf.ksprintf
+        (fun str ->
            if cond then
              begin
                ctxt.printf lvl str
              end)
         fmt
-  
+
   let debug ~ctxt fmt =
     generic_message ~ctxt `Debug fmt
-  
-  let info ~ctxt fmt = 
+
+  let info ~ctxt fmt =
     generic_message ~ctxt `Info fmt
-  
+
   let warning ~ctxt fmt =
     generic_message ~ctxt `Warning fmt
-  
+
   let error ~ctxt fmt =
     generic_message ~ctxt `Error fmt
-  
-  
-  let string_of_exception e = 
-    try 
-      PropList.string_of_exception e
-    with 
-      | Failure s ->
-          s
-      | e ->
-          Printexc.to_string e
-  
-  (* TODO
-  let register_exn_printer f =
-   *)
-  
+
 end
 
 module OASISVersion = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISVersion.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISVersion.ml" *)
+
   open OASISGettext
-  
-  
-  
+
+
+
   type s = string
-  
+
   type t = string 
-  
-  type comparator = 
+
+  type comparator =
     | VGreater of t
     | VGreaterEqual of t
     | VEqual of t
     | VOr of  comparator * comparator
     | VAnd of comparator * comparator
     
-  
+
   (* Range of allowed characters *)
   let is_digit c =
     '0' <= c && c <= '9'
-  
+
   let is_alpha c =
     ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
-  
+
   let is_special =
-    function 
+    function
       | '.' | '+' | '-' | '~' -> true
       | _ -> false
-  
+
   let rec version_compare v1 v2 =
     if v1 <> "" || v2 <> "" then
       begin
-        (* Compare ascii string, using special meaning for version 
+        (* Compare ascii string, using special meaning for version
          * related char
          *)
-        let val_ascii c = 
+        let val_ascii c =
           if c = '~' then -1
           else if is_digit c then 0
           else if c = '\000' then 0
           else if is_alpha c then Char.code c
           else (Char.code c) + 256
         in
-  
+
         let len1 = String.length v1 in
         let len2 = String.length v2 in
-  
+
         let p = ref 0 in
-  
+
         (** Compare ascii part *)
-        let compare_vascii () = 
+        let compare_vascii () =
           let cmp = ref 0 in
-          while !cmp = 0 && 
-                !p < len1 && !p < len2 && 
-                not (is_digit v1.[!p] && is_digit v2.[!p]) do 
+          while !cmp = 0 &&
+                !p < len1 && !p < len2 &&
+                not (is_digit v1.[!p] && is_digit v2.[!p]) do
             cmp := (val_ascii v1.[!p]) - (val_ascii v2.[!p]);
             incr p
           done;
           if !cmp = 0 && !p < len1 && !p = len2 then
-            val_ascii v1.[!p] 
+            val_ascii v1.[!p]
           else if !cmp = 0 && !p = len1 && !p < len2 then
             - (val_ascii v2.[!p])
           else
             !cmp
         in
-  
+
         (** Compare digit part *)
-        let compare_digit () = 
+        let compare_digit () =
           let extract_int v p =
             let start_p = !p in
-              while !p < String.length v && is_digit v.[!p] do 
+              while !p < String.length v && is_digit v.[!p] do
                 incr p
               done;
-              match String.sub v start_p (!p - start_p) with 
-                | "" -> 0, 
-                        v
-                | s -> int_of_string s, 
-                       String.sub v !p ((String.length v) - !p)
+              let substr = 
+                String.sub v !p ((String.length v) - !p)
+              in 
+              let res = 
+                match String.sub v start_p (!p - start_p) with 
+                  | "" -> 0
+                  | s -> int_of_string s
+              in
+                res, substr
           in
           let i1, tl1 = extract_int v1 (ref !p) in
           let i2, tl2 = extract_int v2 (ref !p) in
             i1 - i2, tl1, tl2
         in
-  
+
           match compare_vascii () with
             | 0 ->
                 begin
-                  match compare_digit () with 
+                  match compare_digit () with
                     | 0, tl1, tl2 ->
                         if tl1 <> "" && is_digit tl1.[0] then
                           1
       begin
         0
       end
-  
-  
-  let version_of_string str =
-    String.iter 
-      (fun c ->
-         if is_alpha c || is_digit c || is_special c then
-           ()
-         else
-           failwith
-             (Printf.sprintf 
-                (f_ "Char %C is not allowed in version '%s'")
-                c str))
-      str;
-    str
-  
-  let string_of_version t =
-    t
-  
-  let chop t = 
-    try 
-      let pos = 
-        String.rindex t '.' 
+
+
+  let version_of_string str = str
+
+  let string_of_version t = t
+
+  let chop t =
+    try
+      let pos =
+        String.rindex t '.'
       in
         String.sub t 0 pos
     with Not_found ->
       t
-  
+
   let rec comparator_apply v op =
     match op with
       | VGreater cv ->
           (comparator_apply v op1) || (comparator_apply v op2)
       | VAnd (op1, op2) ->
           (comparator_apply v op1) && (comparator_apply v op2)
-  
+
   let rec string_of_comparator =
-    function 
+    function
       | VGreater v  -> "> "^(string_of_version v)
       | VEqual v    -> "= "^(string_of_version v)
       | VLesser v   -> "< "^(string_of_version v)
       | VGreaterEqual v -> ">= "^(string_of_version v)
       | VLesserEqual v  -> "<= "^(string_of_version v)
-      | VOr (c1, c2)  -> 
+      | VOr (c1, c2)  ->
           (string_of_comparator c1)^" || "^(string_of_comparator c2)
-      | VAnd (c1, c2) -> 
+      | VAnd (c1, c2) ->
           (string_of_comparator c1)^" && "^(string_of_comparator c2)
-  
+
   let rec varname_of_comparator =
-    let concat p v = 
+    let concat p v =
       OASISUtils.varname_concat
-        p 
-        (OASISUtils.varname_of_string 
+        p
+        (OASISUtils.varname_of_string
            (string_of_version v))
     in
-      function 
+      function
         | VGreater v -> concat "gt" v
         | VLesser v  -> concat "lt" v
         | VEqual v   -> concat "eq" v
             (varname_of_comparator c1)^"_or_"^(varname_of_comparator c2)
         | VAnd (c1, c2) ->
             (varname_of_comparator c1)^"_and_"^(varname_of_comparator c2)
-  
+
+  let version_0_3_or_after t =
+    comparator_apply t (VGreaterEqual (string_of_version "0.3"))
+
 end
 
 module OASISLicense = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISLicense.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISLicense.ml" *)
+
   (** License for _oasis fields
       @author Sylvain Le Gall
     *)
-  
-  
-  
+
+
+
   type license = string 
-  
+
   type license_exception = string 
-  
-  type license_version = 
+
+  type license_version =
     | Version of OASISVersion.t
     | VersionOrLater of OASISVersion.t
     | NoVersion
     
-  
-  type license_dep_5 = 
-      {
-        license:    license;
-        exceptions: license_exception list;
-        version:    license_version;
-      } 
-  
+
+  type license_dep_5_unit =
+    {
+      license:   license;
+      excption:  license_exception option;
+      version:   license_version;
+    }
+    
+
+  type license_dep_5 =
+    | DEP5Unit of license_dep_5_unit
+    | DEP5Or of license_dep_5 list
+    | DEP5And of license_dep_5 list
+    
+
   type t =
     | DEP5License of license_dep_5
     | OtherLicense of string (* URL *)
     
-  
+
 end
 
 module OASISExpr = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISExpr.ml"
-  
-  
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISExpr.ml" *)
+
+
+
   open OASISGettext
-  
+
   type test = string 
-  
+
   type flag = string 
-  
+
   type t =
     | EBool of bool
     | ENot of t
     | EFlag of flag
     | ETest of test * string
     
-  
+
   type 'a choices = (t * 'a) list 
-  
+
   let eval var_get t =
-    let rec eval' = 
+    let rec eval' =
       function
         | EBool b ->
             b
-  
-        | ENot e -> 
+
+        | ENot e ->
             not (eval' e)
-  
+
         | EAnd (e1, e2) ->
             (eval' e1) && (eval' e2)
-  
-        | EOr (e1, e2) -> 
+
+        | EOr (e1, e2) ->
             (eval' e1) || (eval' e2)
-  
+
         | EFlag nm ->
             let v =
               var_get nm
             in
               assert(v = "true" || v = "false");
               (v = "true")
-  
+
         | ETest (nm, vl) ->
             let v =
               var_get nm
               (v = vl)
     in
       eval' t
-  
+
   let choose ?printer ?name var_get lst =
-    let rec choose_aux = 
+    let rec choose_aux =
       function
         | (cond, vl) :: tl ->
-            if eval var_get cond then 
-              vl 
+            if eval var_get cond then
+              vl
             else
               choose_aux tl
         | [] ->
-            let str_lst = 
+            let str_lst =
               if lst = [] then
                 s_ "<empty>"
               else
-                String.concat 
+                String.concat
                   (s_ ", ")
                   (List.map
                      (fun (cond, vl) ->
                           | None -> s_ "<no printer>")
                      lst)
             in
-              match name with 
+              match name with
                 | Some nm ->
                     failwith
-                      (Printf.sprintf 
+                      (Printf.sprintf
                          (f_ "No result for the choice list '%s': %s")
                          nm str_lst)
                 | None ->
                          str_lst)
     in
       choose_aux (List.rev lst)
-  
+
 end
 
 module OASISTypes = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISTypes.ml"
-  
-  
-  
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISTypes.ml" *)
+
+
+
+
   type name          = string 
   type package_name  = string 
   type url           = string 
   type arg           = string 
   type args          = string list 
   type command_line  = (prog * arg list) 
-  
+
   type findlib_name = string 
   type findlib_full = string 
-  
+
   type compiled_object =
     | Byte
     | Native
     | Best
     
-  
-  type dependency = 
+
+  type dependency =
     | FindlibPackage of findlib_full * OASISVersion.comparator option
     | InternalLibrary of name
     
-  
+
   type tool =
     | ExternalTool of name
-    | InternalExecutable of name 
+    | InternalExecutable of name
     
-  
-  type vcs = 
-    | Darcs 
-    | Git 
-    | Svn 
-    | Cvs 
-    | Hg 
-    | Bzr 
-    | Arch 
+
+  type vcs =
+    | Darcs
+    | Git
+    | Svn
+    | Cvs
+    | Hg
+    | Bzr
+    | Arch
     | Monotone
     | OtherVCS of url
     
-  
-  type plugin_kind = 
-      [  `Configure 
-       | `Build 
-       | `Doc 
-       | `Test 
-       | `Install 
+
+  type plugin_kind =
+      [  `Configure
+       | `Build
+       | `Doc
+       | `Test
+       | `Install
        | `Extra
       ]
-  
+
   type plugin_data_purpose =
       [  `Configure
        | `Build
        | `Extra
        | `Other of string
       ]
-  
+
   type 'a plugin = 'a * name * OASISVersion.t option 
-  
-  type all_plugin = plugin_kind plugin 
-  
+
+  type all_plugin = plugin_kind plugin
+
   type plugin_data = (all_plugin * plugin_data_purpose * (unit -> unit)) list
-  
-# 102 "/home/gildor/programmation/oasis/src/oasis/OASISTypes.ml"
-  
+
+(* # 102 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISTypes.ml" *)
+
   type 'a conditional = 'a OASISExpr.choices 
-  
-  type custom = 
+
+  type custom =
       {
         pre_command:  (command_line option) conditional;
-        post_command: (command_line option) conditional; 
+        post_command: (command_line option) conditional;
       }
       
-  
+
   type common_section =
       {
         cs_name: name;
         cs_plugin_data: plugin_data;
       }
       
-  
+
   type build_section =
       {
         bs_build:           bool conditional;
         bs_nativeopt:       args conditional;
       }
       
-  
-  type library = 
+
+  type library =
       {
         lib_modules:            string list;
+        lib_pack:               bool;
         lib_internal_modules:   string list;
         lib_findlib_parent:     findlib_name option;
         lib_findlib_name:       findlib_name option;
         lib_findlib_containers: findlib_name list;
       } 
-  
-  type executable = 
+
+  type executable =
       {
         exec_custom:          bool;
         exec_main_is:         unix_filename;
       } 
-  
-  type flag = 
+
+  type flag =
       {
         flag_description:  string option;
         flag_default:      bool conditional;
       } 
-  
-  type source_repository = 
+
+  type source_repository =
       {
         src_repo_type:        vcs;
         src_repo_location:    url;
         src_repo_tag:         string option;
         src_repo_subdir:      unix_filename option;
       } 
-  
-  type test = 
+
+  type test =
       {
         test_type:               [`Test] plugin;
         test_command:            command_line conditional;
         test_run:                bool conditional;
         test_tools:              tool list;
       } 
-  
+
   type doc_format =
     | HTML of unix_filename
     | DocText
     | DVI
     | OtherDoc
     
-  
+
   type doc =
       {
         doc_type:        [`Doc] plugin;
         doc_data_files:  (unix_filename * unix_filename option) list;
         doc_build_tools: tool list;
       } 
-  
+
   type section =
     | Library    of common_section * build_section * library
     | Executable of common_section * build_section * executable
     | Test       of common_section * test
     | Doc        of common_section * doc
     
-  
+
+  type section_kind =
+      [ `Library | `Executable | `Flag | `SrcRepo | `Test | `Doc ]
+
   type package = 
       {
         oasis_version:    OASISVersion.t;
         synopsis:         string;
         description:      string option;
         categories:       url list;
-  
+
         conf_type:        [`Configure] plugin;
         conf_custom:      custom;
-  
+
         build_type:       [`Build] plugin;
         build_custom:     custom;
-  
+
         install_type:     [`Install] plugin;
         install_custom:   custom;
         uninstall_custom: custom;
-  
+
         clean_custom:     custom;
         distclean_custom: custom;
-  
+
         files_ab:         unix_filename list;
         sections:         section list;
         plugins:          [`Extra] plugin list;
         schema_data:      PropList.Data.t;
         plugin_data:      plugin_data;
       } 
-  
+
 end
 
 module OASISUnixPath = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISUnixPath.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISUnixPath.ml" *)
+
   type unix_filename = string
   type unix_dirname = string
-  
+
   type host_filename = string
   type host_dirname = string
-  
+
   let current_dir_name = "."
-  
+
   let parent_dir_name = ".."
-  
-  let concat f1 f2 = 
-    if f1 = current_dir_name then
+
+  let is_current_dir fn =
+    fn = current_dir_name || fn = ""
+
+  let concat f1 f2 =
+    if is_current_dir f1 then
       f2
-    else if f2 = current_dir_name then
-      f1
     else
-      f1^"/"^f2
-  
+      let f1' =
+        try OASISString.strip_ends_with ~what:"/" f1 with Not_found -> f1
+      in
+        f1'^"/"^f2
+
   let make =
     function
       | hd :: tl ->
             tl
       | [] ->
           invalid_arg "OASISUnixPath.make"
-  
+
   let dirname f =
     try
       String.sub f 0 (String.rindex f '/')
     with Not_found ->
       current_dir_name
-  
+
   let basename f =
-    try 
+    try
       let pos_start =
         (String.rindex f '/') + 1
       in
         String.sub f pos_start ((String.length f) - pos_start)
     with Not_found ->
       f
-  
+
   let chop_extension f =
-    try 
+    try
       let last_dot =
         String.rindex f '.'
       in
       let sub =
         String.sub f 0 last_dot
       in
-        try 
+        try
           let last_slash =
             String.rindex f '/'
           in
               f
         with Not_found ->
           sub
-  
+
     with Not_found ->
       f
-  
+
+  let capitalize_file f =
+    let dir = dirname f in
+    let base = basename f in
+    concat dir (String.capitalize base)
+
+  let uncapitalize_file f =
+    let dir = dirname f in
+    let base = basename f in
+    concat dir (String.uncapitalize base)
+
 end
 
+module OASISHostPath = struct
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISHostPath.ml" *)
+
+
+  open Filename
+
+  module Unix = OASISUnixPath
+
+  let make =
+    function
+      | [] ->
+          invalid_arg "OASISHostPath.make"
+      | hd :: tl ->
+          List.fold_left Filename.concat hd tl
+
+  let of_unix ufn =
+    if Sys.os_type = "Unix" then
+      ufn
+    else
+      make
+        (List.map
+           (fun p ->
+              if p = Unix.current_dir_name then
+                current_dir_name
+              else if p = Unix.parent_dir_name then
+                parent_dir_name
+              else
+                p)
+           (OASISString.nsplit ufn '/'))
+
+
+end
+
 module OASISSection = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISSection.ml"
-  
-  (** Manipulate section 
-      @author Sylvain Le Gall
-    *)
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISSection.ml" *)
+
   open OASISTypes
-  
-  type section_kind =
-    | KLibrary 
-    | KExecutable
-    | KFlag
-    | KSrcRepo
-    | KTest
-    | KDoc
-  
-  (** Extract generic information 
-    *)
+
   let section_kind_common = 
     function
       | Library (cs, _, _) -> 
-          KLibrary, cs
+          `Library, cs
       | Executable (cs, _, _) ->
-          KExecutable, cs
+          `Executable, cs
       | Flag (cs, _) ->
-          KFlag, cs
+          `Flag, cs
       | SrcRepo (cs, _) ->
-          KSrcRepo, cs
+          `SrcRepo, cs
       | Test (cs, _) ->
-          KTest, cs
+          `Test, cs
       | Doc (cs, _) ->
-          KDoc, cs
-  
-  (** Common section of a section
-    *)
+          `Doc, cs
+
   let section_common sct =
     snd (section_kind_common sct)
-  
+
+  let section_common_set cs =
+    function
+      | Library (_, bs, lib)     -> Library (cs, bs, lib)
+      | Executable (_, bs, exec) -> Executable (cs, bs, exec)
+      | Flag (_, flg)            -> Flag (cs, flg)
+      | SrcRepo (_, src_repo)    -> SrcRepo (cs, src_repo)
+      | Test (_, tst)            -> Test (cs, tst)
+      | Doc (_, doc)             -> Doc (cs, doc)
+
   (** Key used to identify section
     *)
   let section_id sct = 
       section_kind_common sct
     in
       k, cs.cs_name
-  
+
   let string_of_section sct =
     let k, nm =
       section_id sct
     in
       (match k with
-         | KLibrary    -> "library" 
-         | KExecutable -> "executable"
-         | KFlag       -> "flag"
-         | KSrcRepo    -> "src repository"
-         | KTest       -> "test"
-         | KDoc        -> "doc")
+         | `Library    -> "library" 
+         | `Executable -> "executable"
+         | `Flag       -> "flag"
+         | `SrcRepo    -> "src repository"
+         | `Test       -> "test"
+         | `Doc        -> "doc")
       ^" "^nm
-  
+
+  let section_find id scts =
+    List.find
+      (fun sct -> id = section_id sct)
+      scts
+
+  module CSection =
+  struct
+    type t = section
+
+    let id = section_id
+
+    let compare t1 t2 = 
+      compare (id t1) (id t2)
+      
+    let equal t1 t2 =
+      (id t1) = (id t2)
+
+    let hash t =
+      Hashtbl.hash (id t)
+  end
+
+  module MapSection = Map.Make(CSection)
+  module SetSection = Set.Make(CSection)
+
 end
 
 module OASISBuildSection = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISBuildSection.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISBuildSection.ml" *)
+
 end
 
 module OASISExecutable = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISExecutable.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISExecutable.ml" *)
+
   open OASISTypes
-  
+
   let unix_exec_is (cs, bs, exec) is_native ext_dll suffix_program = 
     let dir = 
       OASISUnixPath.concat
         | Best -> is_native ()
         | Byte -> false
     in
-  
+
       OASISUnixPath.concat
         dir
         (cs.cs_name^(suffix_program ())),
-  
+
       if not is_native_exec && 
          not exec.exec_custom && 
          bs.bs_c_sources <> [] then
-        Some (dir^"/dll"^cs.cs_name^(ext_dll ()))
+        Some (dir^"/dll"^cs.cs_name^"_stubs"^(ext_dll ()))
       else
         None
-  
+
 end
 
 module OASISLibrary = struct
-# 21 "/home/gildor/programmation/oasis/src/oasis/OASISLibrary.ml"
-  
+(* # 21 "/home/jun/.share/projects/externals/oasis/_build/src/oasis/OASISLibrary.ml" *)
+
   open OASISTypes
   open OASISUtils
   open OASISGettext
-  
+  open OASISSection
+
   type library_name = name
-  
-  let generated_unix_files ~ctxt (cs, bs, lib) 
-        source_file_exists is_native ext_lib ext_dll =  
+  type findlib_part_name = name
+  type 'a map_of_findlib_part_name = 'a OASISUtils.MapString.t
+
+  exception InternalLibraryNotFound of library_name
+  exception FindlibPackageNotFound of findlib_name
+
+  type group_t =
+    | Container of findlib_name * group_t list
+    | Package of (findlib_name *
+                  common_section *
+                  build_section *
+                  library *
+                  group_t list)
+
+  (* Look for a module file, considering capitalization or not. *)
+  let find_module source_file_exists (cs, bs, lib) modul =
+    let possible_base_fn =
+      List.map
+        (OASISUnixPath.concat bs.bs_path)
+        [modul;
+         OASISUnixPath.uncapitalize_file modul;
+         OASISUnixPath.capitalize_file modul]
+    in
+      (* TODO: we should be able to be able to determine the source for every
+       * files. Hence we should introduce a Module(source: fn) for the fields
+       * Modules and InternalModules
+       *)
+      List.fold_left
+        (fun acc base_fn ->
+           match acc with
+             | `No_sources _ ->
+                 begin
+                   let file_found =
+                     List.fold_left
+                       (fun acc ext ->
+                          if source_file_exists (base_fn^ext) then
+                            (base_fn^ext) :: acc
+                          else
+                            acc)
+                       []
+                       [".ml"; ".mli"; ".mll"; ".mly"]
+                   in
+                     match file_found with
+                       | [] ->
+                           acc
+                       | lst ->
+                           `Sources (base_fn, lst)
+                 end
+             | `Sources _ ->
+                 acc)
+        (`No_sources possible_base_fn)
+        possible_base_fn
+
+  let source_unix_files ~ctxt (cs, bs, lib) source_file_exists =
+    List.fold_left
+      (fun acc modul ->
+         match find_module source_file_exists (cs, bs, lib) modul with
+           | `Sources (base_fn, lst) ->
+               (base_fn, lst) :: acc
+           | `No_sources _ ->
+               OASISMessage.warning
+                 ~ctxt
+                 (f_ "Cannot find source file matching \
+                      module '%s' in library %s")
+                 modul cs.cs_name;
+               acc)
+      []
+      (lib.lib_modules @ lib.lib_internal_modules)
+
+  let generated_unix_files
+        ~ctxt
+        ~is_native
+        ~has_native_dynlink
+        ~ext_lib
+        ~ext_dll
+        ~source_file_exists
+        (cs, bs, lib) =
+
+    let find_modules lst ext = 
+      let find_module modul =
+        match find_module source_file_exists (cs, bs, lib) modul with
+          | `Sources (base_fn, _) ->
+              [base_fn]
+          | `No_sources lst ->
+              OASISMessage.warning
+                ~ctxt
+                (f_ "Cannot find source file matching \
+                     module '%s' in library %s")
+                modul cs.cs_name;
+              lst
+      in
+      List.map 
+        (fun nm -> 
+           List.map 
+             (fun base_fn -> base_fn ^"."^ext)
+             (find_module nm))
+        lst
+    in
+
     (* The headers that should be compiled along *)
-    let headers = 
-      List.fold_left
-        (fun hdrs modul ->
-           try 
-             let base_fn = 
-               List.find
-                 (fun fn -> 
-                    source_file_exists (fn^".ml") ||
-                    source_file_exists (fn^".mli") ||
-                    source_file_exists (fn^".mll") ||
-                    source_file_exists (fn^".mly")) 
-                 (List.map
-                    (OASISUnixPath.concat bs.bs_path)
-                    [modul;
-                     String.uncapitalize modul;
-                     String.capitalize modul])
-             in
-               [base_fn^".cmi"] :: hdrs
-           with Not_found ->
-             OASISMessage.warning
-               ~ctxt
-               (f_ "Cannot find source file matching \
-                    module '%s' in library %s")
-               modul cs.cs_name;
-               (List.map (OASISUnixPath.concat bs.bs_path)
-                  [modul^".cmi";
-                   String.uncapitalize modul ^ ".cmi";
-                   String.capitalize modul ^ ".cmi"])
-               :: hdrs)
+    let headers =
+      if lib.lib_pack then
         []
-        lib.lib_modules
+      else
+        find_modules
+          lib.lib_modules
+          "cmi"
     in
-  
+
+    (* The .cmx that be compiled along *)
+    let cmxs =
+      let should_be_built =
+        (not lib.lib_pack) && (* Do not install .cmx packed submodules *)
+        match bs.bs_compiled_object with
+          | Native -> true
+          | Best -> is_native
+          | Byte -> false
+      in
+        if should_be_built then
+          find_modules
+            (lib.lib_modules @ lib.lib_internal_modules)
+            "cmx"
+        else
+          []
+    in
+
     let acc_nopath =
       []
     in
-  
+
     (* Compute what libraries should be built *)
     let acc_nopath =
+      (* Add the packed header file if required *)
+      let add_pack_header acc =
+        if lib.lib_pack then
+          [cs.cs_name^".cmi"] :: acc
+        else
+          acc
+      in
       let byte acc =
-        [cs.cs_name^".cma"] :: acc
+        add_pack_header ([cs.cs_name^".cma"] :: acc)
       in
       let native acc =
-        [cs.cs_name^".cmxa"] :: [cs.cs_name^(ext_lib ())] :: acc
+        let acc = 
+          add_pack_header
+            (if has_native_dynlink then
+               [cs.cs_name^".cmxs"] :: acc
+             else acc)
+        in
+          [cs.cs_name^".cmxa"] :: [cs.cs_name^ext_lib] :: acc
       in
-        match bs.bs_compiled_object with 
+        match bs.bs_compiled_object with
           | Native ->
               byte (native acc_nopath)
-          | Best when is_native () ->
+          | Best when is_native ->
               byte (native acc_nopath)
           | Byte | Best ->
               byte acc_nopath
     in
-  
+
     (* Add C library to be built *)
-    let acc_nopath = 
+    let acc_nopath =
       if bs.bs_c_sources <> [] then
         begin
-          ["lib"^cs.cs_name^(ext_lib ())]
+          ["lib"^cs.cs_name^"_stubs"^ext_lib]
           ::
-          ["dll"^cs.cs_name^(ext_dll ())]
+          ["dll"^cs.cs_name^"_stubs"^ext_dll]
           ::
           acc_nopath
         end
       else
         acc_nopath
     in
-  
+
       (* All the files generated *)
       List.rev_append
         (List.rev_map
            (List.rev_map
               (OASISUnixPath.concat bs.bs_path))
            acc_nopath)
-        headers
-  
-  
-  type group_t = 
-    | Container of findlib_name * (group_t list)
-    | Package of (findlib_name * 
-                  common_section *
-                  build_section * 
-                  library * 
-                  (group_t list))
-  
-  let group_libs pkg =
-    (** Associate a name with its children *)
-    let children =
+        (headers @ cmxs)
+
+  type data = common_section * build_section * library
+  type tree =
+    | Node of (data option) * (tree MapString.t)
+    | Leaf of data
+
+  let findlib_mapping pkg =
+    (* Map from library name to either full findlib name or parts + parent. *)
+    let fndlb_parts_of_lib_name =
+      let fndlb_parts cs lib =
+        let name =
+          match lib.lib_findlib_name with
+            | Some nm -> nm
+            | None -> cs.cs_name
+        in
+        let name =
+          String.concat "." (lib.lib_findlib_containers @ [name])
+        in
+          name
+      in
+        List.fold_left
+          (fun mp ->
+             function
+               | Library (cs, _, lib) ->
+                   begin
+                     let lib_name = cs.cs_name in
+                     let fndlb_parts = fndlb_parts cs lib in
+                       if MapString.mem lib_name mp then
+                         failwithf
+                           (f_ "The library name '%s' is used more than once.")
+                           lib_name;
+                       match lib.lib_findlib_parent with
+                         | Some lib_name_parent ->
+                             MapString.add
+                               lib_name
+                               (`Unsolved (lib_name_parent, fndlb_parts))
+                               mp
+                         | None ->
+                             MapString.add
+                               lib_name
+                               (`Solved fndlb_parts)
+                               mp
+                   end
+
+               | Executable _ | Test _ | Flag _ | SrcRepo _ | Doc _ ->
+                   mp)
+          MapString.empty
+          pkg.sections
+    in
+
+    (* Solve the above graph to be only library name to full findlib name. *)
+    let fndlb_name_of_lib_name =
+      let rec solve visited mp lib_name lib_name_child =
+        if SetString.mem lib_name visited then
+          failwithf
+            (f_ "Library '%s' is involved in a cycle \
+                 with regard to findlib naming.")
+            lib_name;
+        let visited = SetString.add lib_name visited in
+          try
+            match MapString.find lib_name mp with
+              | `Solved fndlb_nm ->
+                  fndlb_nm, mp
+              | `Unsolved (lib_nm_parent, post_fndlb_nm) ->
+                  let pre_fndlb_nm, mp =
+                    solve visited mp lib_nm_parent lib_name
+                  in
+                  let fndlb_nm = pre_fndlb_nm^"."^post_fndlb_nm in
+                    fndlb_nm, MapString.add lib_name (`Solved fndlb_nm) mp
+          with Not_found ->
+            failwithf
+              (f_ "Library '%s', which is defined as the findlib parent of \
+                   library '%s', doesn't exist.")
+              lib_name lib_name_child
+      in
+      let mp =
+        MapString.fold
+          (fun lib_name status mp ->
+             match status with
+               | `Solved _ ->
+                   (* Solved initialy, no need to go further *)
+                   mp
+               | `Unsolved _ ->
+                   let _, mp = solve SetString.empty mp lib_name "<none>" in
+                     mp)
+          fndlb_parts_of_lib_name
+          fndlb_parts_of_lib_name
+      in
+        MapString.map
+          (function
+             | `Solved fndlb_nm -> fndlb_nm
+             | `Unsolved _ -> assert false)
+          mp
+    in
+
+    (* Convert an internal library name to a findlib name. *)
+    let findlib_name_of_library_name lib_nm =
+      try
+        MapString.find lib_nm fndlb_name_of_lib_name
+      with Not_found ->
+        raise (InternalLibraryNotFound lib_nm)
+    in
+
+    (* Add a library to the tree.
+     *)
+    let add sct mp =
+      let fndlb_fullname =
+        let cs, _, _ = sct in
+        let lib_name = cs.cs_name in
+          findlib_name_of_library_name lib_name
+      in
+      let rec add_children nm_lst (children : tree MapString.t) =
+        match nm_lst with
+          | (hd :: tl) ->
+              begin
+                let node =
+                  try
+                    add_node tl (MapString.find hd children)
+                  with Not_found ->
+                    (* New node *)
+                    new_node tl
+                in
+                  MapString.add hd node children
+              end
+          | [] ->
+              (* Should not have a nameless library. *)
+              assert false
+      and add_node tl node =
+        if tl = [] then
+          begin
+            match node with
+              | Node (None, children) ->
+                  Node (Some sct, children)
+              | Leaf (cs', _, _) | Node (Some (cs', _, _), _) ->
+                  (* TODO: allow to merge Package, i.e.
+                   * archive(byte) = "foo.cma foo_init.cmo"
+                   *)
+                  let cs, _, _ = sct in
+                    failwithf
+                      (f_ "Library '%s' and '%s' have the same findlib name '%s'")
+                      cs.cs_name cs'.cs_name fndlb_fullname
+          end
+        else
+          begin
+            match node with