#!/usr/bin/env ocaml

(*
 * This script computes an installation prefix based on
 *    1) $PREFIX, if set, or
 *    2) "opam config var prefix", if available, or
 *    3) "/usr/local" as a fallback.
 * The result gets substituted for @prefix@ in the input file, in much
 * the same way that autoconf does things.
 *)

#use "topfind";;
#require "unix";;


let opam_prefix () : string option =
  try
    let ic = UnixLabels.open_process_in "opam config var prefix" in
    let prefix = input_line ic in
    let status = UnixLabels.close_process_in ic in
    begin match status with
    | UnixLabels.WEXITED 0 ->
        Some prefix
    | _ ->
        None
    end
  with _ ->
    None


let installation_prefix () =
  match Sys.getenv_opt "PREFIX" with
  | Some prefix ->
      prefix
  | None ->
      begin match opam_prefix () with
      | Some prefix ->
          prefix
      | None ->
          "/usr/local"
      end


let sed_escape (input : string) : string =
  let buf = Buffer.create (String.length input) in
  for i = 0 to String.length input - 1 do
    begin if input.[i] == '\\' || input.[i] == '/' then
      Buffer.add_char buf '\\'
    end;
    Buffer.add_char buf input.[i]
  done;
  Buffer.contents buf


let subst_prefix (in_filename : string) (out_filename : string) : unit =
  let prefix = installation_prefix () in
  let cmd = Printf.sprintf "sed 's/@prefix@/%s/g' \"%s\" > \"%s\""
    (sed_escape prefix) in_filename out_filename in
  let ec = Sys.command cmd in
  begin if ec <> 0 then
    Printf.fprintf stderr "sed substitution failed with exit code %d.\n" ec
  end;
  exit ec


let abort_usage () =
  Printf.fprintf stderr "Usage:\n";
  Printf.fprintf stderr "    compute_prefix eval\n";
  Printf.fprintf stderr "    compute_prefix subst in_filename out_filename\n";
  exit 2


let () =
  begin if Array.length Sys.argv < 2 then
    abort_usage ()
  end;
  let command = Sys.argv.(1) in
  if String.equal command "eval" && Array.length Sys.argv = 2 then
    print_string (installation_prefix ())
  else if String.equal command "subst" && Array.length Sys.argv = 4 then
    let in_filename = Sys.argv.(2) in
    let out_filename = Sys.argv.(3) in
    subst_prefix in_filename out_filename
  else
    abort_usage ()

