1
|
(* This file is part of the Kind 2 model checker.
|
2
|
|
3
|
Copyright (c) 2015 by the Board of Trustees of the University of Iowa
|
4
|
|
5
|
Licensed under the Apache License, Version 2.0 (the "License"); you
|
6
|
may not use this file except in compliance with the License. You
|
7
|
may obtain a copy of the License at
|
8
|
|
9
|
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
|
11
|
Unless required by applicable law or agreed to in writing, software
|
12
|
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
14
|
implied. See the License for the specific language governing
|
15
|
permissions and limitations under the License.
|
16
|
|
17
|
*)
|
18
|
|
19
|
open KindPretty
|
20
|
open KindLib
|
21
|
|
22
|
|
23
|
(* Signature of module for reuse in Event *)
|
24
|
module type Sig = sig
|
25
|
type 'a log_printer =
|
26
|
KindLib.log_level ->
|
27
|
('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a
|
28
|
type 'a m_log_printer =
|
29
|
KindLib.kind_module -> 'a log_printer
|
30
|
val set_module : KindLib.kind_module -> unit
|
31
|
val get_module : unit -> KindLib.kind_module
|
32
|
type log_format = | F_pt | F_xml | F_json | F_relay
|
33
|
val get_log_format : unit -> log_format
|
34
|
val set_log_format : log_format -> unit
|
35
|
val set_log_format_pt : unit -> unit
|
36
|
val set_log_format_xml : unit -> unit
|
37
|
val set_log_format_json : unit -> unit
|
38
|
val set_relay_log : unit -> unit
|
39
|
val unset_relay_log : unit -> unit
|
40
|
val pp_print_kind_module_xml_src : Format.formatter -> KindLib.kind_module -> unit
|
41
|
val print_xml_trailer : unit -> unit
|
42
|
val printf_xml : 'a m_log_printer
|
43
|
val printf_json : 'a m_log_printer
|
44
|
val parse_log_xml : KindLib.log_level -> KindLib.position -> string -> unit
|
45
|
val parse_log_json : KindLib.log_level -> KindLib.position -> string -> unit
|
46
|
end
|
47
|
|
48
|
|
49
|
|
50
|
(* ********************************************************************** *)
|
51
|
(* Initialization for the messaging system *)
|
52
|
(* ********************************************************************** *)
|
53
|
|
54
|
type 'a log_printer =
|
55
|
KindLib.log_level ->
|
56
|
('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a
|
57
|
|
58
|
type 'a m_log_printer =
|
59
|
KindLib.kind_module -> 'a log_printer
|
60
|
|
61
|
(* Module currently running *)
|
62
|
let this_module = ref `Parser
|
63
|
|
64
|
(* Set module currently running *)
|
65
|
let set_module mdl = this_module := mdl
|
66
|
|
67
|
(* Get module currently running *)
|
68
|
let get_module () = !this_module
|
69
|
|
70
|
|
71
|
(* ********************************************************************** *)
|
72
|
(* State of the logger *)
|
73
|
(* ********************************************************************** *)
|
74
|
|
75
|
|
76
|
(* Log formats *)
|
77
|
type log_format =
|
78
|
| F_pt
|
79
|
| F_xml
|
80
|
| F_json
|
81
|
| F_relay
|
82
|
|
83
|
|
84
|
(* Current log format *)
|
85
|
let log_format = ref F_pt
|
86
|
let prev_log_format = ref !log_format
|
87
|
|
88
|
let get_log_format () = !log_format
|
89
|
let set_log_format l = log_format := l
|
90
|
|
91
|
|
92
|
|
93
|
|
94
|
(* ********************************************************************** *)
|
95
|
(* Plain text output *)
|
96
|
(* ********************************************************************** *)
|
97
|
|
98
|
|
99
|
(* Pretty-print kind module for plain text output *)
|
100
|
let pp_print_kind_module_pt =
|
101
|
pp_print_kind_module
|
102
|
|
103
|
|
104
|
(* Output message as plain text *)
|
105
|
let printf_pt mdl level fmt =
|
106
|
(ignore_or_fprintf level)
|
107
|
!log_ppf ("%a @[<hov>" ^^ fmt ^^ "@]@.@.") tag_of_level level
|
108
|
|
109
|
|
110
|
(* Unconditional printing as plain text. *)
|
111
|
let printf_pt_uncond mdl fmt =
|
112
|
Format.fprintf !log_ppf ("@[<hov>" ^^ fmt ^^ "@]@.@.")
|
113
|
|
114
|
|
115
|
|
116
|
(* ********************************************************************** *)
|
117
|
(* XML output *)
|
118
|
(* ********************************************************************** *)
|
119
|
|
120
|
(* Level to class attribute of log tag *)
|
121
|
let xml_cls_of_level = string_of_log_level
|
122
|
|
123
|
(* XML at the beginning the output *)
|
124
|
let print_xml_header () =
|
125
|
Format.fprintf !log_ppf "<?xml version=\"1.0\"?>@."
|
126
|
|
127
|
|
128
|
(* Pretty-print level as class attribute of log tag *)
|
129
|
let pp_print_level_xml_cls ppf l =
|
130
|
Format.fprintf ppf "%s" (xml_cls_of_level l)
|
131
|
|
132
|
(* Kind module as source attribute of log tag *)
|
133
|
let xml_src_of_kind_module = short_name_of_kind_module
|
134
|
|
135
|
(* Pretty-print kind module as source attribute of log tag *)
|
136
|
let pp_print_kind_module_xml_src ppf m =
|
137
|
Format.fprintf ppf "%s" (xml_src_of_kind_module m)
|
138
|
|
139
|
|
140
|
(* XML at the end of the output *)
|
141
|
let print_xml_trailer () =
|
142
|
Format.fprintf !log_ppf "@.@.</Results>@."
|
143
|
|
144
|
|
145
|
(* Output message as XML *)
|
146
|
let printf_xml mdl level fmt =
|
147
|
|
148
|
(ignore_or_fprintf level)
|
149
|
!log_ppf
|
150
|
("@[<hv 2><Log class=\"%a\" source=\"%a\">@,@[<hov>" ^^
|
151
|
fmt ^^
|
152
|
"@]@;<0 -2></Log>@]@.")
|
153
|
pp_print_level_xml_cls level
|
154
|
pp_print_kind_module_xml_src mdl
|
155
|
|
156
|
|
157
|
let parse_log_xml level pos msg =
|
158
|
let pp_print_fname ppf fname =
|
159
|
if fname = "" then () else
|
160
|
Format.fprintf ppf " file=\"%s\"" fname
|
161
|
in
|
162
|
let file, lnum, cnum = file_row_col_of_pos pos in
|
163
|
(ignore_or_fprintf level)
|
164
|
!log_ppf
|
165
|
"@[<hv 2><Log class=\"%a\" source=\"parse\" line=\"%d\" column=\"%d\"%a>\
|
166
|
@,@[<hov>%s@]@;<0 -2></Log>@]@."
|
167
|
pp_print_level_xml_cls level lnum cnum pp_print_fname file msg
|
168
|
|
169
|
|
170
|
(* ********************************************************************** *)
|
171
|
(* JSON output *)
|
172
|
(* ********************************************************************** *)
|
173
|
|
174
|
let escape_json_string s =
|
175
|
let backslash = Str.regexp "\\" in
|
176
|
let double_quotes = Str.regexp "\"" in
|
177
|
let newline = Str.regexp "\n" in
|
178
|
s |> Str.global_replace backslash "\\\\"
|
179
|
|> Str.global_replace double_quotes "\\\""
|
180
|
|> Str.global_replace newline "\\n"
|
181
|
|
182
|
(* Output message as JSON *)
|
183
|
let printf_json mdl level fmt =
|
184
|
|
185
|
(ignore_or_fprintf level)
|
186
|
!log_ppf
|
187
|
(",@.{@[<v 1>@," ^^
|
188
|
"\"objectType\" : \"log\",@," ^^
|
189
|
"\"level\" : \"%s\",@," ^^
|
190
|
"\"source\" : \"%s\",@," ^^
|
191
|
"\"value\" : \"" ^^ fmt ^^ "\"" ^^
|
192
|
"@]@.}@.")
|
193
|
(string_of_log_level level)
|
194
|
(short_name_of_kind_module mdl)
|
195
|
|
196
|
let parse_log_json level pos msg =
|
197
|
let pp_print_fname ppf fname =
|
198
|
if fname = "" then () else
|
199
|
Format.fprintf ppf "\"file\" : \"%s\",@," fname
|
200
|
in
|
201
|
let file, lnum, cnum = file_row_col_of_pos pos in
|
202
|
(ignore_or_fprintf level)
|
203
|
!log_ppf
|
204
|
",@.{@[<v 1>@,\
|
205
|
\"objectType\" : \"log\",@,\
|
206
|
\"level\" : \"%s\",@,\
|
207
|
\"source\" : \"parse\",@,\
|
208
|
%a\
|
209
|
\"line\" : %d,@,\
|
210
|
\"column\" : %d,@,\
|
211
|
\"value\" : \"%s\"\
|
212
|
@]@.}@.\
|
213
|
"
|
214
|
(string_of_log_level level)
|
215
|
pp_print_fname file
|
216
|
lnum cnum msg
|
217
|
|
218
|
|
219
|
(*****************************************************************)
|
220
|
(* Setup *)
|
221
|
(*****************************************************************)
|
222
|
|
223
|
(* Set log format to plain text *)
|
224
|
let set_log_format_pt () = log_format := F_pt
|
225
|
|
226
|
(* Set log format to XML *)
|
227
|
let set_log_format_xml () =
|
228
|
log_format := F_xml;
|
229
|
(* Print XML header *)
|
230
|
print_xml_header ()
|
231
|
|
232
|
(* Set log format to JSON *)
|
233
|
let set_log_format_json () = log_format := F_json
|
234
|
|
235
|
(* Relay log messages to invariant manager *)
|
236
|
let set_relay_log () =
|
237
|
prev_log_format := !log_format;
|
238
|
log_format := F_relay
|
239
|
|
240
|
|
241
|
let unset_relay_log () = log_format := !prev_log_format
|
242
|
|
243
|
|
244
|
module type SLog = sig
|
245
|
val log : 'a log_printer
|
246
|
val log_uncond : ('a, Format.formatter, unit) format -> 'a
|
247
|
end
|
248
|
|
249
|
module Make (R : sig val printf_relay : 'a m_log_printer end) : SLog = struct
|
250
|
|
251
|
(* ********************************************************************** *)
|
252
|
(* Generic logging functions *)
|
253
|
(* ********************************************************************** *)
|
254
|
|
255
|
(* Log a message with source and log level *)
|
256
|
let log level fmt =
|
257
|
|
258
|
let mdl = get_module () in
|
259
|
|
260
|
match !log_format with
|
261
|
| F_pt -> printf_pt mdl level fmt
|
262
|
| F_xml -> printf_xml mdl level fmt
|
263
|
| F_json -> printf_json mdl level fmt
|
264
|
| F_relay -> R.printf_relay mdl level fmt
|
265
|
|
266
|
|
267
|
(* Unconditionally logs a message. *)
|
268
|
let log_uncond fmt =
|
269
|
|
270
|
let mdl = get_module () in
|
271
|
|
272
|
match !log_format with
|
273
|
| F_pt -> printf_pt_uncond mdl fmt
|
274
|
| F_xml -> printf_xml mdl L_info fmt
|
275
|
| F_json -> printf_json mdl L_info fmt
|
276
|
| F_relay -> R.printf_relay mdl L_info fmt
|
277
|
|
278
|
end
|
279
|
|
280
|
|
281
|
include Make (struct let printf_relay _ _ _ = failwith "Uninitialized" end)
|
282
|
|
283
|
|
284
|
(*
|
285
|
Local Variables:
|
286
|
compile-command: "make -C .. -k"
|
287
|
tuareg-interactive-program: "./kind2.top -I ./_build -I ./_build/SExpr"
|
288
|
indent-tabs-mode: nil
|
289
|
End:
|
290
|
*)
|