$OpenBSD: patch-src_configurator_ml,v 1.3 2019/08/09 12:08:16 chrisz Exp $

don't depend on janestreet base.

Index: src/configurator.ml
--- src/configurator.ml.orig
+++ src/configurator.ml
@@ -1,13 +1,8 @@
-open Base
-open Stdio
+module Fn         = Filename
+open StdLabels
 
-module Sys        = Caml.Sys
-module Fn         = Caml.Filename
-module Arg        = Caml.Arg
-module Buffer     = Caml.Buffer
-module Pervasives = Caml.Pervasives
+module StringMap = Map.Make(String)
 
-let ( ^^ ) = Caml.( ^^ )
 let ( ^/ ) = Fn.concat
 let sprintf = Printf.sprintf
 
@@ -18,6 +13,13 @@ let die fmt =
     raise (Fatal_error s);
   ) fmt
 
+let split_lines s =
+  String.split_on_char ~sep:'\n' s |> List.map ~f:begin fun s ->
+    if s.[String.length s - 1] = '\r'
+    then String.sub s ~pos:0 ~len:(String.length s - 1)
+    else s
+  end
+
 type t =
   { name              : string
   ; dest_dir          : string
@@ -28,7 +30,7 @@ type t =
   ; c_compiler        : string
   ; stdlib_dir        : string
   ; ccomp_type        : string
-  ; ocamlc_config     : string Map.M(String).t
+  ; ocamlc_config     : string StringMap.t
   ; ocamlc_config_cmd : string
   }
 
@@ -47,7 +49,7 @@ module Temp = struct
   let prng = lazy(Random.State.make_self_init ())
 
   let gen_name ~temp_dir ~prefix ~suffix =
-    let rnd = Int.bit_and (Random.State.bits (Lazy.force prng)) 0xFFFFFF in
+    let rnd = (land) (Random.State.bits (Lazy.force prng)) 0xFFFFFF in
     temp_dir ^/ (Printf.sprintf "%s%06x%s" prefix rnd suffix)
 
   let create ~prefix ~suffix ~mk =
@@ -63,7 +65,7 @@ module Temp = struct
 
   let create_temp_dir ~prefix ~suffix =
     let dir = create ~prefix ~suffix ~mk:(fun name -> Unix.mkdir name 0o700) in
-    Caml.at_exit (fun () -> rm_rf dir);
+    at_exit (fun () -> rm_rf dir);
     dir
 end
 
@@ -76,8 +78,8 @@ module Find_in_path = struct
 
   let get_path () =
     match Sys.getenv "PATH" with
-    | exception (Not_found_s _ | Caml.Not_found) -> []
-    | s -> String.split s ~on:path_sep
+    | exception Not_found -> []
+    | s -> String.split_on_char s ~sep:path_sep
 
   let exe = if Sys.win32 then ".exe" else ""
 
@@ -96,17 +98,22 @@ module Find_in_path = struct
         None
 
   let find_ocaml_prog prog =
-    match
-      List.find_map (get_path ()) ~f:(fun dir ->
-        best_prog dir prog)
-    with
-    | None -> prog_not_found prog
-    | Some fn -> fn
+    let rec loop = function
+    | [] ->  prog_not_found prog
+    | dir :: rest ->
+        match best_prog dir prog with
+        | None -> loop rest
+        | Some fn -> fn
+    in loop (get_path ())
 
   let find prog =
-    List.find_map (get_path ()) ~f:(fun dir ->
-      let fn = dir ^/ prog ^ exe in
-      Option.some_if (Sys.file_exists fn) fn)
+    let rec loop = function
+      | [] -> None
+      | dir :: rest ->
+          let fn = dir ^/ prog ^ exe in
+          if Sys.file_exists fn
+          then Some fn else loop rest
+    in loop  (get_path ())
 end
 
 let logf t fmt = Printf.ksprintf t.log fmt
@@ -122,18 +129,8 @@ type run_result =
   ; stderr    : string
   }
 
-let quote =
-  let need_quote = function
-    | ' ' | '\"' -> true
-    | _          -> false
-  in
-  fun s ->
-    if String.is_empty s || String.exists ~f:need_quote s
-    then Fn.quote s
-    else s
-
 let command_line prog args =
