diff -Naur ocaml-3.10.0/asmrun/backtrace.c ocaml-3.10.0-backtrace/asmrun/backtrace.c --- ocaml-3.10.0/asmrun/backtrace.c 2007-08-02 18:42:24.000000000 +0000 +++ ocaml-3.10.0-backtrace/asmrun/backtrace.c 2007-09-04 17:46:00.000000000 +0000 @@ -97,7 +97,7 @@ /* Print a backtrace */ -static void print_location(int index, frame_descr * d) +static int snprint_location(char *s, int len, int index, frame_descr * d) { uintnat infoptr; uint32 info1, info2, k, n, l, a, b; @@ -106,7 +106,7 @@ /* If no debugging information available, print nothing. When everything is compiled with -g, this corresponds to compiler-inserted re-raise operations. */ - if ((d->frame_size & 1) == 0) return; + if ((d->frame_size & 1) == 0) return 0; /* Recover debugging info */ infoptr = ((uintnat) d + sizeof(char *) + sizeof(short) + sizeof(short) + @@ -136,14 +136,60 @@ else kind = "Called from"; - fprintf(stderr, "%s file \"%s\", line %d, characters %d-%d\n", - kind, ((char *) infoptr) + n, l, a, b); + char *fmt = "%s file \"%s\", line %d, characters %d-%d\n"; + if (s) + return snprintf(s, len, fmt, kind, ((char *) infoptr) + n, l, a, b); + else { + fprintf(stderr, fmt, kind, ((char *) infoptr) + n, l, a, b); + return 0; + } } -void caml_print_exception_backtrace(void) +static int snprint_exception_backtrace(char *s, int len) { int i; + int total_chars = 0; for (i = 0; i < caml_backtrace_pos; i++) - print_location(i, (frame_descr *) caml_backtrace_buffer[i]); + { + int chars = snprint_location(s, len, i, (frame_descr *) caml_backtrace_buffer[i]); + total_chars += chars; + s += chars; + len -= chars; + } + return total_chars; +} + +void caml_print_exception_backtrace(void) +{ + snprint_exception_backtrace(0, 0); +} + +CAMLprim value caml_sprint_backtrace(value sv) +{ + if (caml_backtrace_active) + { + int len = caml_string_length(sv); + char *s = String_val(sv); + int chars = snprint_exception_backtrace(s, len); + return Val_int(chars); + } + else + return Val_int(0); +} + +CAMLprim value caml_capture_backtrace(value on) +{ + if (Bool_val(on)) + { + caml_backtrace_active = 1; + caml_register_global_root(&caml_backtrace_last_exn); + } + else + { + caml_backtrace_active = 0; + caml_remove_global_root(&caml_backtrace_last_exn); + caml_backtrace_last_exn = Val_unit; + } + return Val_unit; } diff -Naur ocaml-3.10.0/byterun/Makefile ocaml-3.10.0-backtrace/byterun/Makefile --- ocaml-3.10.0/byterun/Makefile 2007-08-02 18:42:24.000000000 +0000 +++ ocaml-3.10.0-backtrace/byterun/Makefile 2007-08-02 19:25:23.000000000 +0000 @@ -29,7 +29,7 @@ DOBJS=$(OBJS:.o=.d.o) instrtrace.d.o -PRIMS=alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c \ +PRIMS=alloc.c array.c backtrace.c compare.c extern.c floats.c gc_ctrl.c hash.c \ intern.c interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c \ signals.c str.c sys.c terminfo.c callback.c weak.c finalise.c stacks.c \ dynlink.c diff -Naur ocaml-3.10.0/byterun/backtrace.c ocaml-3.10.0-backtrace/byterun/backtrace.c --- ocaml-3.10.0/byterun/backtrace.c 2007-08-02 18:42:24.000000000 +0000 +++ ocaml-3.10.0-backtrace/byterun/backtrace.c 2007-09-04 17:46:00.000000000 +0000 @@ -168,7 +168,7 @@ /* Print the location corresponding to the given PC */ -static void print_location(value events, int index) +static int snprint_location(char *s, int len, value events, int index) { code_t pc = caml_backtrace_buffer[index]; char * info; @@ -177,7 +177,7 @@ ev = event_for_location(events, pc); if (caml_is_instruction(*pc, RAISE)) { /* Ignore compiler-inserted raise */ - if (ev == Val_false) return; + if (ev == Val_false) return 0; /* Initial raise if index == 0, re-raise otherwise */ if (index == 0) info = "Raised at"; @@ -190,7 +190,13 @@ info = "Called from"; } if (ev == Val_false) { - fprintf(stderr, "%s unknown location\n", info); + char *fmt = "%s unknown location\n"; + if (s) + return snprintf(s, len, fmt, info); + else { + fprintf(stderr, fmt, info); + return 0; + } } else { value ev_start = Field (Field (ev, EV_LOC), LOC_START); char *fname = String_val (Field (ev_start, POS_FNAME)); @@ -199,24 +205,74 @@ - Int_val (Field (ev_start, POS_BOL)); int endchr = Int_val (Field (Field (Field (ev, EV_LOC), LOC_END), POS_CNUM)) - Int_val (Field (ev_start, POS_BOL)); - fprintf (stderr, "%s file \"%s\", line %d, characters %d-%d\n", info, fname, - lnum, startchr, endchr); + char *fmt = "%s file \"%s\", line %d, characters %d-%d\n"; + if (s) + return snprintf (s, len, fmt, info, fname, lnum, startchr, endchr); + else { + fprintf (stderr, fmt, info, fname,lnum, startchr, endchr); + return 0; + } } } /* Print a backtrace */ -CAMLexport void caml_print_exception_backtrace(void) +static int snprint_exception_backtrace(char *s, int len) { value events; int i; events = read_debug_info(); if (events == Val_false) { - fprintf(stderr, - "(Program not linked with -g, cannot print stack backtrace)\n"); - return; + char *fmt = "(Program not linked with -g, cannot print stack backtrace)\n"; + if (s) + return snprintf(s, len, fmt); + else { + fprintf(stderr, fmt); + return 0; + } } + int total_chars = 0; for (i = 0; i < caml_backtrace_pos; i++) - print_location(events, i); + { + int chars = snprint_location(s, len, events, i); + total_chars += chars; + s += chars; + len -= chars; + } + return total_chars; +} + +CAMLexport void caml_print_exception_backtrace(void) +{ + snprint_exception_backtrace(0, 0); +} + +CAMLprim value caml_sprint_backtrace(value sv) +{ + if (caml_backtrace_active) + { + int len = caml_string_length(sv); + char *s = String_val(sv); + int chars = snprint_exception_backtrace(s, len); + return Val_int(chars); + } + else + return Val_int(0); +} + +CAMLprim value caml_capture_backtrace(value on) +{ + if (Bool_val(on)) + { + caml_backtrace_active = 1; + caml_register_global_root(&caml_backtrace_last_exn); + } + else + { + caml_backtrace_active = 0; + caml_remove_global_root(&caml_backtrace_last_exn); + caml_backtrace_last_exn = Val_unit; + } + return Val_unit; } diff -Naur ocaml-3.10.0/stdlib/printexc.ml ocaml-3.10.0-backtrace/stdlib/printexc.ml --- ocaml-3.10.0/stdlib/printexc.ml 2007-03-30 20:30:16.000000000 +0000 +++ ocaml-3.10.0-backtrace/stdlib/printexc.ml 2007-09-04 18:53:36.000000000 +0000 @@ -13,6 +13,9 @@ (* $Id: printexc.ml,v 1.18 2004/01/16 15:24:02 doligez Exp $ *) +external capture_backtrace : bool -> unit = "caml_capture_backtrace";; +external sprint_backtrace : string -> int = "caml_sprint_backtrace";; + open Printf;; let locfmt = format_of_string "File \"%s\", line %d, characters %d-%d: %s";; diff -Naur ocaml-3.10.0/stdlib/printexc.mli ocaml-3.10.0-backtrace/stdlib/printexc.mli --- ocaml-3.10.0/stdlib/printexc.mli 2007-03-30 20:30:16.000000000 +0000 +++ ocaml-3.10.0-backtrace/stdlib/printexc.mli 2007-09-04 18:28:58.000000000 +0000 @@ -15,6 +15,16 @@ (** Facilities for printing exceptions. *) +(* UNCOMMENT +val capture_backtrace : bool -> unit +(** [Printexc.capture_backtrace b] turns the capturing of backtraces + on if [b] is true, otherwise turns it off. *) + +val sprint_backtrace : string -> int +(** [Printexc.sprint_backtrace s] prints the latest exception + backtrace into [s] and returns the number of characters written. *) +*) + val to_string : exn -> string (** [Printexc.to_string e] returns a string representation of the exception [e]. *)