1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1996 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the GNU Library General Public License, with *)
10 (* the special exception on linking described in file ../LICENSE. *)
12 (* (C) Flying Frog Consultancy Ltd., 2006 *)
13 (* portions lifted from Extlib *)
14 (* Copyright (C) 2003 Brian Hurt *)
15 (* Copyright (C) 2003 Nicolas Cannasse *)
16 (***********************************************************************)
20 (* type 'a option = None | Some of 'a *)
24 external raise
: exn
-> 'a
= "%raise"
26 let failwith s
= raise
(Failure s
)
27 let invalid_arg s
= raise
(Invalid_argument s
)
29 let finally handler f x
=
30 let r = ( try f x
with e
-> handler
(); raise e
) in
38 external (=) : 'a
-> 'a
-> bool = "%equal"
39 external (<>) : 'a
-> 'a
-> bool = "%notequal"
40 external (<) : 'a
-> 'a
-> bool = "%lessthan"
41 external (>) : 'a
-> 'a
-> bool = "%greaterthan"
42 external (<=) : 'a
-> 'a
-> bool = "%lessequal"
43 external (>=) : 'a
-> 'a
-> bool = "%greaterequal"
44 external compare
: 'a
-> 'a
-> int = "%compare"
46 let min x y
= if x
<= y
then x
else y
47 let max x y
= if x
>= y
then x
else y
49 external (==) : 'a
-> 'a
-> bool = "%eq"
50 external (!=) : 'a
-> 'a
-> bool = "%noteq"
52 (* Boolean operations *)
54 external not
: bool -> bool = "%boolnot"
55 external (&) : bool -> bool -> bool = "%sequand"
56 external (&&) : bool -> bool -> bool = "%sequand"
57 external (or) : bool -> bool -> bool = "%sequor"
58 external (||) : bool -> bool -> bool = "%sequor"
60 (* Integer operations *)
62 external (~
-) : int -> int = "%negint"
63 external succ
: int -> int = "%succint"
64 external pred
: int -> int = "%predint"
65 external (+) : int -> int -> int = "%addint"
66 external (-) : int -> int -> int = "%subint"
67 external ( * ) : int -> int -> int = "%mulint"
68 external (/) : int -> int -> int = "%divint"
69 external (mod) : int -> int -> int = "%modint"
71 let abs x
= if x
>= 0 then x
else -x
73 external (land) : int -> int -> int = "%andint"
74 external (lor) : int -> int -> int = "%orint"
75 external (lxor) : int -> int -> int = "%xorint"
77 let lnot x
= x
lxor (-1)
79 external (lsl) : int -> int -> int = "%lslint"
80 external (lsr) : int -> int -> int = "%lsrint"
81 external (asr) : int -> int -> int = "%asrint"
83 let min_int = 1 lsl (if 1 lsl 31 = 0 then 30 else 62)
84 let max_int = min_int - 1
86 (* Floating-point operations *)
88 external (~
-.) : float -> float = "%negfloat"
89 external (+.) : float -> float -> float = "%addfloat"
90 external (-.) : float -> float -> float = "%subfloat"
91 external ( *. ) : float -> float -> float = "%mulfloat"
92 external (/.) : float -> float -> float = "%divfloat"
93 external ( ** ) : float -> float -> float = "caml_power_float" "pow" "float"
94 external exp
: float -> float = "caml_exp_float" "exp" "float"
95 external acos
: float -> float = "caml_acos_float" "acos" "float"
96 external asin
: float -> float = "caml_asin_float" "asin" "float"
97 external atan
: float -> float = "caml_atan_float" "atan" "float"
98 external atan2
: float -> float -> float = "caml_atan2_float" "atan2" "float"
99 external cos
: float -> float = "caml_cos_float" "cos" "float"
100 external cosh
: float -> float = "caml_cosh_float" "cosh" "float"
101 external log
: float -> float = "caml_log_float" "log" "float"
102 external log10
: float -> float = "caml_log10_float" "log10" "float"
103 external sin
: float -> float = "caml_sin_float" "sin" "float"
104 external sinh
: float -> float = "caml_sinh_float" "sinh" "float"
105 external sqrt
: float -> float = "caml_sqrt_float" "sqrt" "float"
106 external tan
: float -> float = "caml_tan_float" "tan" "float"
107 external tanh
: float -> float = "caml_tanh_float" "tanh" "float"
108 external ceil
: float -> float = "caml_ceil_float" "ceil" "float"
109 external floor
: float -> float = "caml_floor_float" "floor" "float"
110 external abs_float
: float -> float = "%absfloat"
111 external mod_float
: float -> float -> float = "caml_fmod_float" "fmod" "float"
112 external frexp
: float -> float * int = "caml_frexp_float"
113 external ldexp
: float -> int -> float = "caml_ldexp_float"
114 external modf
: float -> float * float = "caml_modf_float"
115 external float : int -> float = "%floatofint"
116 external float_of_int
: int -> float = "%floatofint"
117 external truncate
: float -> int = "%intoffloat"
118 external int_of_float
: float -> int = "%intoffloat"
119 external float_of_bits
: int64
-> float = "caml_int64_float_of_bits"
121 float_of_bits
0x7F_F
0_00_00_00_00_00_00L
123 float_of_bits
0xFF_F
0_00_00_00_00_00_00L
125 float_of_bits
0x7F_F
0_00_00_00_00_00_01L
127 float_of_bits
0x7F_EF_FF_FF_FF_FF_FF_FFL
129 float_of_bits
0x00_10_00_00_00_00_00_00L
131 float_of_bits
0x3C_B
0_00_00_00_00_00_00L
132 let pi = 4. *. atan
1.
140 external classify_float
: float -> fpclass
= "caml_classify_float"
142 (* String operations -- more in module String *)
144 external string_length
: string -> int = "%string_length"
145 external string_create
: int -> string = "caml_create_string"
146 external string_blit
: string -> int -> string -> int -> int -> unit
147 = "caml_blit_string" "noalloc"
150 let l1 = string_length s1
and l2
= string_length s2
in
151 let s = string_create
(l1 + l2
) in
152 string_blit s1
0 s 0 l1;
153 string_blit s2
0 s l1 l2
;
156 (* Character operations -- more in module Char *)
158 external int_of_char
: char
-> int = "%identity"
159 external unsafe_char_of_int
: int -> char
= "%identity"
161 if n
< 0 || n
> 255 then invalid_arg "char_of_int" else unsafe_char_of_int n
163 (* Unit operations *)
165 external ignore
: 'a
-> unit = "%ignore"
167 (* Pair operations *)
169 external fst
: 'a
* 'b
-> 'a
= "%field0"
170 external snd
: 'a
* 'b
-> 'b
= "%field1"
172 (* String conversion functions *)
174 external format_int
: string -> int -> string = "caml_format_int"
175 external format_float
: string -> float -> string = "caml_format_float"
177 let string_of_bool b
=
178 if b
then "true" else "false"
179 let bool_of_string = function
182 | _
-> invalid_arg "bool_of_string"
184 let string_of_int n
=
187 external int_of_string
: string -> int = "caml_int_of_string"
189 module String
= struct
190 external get
: string -> int -> char
= "%string_safe_get"
193 let valid_float_lexem s =
194 let l = string_length
s in
196 if i
>= l then s ^
"." else
198 | '
0'
.. '
9'
| '
-'
-> loop (i
+1)
204 let string_of_float f
= valid_float_lexem (format_float
"%.12g" f
);;
206 external float_of_string
: string -> float = "caml_float_of_string"
208 (* List operations -- more in module List *)
213 | hd
:: tl
-> hd
:: (tl
@ l2
)
220 external open_descriptor_out
: int -> out_channel
= "caml_ml_open_descriptor_out"
221 external open_descriptor_in
: int -> in_channel
= "caml_ml_open_descriptor_in"
223 let stdin = open_descriptor_in
0
224 let stdout = open_descriptor_out
1
225 let stderr = open_descriptor_out
2
227 (* General output functions *)
230 Open_rdonly
| Open_wronly
| Open_append
231 | Open_creat
| Open_trunc
| Open_excl
232 | Open_binary
| Open_text
| Open_nonblock
234 external open_desc
: string -> open_flag list
-> int -> int = "caml_sys_open"
236 let open_out_gen mode perm name
=
237 open_descriptor_out
(open_desc name mode perm
)
240 open_out_gen [Open_wronly
; Open_creat
; Open_trunc
; Open_text
] 0o666 name
242 let open_out_bin name
=
243 open_out_gen [Open_wronly
; Open_creat
; Open_trunc
; Open_binary
] 0o666 name
245 external flush
: out_channel
-> unit = "caml_ml_flush"
247 external out_channels_list
: unit -> out_channel list
248 = "caml_ml_out_channels_list"
251 let rec iter = function
253 | a
::l -> (try flush a
with _
-> ()); iter l
254 in iter (out_channels_list
())
256 external unsafe_output
: out_channel
-> string -> int -> int -> unit
259 external output_char
: out_channel
-> char
-> unit = "caml_ml_output_char"
261 let output_string oc
s =
262 unsafe_output oc
s 0 (string_length
s)
264 let output oc
s ofs len
=
265 if ofs
< 0 || len
< 0 || ofs
> string_length
s - len
266 then invalid_arg "output"
267 else unsafe_output oc
s ofs len
269 external output_byte
: out_channel
-> int -> unit = "caml_ml_output_char"
270 external output_binary_int
: out_channel
-> int -> unit = "caml_ml_output_int"
272 external marshal_to_channel
: out_channel
-> 'a
-> unit list
-> unit
273 = "caml_output_value"
274 let output_value chan v
= marshal_to_channel chan v
[]
276 external seek_out
: out_channel
-> int -> unit = "caml_ml_seek_out"
277 external pos_out
: out_channel
-> int = "caml_ml_pos_out"
278 external out_channel_length
: out_channel
-> int = "caml_ml_channel_size"
279 external close_out_channel
: out_channel
-> unit = "caml_ml_close_channel"
280 let close_out oc
= flush oc
; close_out_channel oc
281 let close_out_noerr oc
=
282 (try flush oc
with _
-> ());
283 (try close_out_channel oc
with _
-> ())
284 external set_binary_mode_out
: out_channel
-> bool -> unit
285 = "caml_ml_set_binary_mode"
287 (* General input functions *)
289 let open_in_gen mode perm name
=
290 open_descriptor_in
(open_desc name mode perm
)
293 open_in_gen [Open_rdonly
; Open_text
] 0 name
295 let open_in_bin name
=
296 open_in_gen [Open_rdonly
; Open_binary
] 0 name
298 external input_char
: in_channel
-> char
= "caml_ml_input_char"
300 external unsafe_input
: in_channel
-> string -> int -> int -> int
303 let input ic
s ofs len
=
304 if ofs
< 0 || len
< 0 || ofs
> string_length
s - len
305 then invalid_arg "input"
306 else unsafe_input ic
s ofs len
308 let rec unsafe_really_input ic
s ofs len
=
309 if len
<= 0 then () else begin
310 let r = unsafe_input ic
s ofs len
in
312 then raise End_of_file
313 else unsafe_really_input ic
s (ofs
+r) (len
-r)
316 let really_input ic
s ofs len
=
317 if ofs
< 0 || len
< 0 || ofs
> string_length
s - len
318 then invalid_arg "really_input"
319 else unsafe_really_input ic
s ofs len
321 external input_scan_line
: in_channel
-> int = "caml_ml_input_scan_line"
323 let input_line chan
=
324 let rec build_result buf pos
= function
327 let len = string_length hd
in
328 string_blit hd
0 buf
(pos
- len) len;
329 build_result buf
(pos
- len) tl
in
330 let rec scan accu
len =
331 let n = input_scan_line chan
in
332 if n = 0 then begin (* n = 0: we are at EOF *)
334 [] -> raise End_of_file
335 | _
-> build_result (string_create
len) len accu
336 end else if n > 0 then begin (* n > 0: newline found in buffer *)
337 let res = string_create
(n-1) in
338 ignore
(unsafe_input chan
res 0 (n-1));
339 ignore
(input_char chan
); (* skip the newline *)
342 | _
-> let len = len + n - 1 in
343 build_result (string_create
len) len (res :: accu
)
344 end else begin (* n < 0: newline not found *)
345 let beg = string_create
(-n) in
346 ignore
(unsafe_input chan
beg 0 (-n));
347 scan (beg :: accu
) (len - n)
351 external input_byte
: in_channel
-> int = "caml_ml_input_char"
352 external input_binary_int
: in_channel
-> int = "caml_ml_input_int"
353 external input_value
: in_channel
-> 'a
= "caml_input_value"
354 external seek_in
: in_channel
-> int -> unit = "caml_ml_seek_in"
355 external pos_in
: in_channel
-> int = "caml_ml_pos_in"
356 external in_channel_length
: in_channel
-> int = "caml_ml_channel_size"
357 external close_in
: in_channel
-> unit = "caml_ml_close_channel"
358 let close_in_noerr ic
= (try close_in ic
with _
-> ());;
359 external set_binary_mode_in
: in_channel
-> bool -> unit
360 = "caml_ml_set_binary_mode"
362 (* Output functions on standard output *)
364 let print_char c
= output_char
stdout c
365 let print_string s = output_string stdout s
366 let print_int i
= output_string stdout (string_of_int i
)
367 let print_float f
= output_string stdout (string_of_float f
)
368 let print_endline s =
369 output_string stdout s; output_char
stdout '
\n'
; flush
stdout
370 let print_newline () = output_char
stdout '
\n'
; flush
stdout
372 (* Output functions on standard error *)
374 let prerr_char c
= output_char
stderr c
375 let prerr_string s = output_string stderr s
376 let prerr_int i
= output_string stderr (string_of_int i
)
377 let prerr_float f
= output_string stderr (string_of_float f
)
378 let prerr_endline s =
379 output_string stderr s; output_char
stderr '
\n'
; flush
stderr
380 let prerr_newline () = output_char
stderr '
\n'
; flush
stderr
382 (* Input functions on standard input *)
384 let read_line () = flush
stdout; input_line stdin
385 let read_int () = int_of_string
(read_line())
386 let read_float () = float_of_string
(read_line())
388 (* Operations on large files *)
392 external seek_out
: out_channel
-> int64
-> unit = "caml_ml_seek_out_64"
393 external pos_out
: out_channel
-> int64
= "caml_ml_pos_out_64"
394 external out_channel_length
: out_channel
-> int64
395 = "caml_ml_channel_size_64"
396 external seek_in
: in_channel
-> int64
-> unit = "caml_ml_seek_in_64"
397 external pos_in
: in_channel
-> int64
= "caml_ml_pos_in_64"
398 external in_channel_length
: in_channel
-> int64
= "caml_ml_channel_size_64"
403 type 'a
ref = { mutable contents
: 'a
}
404 external ref: 'a
-> 'a
ref = "%makemutable"
405 external (!): 'a
ref -> 'a
= "%field0"
406 external (:=): 'a
ref -> 'a
-> unit = "%setfield0"
407 external incr
: int ref -> unit = "%incr"
408 external decr
: int ref -> unit = "%decr"
411 type ('a
, 'b
, 'c
, 'd
) format4
= ('a
, 'b
, 'c
, 'c
, 'c
, 'd
) format6
413 type ('a
, 'b
, 'c
) format
= ('a
, 'b
, 'c
, 'c
) format4
415 external format_of_string
:
416 ('a
, 'b
, 'c
, 'd
, 'e
, 'f
) format6
->
417 ('a
, 'b
, 'c
, 'd
, 'e
, 'f
) format6
= "%identity"
419 external format_to_string
:
420 ('a
, 'b
, 'c
, 'd
, 'e
, 'f
) format6
-> string = "%identity"
421 external string_to_format
:
422 string -> ('a
, 'b
, 'c
, 'd
, 'e
, 'f
) format6
= "%identity"
425 ('a
, 'b
, 'c
, 'd
, 'e
, 'f
) format6
->
426 ('f
, 'b
, 'c
, 'e
, 'g
, 'h
) format6
->
427 ('a
, 'b
, 'c
, 'd
, 'g
, 'h
) format6
) =
429 string_to_format
(format_to_string fmt1 ^ format_to_string fmt2
);;
431 let string_of_format fmt
=
432 let s = format_to_string fmt
in
433 let l = string_length
s in
434 let r = string_create
l in
435 string_blit
s 0 r 0 l;
440 external sys_exit
: int -> 'a
= "caml_sys_exit"
442 let exit_function = ref flush_all
445 let g = !exit_function in
446 exit_function := (fun () -> f
(); g())
448 let do_at_exit () = (!exit_function) ()
454 external register_named_value
: string -> 'a
-> unit
455 = "caml_register_named_value"
457 let _ = register_named_value
"Pervasives.do_at_exit" do_at_exit