elf_arrows/src/html_renderer.ml

97 lines
3.5 KiB
OCaml

(** HTML Renderer
Renders the output of computations on a given program as an HTML webpage.
*)
(** Generates a fresh unique identifier *)
let fresh_uuid =
let next = ref 0 in
fun () ->
let out = !next in
incr next ; out
(** Checks whether a submethod is relevant to show, or whether it should be
hidden by default. *)
let is_sub_relevant sub = Renderer.AnnotAsm.(
List.exists
(fun instr -> instr.instr_annot.Renderer.events <> [])
sub.sub_asm
)
(** Box `AnnotAsm.asm_info_t` as a Jingoo tvalue *)
let render_prog_box annotated_prog = Jingoo.Jg_types.(Renderer.AnnotAsm.(
let render_addr addr = (Format.sprintf "%04x" addr) in
List.map (fun render_sub ->
[
("sub_section", box_string render_sub.sub_section);
("sub_name", box_string render_sub.sub_name);
("sub_addr", box_string (Format.sprintf "%016x" render_sub.sub_addr));
("sub_uuid", box_int @@ fresh_uuid ());
("sub_relevant", box_int @@ (match is_sub_relevant render_sub with
| true -> 1
| false -> 0));
("sub_asm", List.map (fun row -> [
("instr_addr", box_string (render_addr row.instr_addr));
("instr_bytes", box_string (
Format.asprintf "%a" Asm_acquire.pp_hex_bytes row.instr_bytes
));
("instr_asm", box_string row.instr_asm);
("instr_events", (List.map (fun event ->
let typ, id, bound, data = Renderer.(match event with
| BoxStart(id, bound, data) -> "start", id, bound, data
| BoxEnd(id, bound, data) -> "end", id, bound, data
) in
[
("typ", box_string typ);
("id", box_int id);
("bound", box_string @@ render_addr bound);
("data", box_string @@ Format.sprintf "[%d] File %s, %d:%d"
data.box_class_id data.box_file data.box_line data.box_col);
("box_eq", box_int data.box_class_id);
] |> box_obj)
row.instr_annot.Renderer.events)
|> box_list);
] |> box_obj) render_sub.sub_asm
|> box_list;
)] |> box_obj
) annotated_prog
|> box_list
))
let render_progs_box annotated_progs = Jingoo.Jg_types.(
List.map (fun (prog_path, annotated_prog) ->
[
("path", box_string prog_path);
("prog", render_prog_box annotated_prog)
] |> box_obj)
annotated_progs
|> box_list
)
module IntSet = Set.Make(struct type t = int let compare = compare end)
let prog_box_classes render_data = Jingoo.Jg_types.(
List.fold_left (fun accu prog ->
List.fold_left (fun accu (Renderer.TaggedRange(_, _, box)) ->
IntSet.add box.box_class_id accu)
accu prog.Renderer.render_boxes)
IntSet.empty render_data
|> IntSet.elements
|> List.map box_int
|> box_list
)
(** [render multi_render_data] renders the given [render_data] to a string. *)
let render multi_render_data = Jingoo.(
let annotated_progs = List.map (fun render_data ->
render_data.Renderer.render_prog_path,
Renderer.render_data_to_annotated_asm render_data) multi_render_data in
let models = [
("progs", render_progs_box annotated_progs);
("box_classes", prog_box_classes multi_render_data);
] in
Jg_template.from_file "src/render_html.jingoo" ~models:models
)