3 let b = Bytes.of_string
s;;
7 type platform
= | Punknown
| Plinux
| Posx
| Psun
| Pbsd
| Pcygwin
;;
9 let tempfailureretry f
a =
11 try f
a with Unix.Unix_error
(Unix.EINTR
, _
, _
) -> g ()
15 external cloexec
: Unix.file_descr
-> unit = "ml_cloexec";;
16 external hasdata
: Unix.file_descr
-> bool = "ml_hasdata";;
17 external toutf8
: int -> string = "ml_keysymtoutf8";;
18 external mbtoutf8
: string -> string = "ml_mbtoutf8";;
19 external popen
: string -> (Unix.file_descr
* int) list
-> int = "ml_popen";;
20 external platform
: unit -> (platform
* string array
) = "ml_platform";;
22 let now = Unix.gettimeofday
;;
23 let platform, uname
= platform ();;
24 let dolog fmt
= Format.ksprintf prerr_endline fmt
;;
27 | Unix.Unix_error
(e
, s, a) -> Printf.sprintf
"%s(%s) : %s (%d)"
28 s a (Unix.error_message e
) (Obj.magic e
)
29 | exn
-> Printexc.to_string exn
;
32 let error fmt
= Printf.kprintf failwith fmt
;;
34 module IntSet
= Set.Make
(struct type t
= int let compare = (-) end);;
36 let emptystr s = String.length
s = 0;;
37 let nonemptystr s = String.length
s > 0;;
38 let bound v minv maxv
= max minv
(min maxv v
);;
42 then failwith
"popen not implemented under cygwin yet"
48 type t
= private string
49 val of_string
: string -> t
50 val to_string
: t
-> string
60 let (~
<) = Opaque.of_string;;
61 let (~
>) = Opaque.to_string;;
63 let int_of_string_with_suffix s =
64 let l = String.length
s in
68 let suffix = Char.lowercase
s.[l-1] in
70 | 'k'
-> String.sub
s 0 (l-1), 10
71 | 'm'
-> String.sub
s 0 (l-1), 20
72 | '
g'
-> String.sub
s 0 (l-1), 30
76 let n = int_of_string
s1 in
77 let m = n lsl shift
in
79 then error "value too large"
83 let string_with_suffix_of_int n =
87 let units = [(30, "G"); (20, "M"); (10, "K")] in
93 then string_of_int
h ^
s
95 let s = Printf.sprintf
"_%03d%s" h s in
101 let rec find = function
103 | (shift
, suffix) :: rest
->
104 if (n land ((1 lsl shift
) - 1)) = 0
105 then prettyint (n lsr shift
) ^
suffix
111 let color_of_string s =
112 Scanf.sscanf
s "%d/%d/%d" (fun r
g b ->
113 (float r
/. 256.0, float g /. 256.0, float b /. 256.0)
117 let color_to_string (r
, g, b) =
118 let r = truncate
(r *. 256.0)
119 and g = truncate
(g *. 256.0)
120 and b = truncate
(b *. 256.0) in
121 Printf.sprintf
"%d/%d/%d" r g b
125 if Filename.is_relative path
127 let cwd = Sys.getcwd
() in
128 if Filename.is_implicit path
129 then Filename.concat
cwd path
130 else Filename.concat
cwd (Filename.basename path
)
142 try tempfailureretry Unix.close fd
143 with exn
-> f
(exntos exn
)
147 let getenvwithdef name def
=
148 match Sys.getenv name
with
150 | exception Not_found
-> def
153 let newlinere = Str.regexp
"[\r\n]";;
154 let percentsre = Str.regexp
"%s";;
157 let ic = open_in path
in
158 let b = Buffer.create
(in_channel_length
ic) in
160 match input_line
ic with
161 | (exception End_of_file
) -> Buffer.contents
b
163 if Buffer.length
b > 0
164 then Buffer.add_char
b '
\n'
;
165 Buffer.add_string
b line
;
176 let b = Buffer.create
(String.length
s + 1) in
177 Buffer.add_string
b s;
182 let btod b = if b then 1 else 0;;
185 let r = Str.regexp
" " in
186 fun s -> Str.bounded_split
r s 2;
189 let boundastep h step
=
191 then bound step ~
-h 0
195 let withoutlastutf8 s =
196 let len = String.length
s in
204 let b = Char.code
s.[pos
] in
205 if b land 0b11000000 = 0b11000000
210 if Char.code
s.[len-1] land 0x80 = 0
214 String.sub
s 0 first;
219 let b = Buffer.create
l in
220 let s = Bytes.create
l in
222 let n = tempfailureretry (Unix.read fd
s 0) l in
224 then Buffer.contents
b
226 Buffer.add_subbytes
b s 0 n;
233 let getcmdoutput errfun cmd
=
234 let reperror fmt
= Printf.kprintf errfun fmt
in
235 let clofail s e
= error "failed to close %s: %s" s e
in
236 match Unix.pipe
() with
238 reperror "pipe failed: %s" (exntos exn
);
241 match popen cmd
[r, -1; w
, 1] with
243 reperror "failed to execute %S: %s" cmd
(exntos exn
);
246 Ne.clo w
@@ clofail "write end of the pipe";
248 match Unix.waitpid
[] pid
with
250 reperror "waitpid on %S %d failed: %s" cmd pid
(exntos exn
);
252 | _pid
, Unix.WEXITED
0 ->
254 match fdcontents r with
256 reperror "failed to read output of %S: %s" cmd
(exntos exn
);
259 let l = String.length
s in
260 if l > 0 && s.[l-1] = '
\n'
261 then String.sub
s 0 (l-1)
264 | _pid
, Unix.WEXITED
n ->
265 reperror "%S exited with error code %d" cmd
n;
267 | _pid
, Unix.WSIGNALED
n ->
268 reperror "%S was killed with signal %d" cmd
n;
270 | _pid
, Unix.WSTOPPED
n ->
271 reperror "%S was stopped by signal %d" cmd
n;
274 Ne.clo r @@ clofail "read end of the pipe";
279 let colonpos = try String.index
s '
:'
with Not_found
-> -1 in
280 let len = String.length
s in
281 if colonpos >= 0 && colonpos + 3 < len
283 if s.[colonpos+1] = '
/'
&& s.[colonpos+2] = '
/'
286 try String.rindex_from
s colonpos ' '
290 String.sub
s (schemestartpos+1) (colonpos-1-schemestartpos)
293 | "http" | "https" | "ftp" | "mailto" ->
295 try String.index_from
s colonpos ' '
296 with Not_found
-> len
298 String.sub
s (schemestartpos+1) (epos-1-schemestartpos)