(* Time-stamp: <modified the 20/05/2016 (at 08:47) by erwan> *) (* Should rather be names misc or utils *) (* [string_to_string_list str] returns the list of substrings of [str] that are separated by blanks. *) let (string_to_string_list : string -> string list) = fun str -> Str.split (Str.regexp "[ \t]+") str (* Cloned from the OCaml stdlib Arg module: I want it on stdout! (scrogneugneu) *) let usage_out speclist errmsg = Printf.printf "%s" (Arg.usage_string speclist errmsg) let (readfile: ?verbose:bool ->string -> string) = fun ?(verbose=false) file -> if verbose then (Printf.eprintf "Reading %s...\n" file; flush stderr); try let rec (readfile_ic : in_channel -> string) = fun ic -> let ic_l = in_channel_length ic in let str_buf = String.make ic_l ' ' in let _ = really_input ic str_buf 0 ic_l in str_buf in let ic = (open_in file) in let str = readfile_ic ic in close_in ic; str with e -> print_string ((Printexc.to_string e) ^ ": "); output_string stdout ("Error when reading " ^file^ ".\n"); flush stdout; raise Not_found let mygetenv x = let x = match Sys.os_type with | "Win32" -> (x^"_DOS") | _ -> x in try Unix.getenv x with Not_found -> x^" env var not defined" (****************************************************************************) (* a few list utils *) let rec (list_split7: ('a * 'b * 'c * 'd * 'e * 'f * 'g) list -> 'a list * 'b list * 'c list * 'd list * 'e list * 'f list * 'g list) = function | [] -> ([], [], [], [], [], [], []) | (x,y,z,t,u,v,w)::l -> let (rx, ry, rz, rt, ru, rv, rw) = list_split7 l in (x::rx, y::ry, z::rz, t::rt, u::ru, v::rv, w::rw) (* returns a \ b *) let list_minus a b = List.filter (fun v -> not (List.mem v b)) a (* returns a U b *) let list_union a b = List.fold_left (fun acc x -> if (List.mem x acc) then acc else x::acc) a b (** Removes duplicates from a list (conserving its order) *) let (list_rm_dup : 'a list -> 'a list) = fun list -> let rec aux acc list = match list with | [] -> List.rev acc | elt::tail -> if List.mem elt acc then aux acc tail else aux (elt::acc) tail in aux [] list (****************************************************************************) (** Map of strings *) module StringMap = struct include Map.Make(struct type t = string let compare = compare end) end (****************************************************************************) (** I define my own version of print_float to turn around a bug of sim2chro where it does not understand floats with no digit (e.g., 4. instead of 4.0) *) (* format_float is not exported in Pervasives.mli. nb: its name changed in ocaml version 3.08 (was "format_float") *) external format_float: string -> float -> string = "caml_format_float" let my_string_of_float f p = format_float ("%." ^ (string_of_int p) ^ "f") f let my_print_float f p = output_string stdout (my_string_of_float f p) let overflow_msg str = Printf.eprintf "Fail to convert into an int the string '%s'.\n" str; flush stderr let int_of_num n = try Num.int_of_num n with _ -> let str = Num.string_of_num n in let msg = Printf.sprintf "Fail to convert into an int the num '%s'.\n" str in overflow_msg msg; exit 2 (* for language that does have one-line comments *) let entete2 comment_open comment_close version sha = let time = Unix.localtime (Unix.time ()) in let date = ( (string_of_int time.Unix.tm_mday) ^ "/" ^ (string_of_int (time.Unix.tm_mon+1)) ^ "/" ^ (string_of_int (1900+time.Unix.tm_year)) ) and time_str = ( (string_of_int time.Unix.tm_hour) ^ ":" ^ (if time.Unix.tm_min < 10 then "0" else "") ^ (string_of_int time.Unix.tm_min) ^ ":" ^ (if time.Unix.tm_sec < 10 then "0" else "") ^ (string_of_int time.Unix.tm_sec) ) and hostname = Unix.gethostname () in (comment_open ^ " Automatically generated by "^ Sys.executable_name^" version \""^version^"\" (\"" ^sha^"\")"^comment_close^"\n" ^ comment_open ^ " on " ^ hostname ^ " the " ^ date ^ " at " ^ time_str ^comment_close^"\n" ^ comment_open^(String.concat " " (Array.to_list Sys.argv))^ comment_close^"\n\n") (* for one-line comments *) let entete comment version sha = entete2 comment "" version sha (****************************************************************************) (* use to perform system calls *) type my_create_process_result = OK | KO | PID of int (* if called with ~wait:false *) let (my_create_process : ?std_in:(Unix.file_descr) -> ?std_out:(Unix.file_descr) -> ?std_err:(Unix.file_descr) -> ?wait:(bool) -> string -> string list -> my_create_process_result) = fun ?(std_in = Unix.stdin) ?(std_out = Unix.stdout) ?(std_err = Unix.stderr) ?(wait = true) prog args -> try let pid = List.iter (fun x -> output_string stderr (x ^ " ")) (prog::args); output_string stderr "\n"; flush stderr; Unix.create_process prog (Array.of_list (prog::args)) (std_in) (std_out) (std_err) in if not wait then PID pid else let (_,status) = (Unix.waitpid [Unix.WUNTRACED] pid) in ( match status with Unix.WEXITED i -> if i = 0 || i = 1 then ( output_string stderr (" ... " ^ prog ^ " exited normally.\n"); flush stderr; OK ) else ( output_string stderr ( "*** Error: " ^ prog ^ " exited abnormally (return code=" ^ (string_of_int i)^").\n"); flush stderr; KO ) | Unix.WSIGNALED i-> output_string stderr ( "*** Error: " ^ prog ^ " process was killed by signal "^(string_of_int i)^"\n"); flush stderr; KO | Unix.WSTOPPED i -> output_string stderr ( "*** Error: " ^ prog ^ " process was stopped by signal " ^ (string_of_int i)^"\n"); flush stderr; KO ) with | Unix.Unix_error(error, name, arg) -> let msg = ( "*** '" ^ (Unix.error_message error) ^ "'in the system call: '" ^ name ^ " " ^ arg ^ "'\n") in output_string stdout msg; flush stdout; output_string stderr msg; flush stderr; KO | e -> output_string stdout (Printexc.to_string e); flush stdout; output_string stderr (Printexc.to_string e); flush stderr; KO (* run a cmd and collect the stdout lines into a list (requires sed) *) let (run : string -> (string -> string option) -> string list) = fun cmd filter -> let proc = Unix.open_process_in ("(" ^ cmd ^ " | sed -e 's/^/stdout: /' ) 2>&1") in let list = ref [] in try while true do let line = input_line proc in if String.length line >= 8 && String.sub line 0 8 = "stdout: " then let str = String.sub line 8 (String.length line - 8) in match filter str with | None -> () | Some str -> list := str::!list done; [] with End_of_file -> ignore (Unix.close_process_in proc); List.rev !list let ls path ext = run ("ls "^path^"*."^ext) (fun s -> Some s)