-  String.concat ~sep:" " (List.map (prog :: args) ~f:quote)
+  String.concat ~sep:" " (List.map (prog :: args) ~f:Fn.quote)
 
 let run t ~dir cmd =
   logf t "run: %s" cmd;
@@ -148,20 +145,27 @@ let run t ~dir cmd =
       (Fn.quote stdout_fn)
       (Fn.quote stderr_fn)
   in
-  let stdout = In_channel.read_all stdout_fn in
-  let stderr = In_channel.read_all stderr_fn in
+  let slurp fn =
+    let chan = open_in fn in
+    let buf = Buffer.create 4096 in
+    (try Buffer.add_channel buf chan max_int with End_of_file -> ());
+    close_in chan;
+    Buffer.contents buf
+  in
+  let stdout = slurp stdout_fn in
+  let stderr = slurp stderr_fn in
   logf t "-> process exited with code %d" exit_code;
   logf t "-> stdout:";
-  List.iter (String.split_lines stdout) ~f:(logf t " | %s");
+  List.iter (split_lines stdout) ~f:(logf t " | %s");
   logf t "-> stderr:";
-  List.iter (String.split_lines stderr) ~f:(logf t " | %s");
+  List.iter (split_lines stderr) ~f:(logf t " | %s");
   { exit_code; stdout; stderr }
 
 let run_capture_exn t ~dir cmd =
   let { exit_code; stdout; stderr } = run t ~dir cmd in
   if exit_code <> 0 then
     die "command exited with code %d: %s" exit_code cmd
-  else if not (String.is_empty stderr) then
+  else if stderr <> "" then
     die "command has non-empty stderr: %s" cmd
   else
     stdout
@@ -169,11 +173,11 @@ let run_capture_exn t ~dir cmd =
 let run_ok t ~dir cmd = (run t ~dir cmd).exit_code = 0
 
 let get_ocaml_config_var_exn ~ocamlc_config_cmd map var =
-  match Map.find map var with
+  match StringMap.find_opt var map with
   | None -> die "variable %S not found in the output of `%s`" var ocamlc_config_cmd
   | Some s -> s
 
-let ocaml_config_var t var = Map.find t.ocamlc_config var
+let ocaml_config_var t var = StringMap.find_opt var t.ocamlc_config
 let ocaml_config_var_exn t var =
   get_ocaml_config_var_exn t.ocamlc_config var
     ~ocamlc_config_cmd:t.ocamlc_config_cmd
@@ -200,31 +204,43 @@ let create ?dest_dir ?ocamlc ?(log=ignore) name =
     ; c_compiler    = ""
     ; stdlib_dir    = ""
     ; ccomp_type    = ""
-    ; ocamlc_config = Map.empty (module String)
+    ; ocamlc_config = StringMap.empty
     ; ocamlc_config_cmd
     }
   in
   let ocamlc_config =
-    let colon_space = String.Search_pattern.create ": " in
+    let search pat s =
+      let rec loop pos len =
+        if len >= String.length pat
+        then Some pos
+        else if pos+len >= String.length s
+        then None
+        else if s.[pos+len] = pat.[len]
+        then loop pos (len+1)
+        else loop (pos+1) 0
+      in loop 0 0
+    in
     run_capture_exn t ~dir:dest_dir ocamlc_config_cmd
