OSDN Git Service

c337c014fe65d132f75c0b0630852ecb2d39f33e
[luatex-ja/luatexja.git] / src / ltj-debug.lua
1 --
2 -- ltj-debug.lua
3 --
4 local ltjdbg = {}
5 luatexja.debug = ltjdbg
6 local table, string = table, string
7
8 -------------------- pretty-print
9
10 local function get_serialize_param()
11   return table.serialize_functions,
12          table.serialize_compact,
13          table.serialize_inline
14 end
15 local function set_serialize_param(s_f, s_c, s_i)
16   table.serialize_functions = s_f
17   table.serialize_compact = s_c
18   table.serialize_inline = s_i
19 end
20
21 local function normal_serialize(t)
22   local s_f, s_c, s_i = get_serialize_param()
23   set_serialize_param(true, true, true)
24   local ret = table.serialize(t, false, false, true)
25   set_serialize_param(s_f, s_c, s_i)
26   return ret
27 end
28
29 local function table_tosource(t)
30   if not next(t) then return "{}" end
31   local res_n = "\127"..normal_serialize({t}).."\127"
32   local s, e, cap = res_n:find("\127{\n ({ .* }),\n}\127")
33   if s == 1 and e == res_n:len() then return cap
34   else return normal_serialize(t)
35   end
36 end
37 ltjdbg.table_tosource = table_tosource
38
39 local function function_tosource(f)
40   local res = normal_serialize({f})
41   return res:sub(4, res:len() - 3)
42 end
43 ltjdbg.function_tosource = function_tosource
44
45 --! 値 v をそれを表すソース文字列に変換する.
46 --! lualibs の table.serialize() の処理を利用している.
47 local function tosource(v)
48   local tv = type(v)
49   if tv == "function" then return function_tosource(v)
50   elseif tv == "table" then return table_tosource(v)
51   elseif tv == "string" then return string.format('%q', v)
52   else return tostring(v)
53   end
54 end
55 ltjdbg.tosource = tosource
56
57 local function coerce(f, v)
58   if f == "q" then return "s", tosource(v)
59   elseif f == "s" then return f, tostring(v)
60   else return f, tonumber(v) or 0
61   end
62 end
63
64 local function do_pformat(fmt, ...)
65   fmt = fmt:gsub("``", "\127"):gsub("`", "%%"):gsub("\127", "`")
66   local i, na, a = 0, {}, {...}
67   local function proc(p, f)
68     i = i + 1; f, na[i] = coerce(f, a[i])
69     return p..f
70   end
71   fmt = fmt:gsub("(%%[-+#]?[%d%.]*)([a-zA-Z])", proc)
72   return fmt:format(unpack(na))
73 end
74
75 --! string.format() の拡張版. 以下の点が異なる.
76 --!  - %q は全ての型について tosource() に変換
77 --!  - <%> の代わりに <`> も使える (TeX での使用のため)
78 --!  - %d, %s 等でキャストを行う
79 local function pformat(fmt, ...)
80   if type(fmt) == "string" then
81     return do_pformat(fmt, ...)
82   else 
83     return tosource(fmt)
84   end
85 end
86 ltjdbg.pformat = pformat
87
88 -------------------- 所要時間合計
89 require("socket")
90 do
91    local max = math.max
92    local gettime = socket.gettime
93    local time_stat = {}
94    local function start_time_measure(n)
95       if not time_stat[n] then
96          time_stat[n] = {1, -gettime()}
97       else
98          local t = time_stat[n]
99          t[1], t[2] = t[1]+1, t[2]-gettime()
100       end
101    end
102    local function stop_time_measure(n)
103       local t = time_stat[n]
104       t[2] = t[2] + gettime()
105    end
106
107    local function print_measure()
108       stop_time_measure('RUN')
109       local temp = {}
110       for i,v in pairs(time_stat) do
111          temp[#temp+1] = { i, v[1], v[2], v[2]/v[1] }
112       end
113       table.sort(temp, function (a,b) return (a[4]>b[4]) end)
114       print()
115       print('desc', 'ave. (us)', 'times', 'total (ms)')
116       for _,v in ipairs(temp) do
117          print ((v[1] .. '                '):sub(1,16), 1000000*v[4], v[2], 1000*v[3])
118       end
119    end
120    if luatexja.base then
121       luatexja.base.start_time_measure = start_time_measure
122       luatexja.base.stop_time_measure = stop_time_measure
123       luatexbase.add_to_callback('stop_run', print_measure, 'luatexja.time_measure', 1)
124       luatexbase.add_to_callback('pre_linebreak_filter', 
125                                  function(p) 
126                                     start_time_measure('tex_linebreak'); return p 
127                                  end, 
128                                  'measure_tex_linebreak', 20000)
129    end
130 end
131
132 -------------------- debug logging
133 do
134 local debug_show_term = true
135 local debug_show_log = true
136 --! デバッグログを端末に出力するか
137 local function show_term(v)
138   debug_show_term = v
139 end
140 ltjdbg.show_term = show_term
141 --! デバッグログをログファイルに出力するか
142 function show_log(v)
143   debug_show_log = v
144 end
145 ltjdbg.show_log = show_log
146
147 local function write_debug_log(s)
148   local target
149   if debug_show_term and debug_show_log then
150     texio.write_nl("term and log", s)
151   elseif debug_show_term and not debug_show_log then
152     texio.write_nl("term", s)
153   elseif not debug_show_term and debug_show_log then
154     texio.write_nl("log", s)
155   end
156 end
157
158 --! デバッグログ出力. 引数は pformat() と同じ.
159 local function out_debug(...)
160   if debug_show_term or debug_show_log then
161     write_debug_log("%DEBUG:"..pformat(...))
162   end
163 end
164
165 --! デバッグログ出力, パッケージ名付き.
166 local function package_debug(pkg, ...)
167   if debug_show_term or debug_show_log then
168     write_debug_log("%DEBUG("..pkg.."):"..pformat(...))
169   end
170 end
171
172 --! パッケージ名付きデバッグログ出力器を得る.
173 local function debug_logger(pkg)
174   return function(...) package_debug(pkg, ...) end
175 end
176
177 if luatexja.base then
178   luatexja.base.out_debug = out_debug
179   luatexja.base.package_debug = package_debug
180   luatexja.base.debug_logger = debug_logger
181   luatexja.base.show_term = show_term
182   luatexja.base.show_log = show_log
183 end
184 end
185
186 -------------------- all done
187 -- EOF