-
Erwan Jahier authored
and collect the stdout lines into a list (requires sed) Also add an entete2 command that accept multi-line comments
Erwan Jahier authoredand collect the stdout lines into a list (requires sed) Also add an entete2 command that accept multi-line comments
mypervasives.ml 7.51 KiB
(* 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)