Commits

camlspotter  committed 6acc7b0

oasis for 2.0.0

  • Participants
  • Parent commits 92fb3c2

Comments (0)

Files changed (4)

 (* OASIS_START *)
-(* DO NOT EDIT (digest: 71b91510d384d94e9d45aac40d5f7262) *)
+(* DO NOT EDIT (digest: 079b45d945085bd110d4ccc6c59d3013) *)
 This is the INSTALL file for the spotlib distribution.
 
 This package uses OASIS to generate its build system. See section OASIS for
 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 *)
    export
 
 Subdirs()
+
+setup.ml: _oasis
+	oasis setup
 OASISFormat: 0.2
 Name:        spotlib
-Version:     1.0.1
+Version:     2.0.0
 Synopsis:    Camlspotter's personal library
 Authors:     Jun FURUSE
 License:     LGPL-2.0 with OCaml linking exception
-(* setup.ml generated for the first time by OASIS v0.2.0 *)
+(* setup.ml generated for the first time by OASIS v0.3.0 *)
 
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 81ac358217d1274e0aee039ce0b07db7) *)
+(* DO NOT EDIT (digest: 15c84f6996059536f8f719f94e0f90d3) *)
 (*
-   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"
+                   *)