Blame src/std.ml

rpm-build 0f2925
(*
rpm-build 0f2925
 * Std - Additional functions
rpm-build 0f2925
 * Copyright (C) 2003 Nicolas Cannasse and Markus Mottl
rpm-build 0f2925
 *
rpm-build 0f2925
 * This library is free software; you can redistribute it and/or
rpm-build 0f2925
 * modify it under the terms of the GNU Lesser General Public
rpm-build 0f2925
 * License as published by the Free Software Foundation; either
rpm-build 0f2925
 * version 2.1 of the License, or (at your option) any later version,
rpm-build 0f2925
 * with the special exception on linking described in file LICENSE.
rpm-build 0f2925
 *
rpm-build 0f2925
 * This library is distributed in the hope that it will be useful,
rpm-build 0f2925
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rpm-build 0f2925
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
rpm-build 0f2925
 * Lesser General Public License for more details.
rpm-build 0f2925
 *
rpm-build 0f2925
 * You should have received a copy of the GNU Lesser General Public
rpm-build 0f2925
 * License along with this library; if not, write to the Free Software
rpm-build 0f2925
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
rpm-build 0f2925
 *)
rpm-build 0f2925
rpm-build 0f2925
open ExtBytes
rpm-build 0f2925
rpm-build 0f2925
let finally handler f x =
rpm-build 0f2925
  let r = (
rpm-build 0f2925
    try
rpm-build 0f2925
      f x
rpm-build 0f2925
    with
rpm-build 0f2925
      e -> handler (); raise e
rpm-build 0f2925
  ) in
rpm-build 0f2925
  handler ();
rpm-build 0f2925
  r
rpm-build 0f2925
rpm-build 0f2925
let input_lines ch =
rpm-build 0f2925
  Enum.from (fun () ->
rpm-build 0f2925
    try input_line ch with End_of_file -> raise Enum.No_more_elements)
rpm-build 0f2925
rpm-build 0f2925
let input_chars ch =
rpm-build 0f2925
  Enum.from (fun () ->
rpm-build 0f2925
    try input_char ch with End_of_file -> raise Enum.No_more_elements)
rpm-build 0f2925
rpm-build 0f2925
type 'a _mut_list = {
rpm-build 0f2925
  hd : 'a;
rpm-build 0f2925
  mutable tl : 'a _mut_list;
rpm-build 0f2925
}
rpm-build 0f2925
rpm-build 0f2925
let input_list ch =
rpm-build 0f2925
  let _empty = Obj.magic [] in
rpm-build 0f2925
  let rec loop dst =
rpm-build 0f2925
    let r = { hd = input_line ch; tl = _empty } in
rpm-build 0f2925
    dst.tl <- r;
rpm-build 0f2925
    loop r in
rpm-build 0f2925
  let r = { hd = Obj.magic(); tl = _empty } in
rpm-build 0f2925
  try loop r
rpm-build 0f2925
  with
rpm-build 0f2925
    End_of_file ->
rpm-build 0f2925
      Obj.magic r.tl
rpm-build 0f2925
rpm-build 0f2925
let buf_len = 8192
rpm-build 0f2925
rpm-build 0f2925
let input_all ic =
rpm-build 0f2925
  let rec loop acc total buf ofs =
rpm-build 0f2925
    let n = input ic buf ofs (buf_len - ofs) in
rpm-build 0f2925
    if n = 0 then
rpm-build 0f2925
      let res = Bytes.create total in
rpm-build 0f2925
      let pos = total - ofs in
rpm-build 0f2925
      let _ = Bytes.blit buf 0 res pos ofs in
rpm-build 0f2925
      let coll pos buf =
rpm-build 0f2925
        let new_pos = pos - buf_len in
rpm-build 0f2925
        Bytes.blit buf 0 res new_pos buf_len;
rpm-build 0f2925
        new_pos in
rpm-build 0f2925
      let _ = List.fold_left coll pos acc in
