Skip to content

Commit

Permalink
documents the Bap_main_event module
Browse files Browse the repository at this point in the history
also establishes equalities between it and its re-export in Bap.Std
and adds an convenience alias in the Bap_main module for the loggers.
  • Loading branch information
ivg committed Jul 15, 2020
1 parent ef6a34a commit aa598fc
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 16 deletions.
21 changes: 16 additions & 5 deletions lib/bap/bap.mli
Original file line number Diff line number Diff line change
Expand Up @@ -8943,11 +8943,12 @@ module Std : sig

(** Event subsystem.
The event subsystem is a way of communicating between different
subsystems of BAP. *)
This module is the [Bap_main_event] module extended with the
[Pritable.S] interface, kept here for backward compatibility.
*)
module Event : sig

type t = ..
type t = Bap_main_event.t = ..
type event = t = ..

(** global [stream] of events *)
Expand All @@ -8967,18 +8968,20 @@ module Std : sig

(** Logging event.*)
module Log : sig
type level =
type level = Bap_main_event.Log.level =
| Debug
| Info
| Warning
| Error

type info = {
type info = Bap_main_event.Log.info = {
level : level;
section : string;
message : string;
}


(** re-exports {!Bap_main_event.Log.Message} *)
type event += Message of info

(** [message level ~section fmt ...] send a message of the
Expand All @@ -8994,6 +8997,9 @@ module Std : sig
info "created some %s" "thing"
v} *)
val message : level -> section:string -> ('a,Format.formatter,unit) format -> 'a


(** re-exports {!Bap_main_event.Log.Progress} *)
type event += Progress of {
task : string; (** hierarchical task name *)
note : string option; (** a short note *)
Expand Down Expand Up @@ -9655,6 +9661,11 @@ module Std : sig
If run in a standalone mode, then field [name] would be set to
[Sys.executable_name] and [argv] to [Sys.argv].
Note: this module uses the [Event.Self()] module and extends it
with several more fields, such as [name], [version], [doc], and
[argv]. It is recommended to use [Event.Self()] aka
[Bap_main_event.Self()] instead.
*)
module Self() : sig

Expand Down
1 change: 1 addition & 0 deletions lib/bap_main/bap_main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module Format = Stdlib.Format
module Digest = Stdlib.Digest
module Filename = Stdlib.Filename
module Sys = Stdlib.Sys
module Loggers = Bap_main_event.Log.Create

let fail fmt = Printf.ksprintf invalid_arg fmt
let sprintf = Printf.sprintf
Expand Down
18 changes: 18 additions & 0 deletions lib/bap_main/bap_main.mli
Original file line number Diff line number Diff line change
Expand Up @@ -1507,3 +1507,21 @@ module Extension : sig
val register_printer : (t -> string option) -> unit
end
end


(** Use this module to insert logging functions to your scope.
E.g.,
{[
open Bap_main
include Loggers()
let main () =
debug "starting main!";
warning "Something wrong has happened: %s" "oops";
...
]}
See the {!Bap_main_event.Log.Create} for more information.
*)
module Loggers = Bap_main_event.Log.Create
128 changes: 117 additions & 11 deletions lib/bap_main/bap_main_event.mli
Original file line number Diff line number Diff line change
@@ -1,71 +1,177 @@
(** Event subsystem.
The event subsystem is a way of communicating between different
components of BAP.
*)

open Bap_future.Std
open Bap_plugins.Std

type t = ..
type event = t = ..


(** the global stream of events *)
val stream : t stream


(** [send event] sends the [event] to the global stream of events [stream]. *)
val send : t -> unit


(** [register_printer f] when event [e] is printed, [f e] must be
(** [register_printer f] when the event [e] is printed, [f e] must be
[None] if [f] is not a subset of events, that is intended to be
printed by an [f]. If it is [Some str], then [str] is printed
printed by [f]. If it is [Some str], then [str] is printed
out.
If more than one printer returns [Some thing] for the same event,
then the last registered has the precedence.
*)
val register_printer : (t -> string option) -> unit


(** Logging Events *)
module Log : sig


(** predefined log levels *)
type level =
| Debug
| Info
| Warning
| Error


(** each logging message carries this inforamtion *)
type info = {
level : level;
section : string;
message : string;
level : level; (** the event importance *)
section : string; (** the event section, e.g., plugin name *)
message : string; (** the actual message *)
}

type event += Message of info


(** the progress bar message *)
type event += Progress of {
task : string;
note : string option;
stage : int option;
total : int option;
task : string; (** the task name *)
note : string option; (** an additional note *)
stage : int option; (** the current stage *)
total : int option; (** the total number of stages *)
}


(** [progress message] sends the progress report message.
See the [report_progress] function for the detailed
description.
*)
val progress : ?note:string -> ?stage:int -> ?total:int -> string -> unit

(** [message level ~section "my message: %s" "hello"] constructs
and sends the logging message.
*)
val message : level -> section:string -> ('a,Format.formatter,unit) format -> 'a


(** generates reporters specialized to the current plugin.
Use [include Bap_main_event.Create()] to bring to the scope
logging and debugging functions.
The functions will post logging events if the corresponding
level of debugging is enabled. Right now only [BAP_DEBUG] and
[BAP_DEBUG_<plugin>] environment variables are consulted to
enable/disable the events of the {!Log.Debug} level. When
neither of these variables is set, the [debug] function will be
a no-op.
*)
module Create() : sig
open Format


(** [debug "my message: %s" "hello"] sends the debugging message. *)
val debug : ('a,formatter,unit) format -> 'a

(** [info "my message: %s" "hello"] sends the info message. *)
val info : ('a,formatter,unit) format -> 'a

(** [warning "my message: %s" "hello"] sends the warning message. *)
val warning : ('a,formatter,unit) format -> 'a

(** [error "my message: %s" "hello"] sends the error message. *)
val error : ('a,formatter,unit) format -> 'a

(** [report_progress ~task:t ~note:n ~state:s ~total:s' ()] reports
a progress of the task [t].
Reports that the task [t] made a progress to the stage [s] out
the total number of stages [s']. The note [n] may provide an
additional textual explanation of the current stage. The report
doesn't mean that the stage is finished, but rather that it is
entered. Thus for [s'] stages we expect to receive [s'-1]
reports. (This approach works fine with functional programming
and iterating - as in functional programming it is more
convenient to report before computation, and during the indexed
iteration the index of the last element is one less than the
total number of elements).
All parameters are optional, and have the following default
values if not specified:
@param task defaults to the plugin [name];
@param note defaults to the empty string;
@param stage defaults to [None]
@param total defaults to [None] or to the last value of this
parameter for the given task.
The [report_progress] bar is an easy way to provide some
feedback to the system, either in the form of a progress (if the
total number of stages is known) or in the form of a friendly
ping back.
The mechanism should be used by analyses that expect to take
some time to complete. Usually, one plugin implements only one
task, so the task name may be omitted. If an analysis is built
from several tasks, then they can be represented as subtasks,
and the main task should represent the whole work.
Example:
{[
let find_interesting_points prog =
report_progress ~task:"discover" ~total:(Term.length sub_t prog) ();
Term.enum sub_t prog |> Seq.concat_mapi ~f:(fun stage sub ->
report_progress ~note:(Sub.name sub) ~task:"discover" ~stage ();
interesting_points_of_sub sub)
let check_interesting_points points =
report_progress ~task:"checking" ~total:(Seq.length points) ();
Seq.iteri ~f:(fun stage p ->
report_progress ~note:(Point.name p) ~task:"checking" ~stage ();
check_point p)
]}
*)
val report_progress :
?task:string ->
?note:string ->
?stage:int ->
?total:int -> unit -> unit


(** the formatter that could be used to send debug messages. *)
val debug_formatter : formatter

(** the formatter that could be used to send info messages. *)
val info_formatter : formatter

(** the formatter that could be used to send warnings. *)
val warning_formatter : formatter

(** the formatter that could be used to send errors *)
val error_formatter : formatter
end

end

(** [pp ppf event] outputs [event] to the formatter [ppf]. *)
val pp : Format.formatter -> t -> unit

0 comments on commit aa598fc

Please sign in to comment.