let buffer_length = 1024 in
let in_buffer = String.create buffer_length in
let out_buffer = String.create buffer_length in
let out_buffer_length = ref 0 in
let end_of_stream = ref false in
let waiting_for_input = ref true in
let waiting_for_output = ref false in
while !waiting_for_input or !waiting_for_output do
(* If !waiting_for_input, we are interested whether input arrives.
* If !waiting_for_output, we are interested whether output is
* possible.
*)
let (in_fd, out_fd, oob_fd) =
Unix.select (if !waiting_for_input then [ Unix.stdin] else [])
(if !waiting_for_output then [ Unix.stdout] else [])
[]
(-.1.0) in
(* If in_fd is non-empty, input is immediately possible and will
* not block.
*)
if in_fd <> [] then begin
(* How many bytes we can read in depends on the amount of
* free space in the output buffer.
*)
let n = buffer_length - !out_buffer_length in
assert(n > 0);
let n' = Unix.read Unix.stdin in_buffer 0 n in
end_of_stream := (n' = 0);
(* Convert the bytes, and append them to the output buffer. *)
let converted = String.uppercase (String.sub in_buffer 0 n') in
String.blit converted 0 out_buffer !out_buffer_length n';
out_buffer_length := !out_buffer_length + n';
end;
(* If out_fd is non-empty, output is immediately possible and
* will not block.
*)
if out_fd <> [] then begin
(* Try to write !out_buffer_length bytes. *)
let n' = Unix.write Unix.stdout out_buffer 0 !out_buffer_length in
(* Remove the written bytes from the out_buffer: *)
String.blit out_buffer n' out_buffer 0 (!out_buffer_length - n');
out_buffer_length := !out_buffer_length - n'
end;
(* Now find out which event is interesting next: *)
waiting_for_input := (* Input is interesting if...*)
not !end_of_stream && (* ...we are before the end *)
!out_buffer_length < buffer_length; (* ...there is space in the out buf *)
waiting_for_output := (* Output is interesting if... *)
!out_buffer_length > 0; (* ...there is material to output *)
done