rpm-build 0f2925
      (* [res] doesn't escape and will not be mutated again *)
rpm-build 0f2925
      Bytes.unsafe_to_string res
rpm-build 0f2925
    else
rpm-build 0f2925
      let new_ofs = ofs + n in
rpm-build 0f2925
      let new_total = total + n in
rpm-build 0f2925
      if new_ofs = buf_len then
rpm-build 0f2925
        loop (buf :: acc) new_total (Bytes.create buf_len) 0
rpm-build 0f2925
      else loop acc new_total buf new_ofs in
rpm-build 0f2925
  loop [] 0 (Bytes.create buf_len) 0
rpm-build 0f2925
rpm-build 0f2925
let input_file ?(bin=false) fname =
rpm-build 0f2925
  let ch = (if bin then open_in_bin else open_in) fname in
rpm-build 0f2925
  finally (fun () -> close_in ch) input_all ch
rpm-build 0f2925
rpm-build 0f2925
let output_file ~filename ~text =
rpm-build 0f2925
  let ch = open_out filename in
rpm-build 0f2925
  finally (fun () -> close_out ch) (output_string ch) text
rpm-build 0f2925
rpm-build 0f2925
let print_bool = function
rpm-build 0f2925
  | true -> print_string "true"
rpm-build 0f2925
  | false -> print_string "false"
rpm-build 0f2925
rpm-build 0f2925
let prerr_bool = function
rpm-build 0f2925
  | true -> prerr_string "true"
rpm-build 0f2925
  | false -> prerr_string "false"
rpm-build 0f2925
rpm-build 0f2925
let string_of_char c = String.make 1 c
rpm-build 0f2925
rpm-build 0f2925
external identity : 'a -> 'a = "%identity"
rpm-build 0f2925
rpm-build 0f2925
let rec dump r =
rpm-build 0f2925
  if Obj.is_int r then
rpm-build 0f2925
    string_of_int (Obj.magic r : int)
rpm-build 0f2925
  else (* Block. *)
rpm-build 0f2925
  let rec get_fields acc = function
rpm-build 0f2925
    | 0 -> acc
rpm-build 0f2925
    | n -> let n = n-1 in get_fields (Obj.field r n :: acc) n
rpm-build 0f2925
  in
rpm-build 0f2925
    let rec is_list r =
rpm-build 0f2925
    if Obj.is_int r then
rpm-build 0f2925
      r = Obj.repr 0 (* [] *)
rpm-build 0f2925
    else
rpm-build 0f2925
      let s = Obj.size r and t = Obj.tag r in
rpm-build 0f2925
      t = 0 && s = 2 && is_list (Obj.field r 1) (* h :: t *)
rpm-build 0f2925
  in
rpm-build 0f2925
    let rec get_list r =
rpm-build 0f2925
    if Obj.is_int r then
rpm-build 0f2925
      []
rpm-build 0f2925
    else 
rpm-build 0f2925
      let h = Obj.field r 0 and t = get_list (Obj.field r 1) in
rpm-build 0f2925
      h :: t
rpm-build 0f2925
    in
rpm-build 0f2925
    let opaque name =
rpm-build 0f2925
    (* XXX In future, print the address of value 'r'.  Not possible in
rpm-build 0f2925
    * pure OCaml at the moment.
rpm-build 0f2925
    *)
rpm-build 0f2925
    "<" ^ name ^ ">"
rpm-build 0f2925
    in
rpm-build 0f2925
    let s = Obj.size r and t = Obj.tag r in
rpm-build 0f2925
    (* From the tag, determine the type of block. *)
rpm-build 0f2925
  match t with 
rpm-build 0f2925
  | _ when is_list r ->
rpm-build 0f2925
    let fields = get_list r in
rpm-build 0f2925
    "[" ^ String.concat "; " (List.map dump fields) ^ "]"
rpm-build 0f2925
  | 0 ->
rpm-build 0f2925
    let fields = get_fields [] s in
rpm-build 0f2925
    "(" ^ String.concat ", " (List.map dump fields) ^ ")"
rpm-build 0f2925
  | x when x = Obj.lazy_tag ->
rpm-build 0f2925
    (* Note that [lazy_tag .. forward_tag] are < no_scan_tag.  Not
rpm-build 0f2925
    * clear if very large constructed values could have the same
rpm-build 0f2925
    * tag. XXX *)
rpm-build 0f2925
    opaque "lazy"
rpm-build 0f2925
  | x when x = Obj.closure_tag ->
rpm-build 0f2925
    opaque "closure"
rpm-build 0f2925
  | x when x = Obj.object_tag ->
rpm-build 0f2925
    let fields = get_fields [] s in
rpm-build 0f2925
    let clasz, id, slots =
rpm-build 0f2925
      match fields with
rpm-build 0f2925
      | h::h'::t -> h, h', t 
rpm-build 0f2925
      | _ -> assert false
rpm-build 0f2925
    in
rpm-build 0f2925
    (* No information on decoding the class (first field).  So just print
rpm-build 0f2925
    * out the ID and the slots. *)
rpm-build 0f2925
    "Object #" ^ dump id ^ " (" ^ String.concat ", " (List.map dump slots) ^ ")"
rpm-build 0f2925
    | x when x = Obj.infix_tag ->
rpm-build 0f2925
    opaque "infix"
rpm-build 0f2925
    | x when x = Obj.forward_tag ->
rpm-build 0f2925
    opaque "forward"
rpm-build 0f2925
  | x when x < Obj.no_scan_tag ->
rpm-build 0f2925
    let fields = get_fields [] s in
rpm-build 0f2925
    "Tag" ^ string_of_int t ^
rpm-build 0f2925
    " (" ^ String.concat ", " (List.map dump fields) ^ ")"
rpm-build 0f2925
  | x when x = Obj.string_tag ->
rpm-build 0f2925
    "\"" ^ String.escaped (Obj.magic r : string) ^ "\""
rpm-build 0f2925
  | x when x = Obj.double_tag ->
rpm-build 0f2925
    string_of_float (Obj.magic r : float)
rpm-build 0f2925
  | x when x = Obj.abstract_tag ->
rpm-build 0f2925
    opaque "abstract"
rpm-build 0f2925
  | x when x = Obj.custom_tag ->
rpm-build 0f2925
    opaque "custom"
rpm-build 0f2925
  | x when x = Obj.double_array_tag ->
rpm-build 0f2925
    let l = ExtList.List.init s (fun i -> string_of_float (Obj.double_field r i)) in
rpm-build 0f2925
    "[| " ^ String.concat "; " l ^ " |]"
rpm-build 0f2925
  | _ ->
rpm-build 0f2925
    opaque (Printf.sprintf "unknown: tag %d size %d" t s)
rpm-build 0f2925
rpm-build 0f2925
let dump v = dump (Obj.repr v)
rpm-build 0f2925
rpm-build 0f2925
let print v = print_endline (dump v)
rpm-build 0f2925
rpm-build 0f2925
let __unique_counter = ref 0
rpm-build 0f2925
rpm-build 0f2925
let unique () =
rpm-build 0f2925
  incr __unique_counter;
rpm-build 0f2925
  !__unique_counter