-    |> String.split_lines
-    |>  List.map ~f:(fun line ->
-      match String.Search_pattern.index colon_space ~in_:line with
+    |> split_lines
+    |> List.map ~f:(fun line ->
+      match search ": " line with
       | Some i ->
         (String.sub line ~pos:0 ~len:i,
          String.sub line ~pos:(i + 2) ~len:(String.length line - i - 2))
       | None ->
         die "unrecognized line in the output of `%s`: %s" ocamlc_config_cmd
           line)
-    |> Map.of_alist (module String)
-    |> function
-    | `Ok x -> x
-    | `Duplicate_key key ->
-      die "variable %S present twice in the output of `%s`" key ocamlc_config_cmd
+    |> List.fold_left ~init:StringMap.empty ~f:begin fun m (k,v) ->
+         if StringMap.exists (fun k' _ -> String.equal k k') m
+         then
+           die "variable %S present twice in the output of `%s`" k ocamlc_config_cmd
+         else
+           StringMap.add k v m
+       end
   in
   let get = get_ocaml_config_var_exn ocamlc_config ~ocamlc_config_cmd in
   let c_compiler =
-    match Map.find ocamlc_config "c_compiler" with
+    match StringMap.find_opt "c_compiler" ocamlc_config with
     | Some c_comp -> c_comp ^ " " ^ get "ocamlc_cflags"
     | None -> get "bytecomp_c_compiler"
   in
@@ -249,9 +265,11 @@ let compile_c_prog t ?(c_flags=[]) ?(link_flags=[]) co
   let c_fname = base ^ ".c" in
   let obj_fname = base ^ t.ext_obj in
   let exe_fname = base ^ ".exe" in
-  Out_channel.write_all c_fname ~data:code;
+  let c_chan = open_out c_fname in
+  output_string c_chan code;
+  close_out c_chan;
   logf t "compiling c program:";
-  List.iter (String.split_lines code) ~f:(logf t " | %s");
+  List.iter (split_lines code) ~f:(logf t " | %s");
   let run_ok args =
     run_ok t ~dir
       (String.concat ~sep:" "
@@ -295,17 +313,6 @@ module C_define = struct
       | (Int | String), Switch -> -1
       | Int, String -> 1
       | String, Int -> -1
-
-    let sexp_of_t = function
-      | Switch -> Sexp.Atom "switch"
-      | Int -> Sexp.Atom "int"
-      | String -> Sexp.Atom "string"
-
-    let t_of_sexp = function
-      | Sexp.Atom "switch" -> Switch
-      | Sexp.Atom "int" -> Int
-      | Sexp.Atom "string" -> String
-      | s -> raise (Sexp.Of_sexp_error (Failure "C_define.Type.t_of_sexp", s))
   end
 
   module Value = struct
@@ -316,28 +323,13 @@ module C_define = struct
 
     let compare x y =
       match x, y with
-      | Switch x, Switch y -> Bool.compare x y
-      | Int x, Int y -> Int.compare x y
+      | Switch x, Switch y -> compare x y
+      | Int x, Int y -> compare x y
       | String x, String y -> String.compare x y
       | Switch _, (Int _ | String _) -> 1
       | (Int _ | String _), Switch _ -> -1
       | Int _, String _ -> 1
       | String _, Int _ -> -1
-
-    let sexp_of_t =
-      let open Sexp in
-      function
-      | Switch b -> List [Atom "switch"; Bool.sexp_of_t b]
-      | Int i -> List [Atom "int"; Int.sexp_of_t i]
-      | String s -> List [Atom "string"; String.sexp_of_t s]
-
-    let t_of_sexp =
-      let open Sexp in
-      function
-      | List [Atom "switch"; x] -> Switch (Bool.t_of_sexp x)
-      | List [Atom "int"; x] -> Int (Int.t_of_sexp x)
-      | List [Atom "string"; x] -> String (String.t_of_sexp x)
-      | s -> raise (Sexp.Of_sexp_error (Failure "C_define.Value.t_of_sexp", s))
   end
 
   let import t ?c_flags ?link_flags ~includes vars =
@@ -367,13 +359,21 @@ module C_define = struct
     | Error () -> die "failed to compile program"
     | Ok exe ->
       run_capture_exn t ~dir:(Fn.dirname exe) (command_line exe [])
-      |> String.split_lines
+      |> split_lines
       |> List.map ~f:(fun s : (string * Value.t) ->
-        let var, data = String.lsplit2_exn s ~on:'=' in
+        let split s c =
+          let pos = String.index s c in
+          String.sub s ~pos:0 ~len:pos,
+          String.sub s ~pos:(pos+1) ~len:(String.length s - pos - 1)
+        in
+        let var, data = split s '=' in
         (var,
-         match String.lsplit2_exn data ~on:':' with
-         | "b", s -> Switch (Bool.of_string s)
-         | "i", s -> Int    (Int. of_string s)
+         match split data ':' with
+         | "b", s -> Switch (match s with
+             | "true" | "yes" -> true
+             | "false" | "no" -> false
+             |_ -> invalid_arg ("expected boolean, but got " ^ s))
+         | "i", s -> Int    (int_of_string s)
          | "s", s -> String s
          | _ -> assert false))
 
@@ -383,11 +383,11 @@ module C_define = struct
       | Some v -> v
       | None ->
         String.map (t.name ^ "_" ^ Fn.basename fname) ~f:(function
-          | 'a'..'z' as c -> Char.uppercase c
+          | 'a'..'z' as c -> int_of_char c + 32 |> char_of_int
           | 'A'..'Z' | '0'..'9' as c -> c
           | _ -> '_')
     in
-    let vars = List.sort vars ~compare:(fun (a, _) (b, _) -> String.compare a b) in
+    let vars = List.sort vars ~cmp:(fun (a, _) (b, _) -> String.compare a b) in
     let lines =
       List.map vars ~f:(fun (name, value) ->
         match (value : Value.t) with
@@ -408,7 +408,9 @@ module C_define = struct
     logf t "writing header file %s" fname;
     List.iter lines ~f:(logf t " | %s");
     let tmp_fname = fname ^ ".tmp" in
-    Out_channel.write_lines tmp_fname lines;
+    let chan = open_out tmp_fname in
+    List.iter lines ~f:(fun s -> output_string chan s; output_char chan '\n');
+    close_out chan;
     Sys.rename tmp_fname fname
 end
 
@@ -419,7 +421,7 @@ let find_in_path t prog =
   logf t "-> %s"
     (match x with
      | None -> "not found"
-     | Some fn -> "found: " ^ quote fn);
+     | Some fn -> "found: " ^ Fn.quote fn);
   x
 
 module Pkg_config = struct
@@ -429,8 +431,8 @@ module Pkg_config = struct
     }
 
   let get c =
-    Option.map (find_in_path c "pkg-config") ~f:(fun pkg_config ->
-      { pkg_config; configurator = c })
+    match find_in_path c "pkg-config" with None -> None
+    | Some pkg_config -> Some  { pkg_config; configurator = c }
 
   type package_conf =
     { libs   : string list
@@ -438,8 +440,8 @@ module Pkg_config = struct
     }
 
   let query t ~package =
-    let package = quote package in
-    let pkg_config = quote t.pkg_config in
+    let package = Fn.quote package in
+    let pkg_config = Fn.quote t.pkg_config in
     let c = t.configurator in
     let dir = c.dest_dir in
     let env =
@@ -448,10 +450,10 @@ module Pkg_config = struct
           match find_in_path c "brew" with
           | Some brew ->
             let prefix =
-              String.strip (run_capture_exn c ~dir (command_line brew ["--prefix"]))
+              String.trim (run_capture_exn c ~dir (command_line brew ["--prefix"]))
             in
             sprintf "env PKG_CONFIG_PATH=%s/opt/%s/lib/pkgconfig:$PKG_CONFIG_PATH "
-              (quote prefix) package
+              (Fn.quote prefix) package
           | None ->
             ""
         end
@@ -460,11 +462,11 @@ module Pkg_config = struct
     if run_ok c ~dir (sprintf "%s%s %s" env pkg_config package) then
       let run what =
         match
-          String.strip
+          String.trim
             (run_capture_exn c ~dir (sprintf "%s%s %s %s" env pkg_config what package))
         with
         | "" -> []
-        | s  -> String.split s ~on:' '
+        | s  -> String.split_on_char s ~sep:' '
       in
       Some
         { libs   = run "--libs"
@@ -503,9 +505,9 @@ let main ?(args=[]) ~name f =
   try
     f t
   with exn ->
-    List.iter (List.rev !log_db) ~f:(eprintf "%s\n");
+    List.iter (List.rev !log_db) ~f:(Printf.eprintf "%s\n");
     match exn with
     | Fatal_error msg ->
-      eprintf "Error: %s\n%!" msg;
-      Caml.exit 1
+      Printf.eprintf "Error: %s\n%!" msg;
+      exit 1
     | exn -> raise exn
