summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/camlp4/Camlp4/ErrorHandler.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/camlp4/Camlp4/ErrorHandler.ml')
-rw-r--r--ocaml-binary-annot/camlp4/Camlp4/ErrorHandler.ml171
1 files changed, 171 insertions, 0 deletions
diff --git a/ocaml-binary-annot/camlp4/Camlp4/ErrorHandler.ml b/ocaml-binary-annot/camlp4/Camlp4/ErrorHandler.ml
new file mode 100644
index 0000000000..231efed904
--- /dev/null
+++ b/ocaml-binary-annot/camlp4/Camlp4/ErrorHandler.ml
@@ -0,0 +1,171 @@
+(****************************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* INRIA Rocquencourt *)
+(* *)
+(* Copyright 2006 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed under *)
+(* the terms of the GNU Library General Public License, with the special *)
+(* exception on linking described in LICENSE at the top of the Objective *)
+(* Caml source tree. *)
+(* *)
+(****************************************************************************)
+
+(* Authors:
+ * - Daniel de Rauglaudre: initial version
+ * - Nicolas Pouillard: refactoring
+ *)
+(* camlp4r *)
+
+open Format;
+
+module ObjTools = struct
+
+ value desc obj =
+ if Obj.is_block obj then
+ "tag = " ^ string_of_int (Obj.tag obj)
+ else "int_val = " ^ string_of_int (Obj.obj obj);
+
+ (*Imported from the extlib*)
+ value rec to_string r =
+ if Obj.is_int r then
+ let i = (Obj.magic r : int)
+ in string_of_int i ^ " | CstTag" ^ string_of_int (i + 1)
+ else (* Block. *)
+ let rec get_fields acc =
+ fun
+ [ 0 -> acc
+ | n -> let n = n-1 in get_fields [Obj.field r n :: acc] n ]
+ in
+ let rec is_list r =
+ if Obj.is_int r then
+ r = Obj.repr 0 (* [] *)
+ else
+ let s = Obj.size r and t = Obj.tag r in
+ t = 0 && s = 2 && is_list (Obj.field r 1) (* h :: t *)
+ in
+ let rec get_list r =
+ if Obj.is_int r then []
+ else let h = Obj.field r 0 and t = get_list (Obj.field r 1) in [h :: t]
+ in
+ let opaque name =
+ (* XXX In future, print the address of value 'r'. Not possible in
+ * pure OCaml at the moment.
+ *)
+ "<" ^ name ^ ">"
+ in
+ let s = Obj.size r and t = Obj.tag r in
+ (* From the tag, determine the type of block. *)
+ match t with
+ [ _ when is_list r ->
+ let fields = get_list r in
+ "[" ^ String.concat "; " (List.map to_string fields) ^ "]"
+ | 0 ->
+ let fields = get_fields [] s in
+ "(" ^ String.concat ", " (List.map to_string fields) ^ ")"
+ | x when x = Obj.lazy_tag ->
+ (* Note that [lazy_tag .. forward_tag] are < no_scan_tag. Not
+ * clear if very large constructed values could have the same
+ * tag. XXX *)
+ opaque "lazy"
+ | x when x = Obj.closure_tag ->
+ opaque "closure"
+ | x when x = Obj.object_tag ->
+ let fields = get_fields [] s in
+ let (_class, id, slots) =
+ match fields with
+ [ [h; h'::t] -> (h, h', t)
+ | _ -> assert False ]
+ in
+ (* No information on decoding the class (first field). So just print
+ * out the ID and the slots. *)
+ "Object #" ^ to_string id ^ " (" ^ String.concat ", " (List.map to_string slots) ^ ")"
+ | x when x = Obj.infix_tag ->
+ opaque "infix"
+ | x when x = Obj.forward_tag ->
+ opaque "forward"
+ | x when x < Obj.no_scan_tag ->
+ let fields = get_fields [] s in
+ "Tag" ^ string_of_int t ^
+ " (" ^ String.concat ", " (List.map to_string fields) ^ ")"
+ | x when x = Obj.string_tag ->
+ "\"" ^ String.escaped (Obj.magic r : string) ^ "\""
+ | x when x = Obj.double_tag ->
+ string_of_float (Obj.magic r : float)
+ | x when x = Obj.abstract_tag ->
+ opaque "abstract"
+ | x when x = Obj.custom_tag ->
+ opaque "custom"
+ | x when x = Obj.final_tag ->
+ opaque "final"
+ | _ ->
+ failwith ("ObjTools.to_string: unknown tag (" ^ string_of_int t ^ ")") ];
+
+ value print ppf x = fprintf ppf "%s" (to_string x);
+ value print_desc ppf x = fprintf ppf "%s" (desc x);
+
+end;
+
+value default_handler ppf x = do {
+ let x = Obj.repr x;
+ fprintf ppf "Camlp4: Uncaught exception: %s"
+ (Obj.obj (Obj.field (Obj.field x 0) 0) : string);
+ if Obj.size x > 1 then do {
+ pp_print_string ppf " (";
+ for i = 1 to Obj.size x - 1 do
+ if i > 1 then pp_print_string ppf ", " else ();
+ ObjTools.print ppf (Obj.field x i);
+ done;
+ pp_print_char ppf ')'
+ }
+ else ();
+ fprintf ppf "@."
+};
+
+value handler = ref (fun ppf default_handler exn -> default_handler ppf exn);
+
+value register f =
+ let current_handler = handler.val in
+ handler.val :=
+ fun ppf default_handler exn ->
+ try f ppf exn with exn -> current_handler ppf default_handler exn;
+
+module Register (Error : Sig.Error) = struct
+ let current_handler = handler.val in
+ handler.val :=
+ fun ppf default_handler ->
+ fun [ Error.E x -> Error.print ppf x
+ | x -> current_handler ppf default_handler x ];
+end;
+
+
+value gen_print ppf default_handler =
+ fun
+ [ Out_of_memory -> fprintf ppf "Out of memory"
+ | Assert_failure (file, line, char) ->
+ fprintf ppf "Assertion failed, file %S, line %d, char %d"
+ file line char
+ | Match_failure (file, line, char) ->
+ fprintf ppf "Pattern matching failed, file %S, line %d, char %d"
+ file line char
+ | Failure str -> fprintf ppf "Failure: %S" str
+ | Invalid_argument str -> fprintf ppf "Invalid argument: %S" str
+ | Sys_error str -> fprintf ppf "I/O error: %S" str
+ | Stream.Failure -> fprintf ppf "Parse failure"
+ | Stream.Error str -> fprintf ppf "Parse error: %s" str
+ | x -> handler.val ppf default_handler x ];
+
+value print ppf = gen_print ppf default_handler;
+
+value try_print ppf = gen_print ppf (fun _ -> raise);
+
+value to_string exn =
+ let buf = Buffer.create 128 in
+ let () = bprintf buf "%a" print exn in
+ Buffer.contents buf;
+
+value try_to_string exn =
+ let buf = Buffer.create 128 in
+ let () = bprintf buf "%a" try_print exn in
+ Buffer.contents buf;