選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

507 行
17 KiB

  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 1996-2009. All Rights Reserved.
  5. %%
  6. %% The contents of this file are subject to the Erlang Public License,
  7. %% Version 1.1, (the "License"); you may not use this file except in
  8. %% compliance with the License. You should have received a copy of the
  9. %% Erlang Public License along with this software. If not, it can be
  10. %% retrieved online at http://www.erlang.org/.
  11. %%
  12. %% Software distributed under the License is distributed on an "AS IS"
  13. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14. %% the License for the specific language governing rights and limitations
  15. %% under the License.
  16. %%
  17. %% %CopyrightEnd%
  18. %%
  19. %% @doc Functions from Erlang OTP distribution that are really useful
  20. %% but aren't exported.
  21. %%
  22. %% All functions in this module are covered by the Erlang/OTP source
  23. %% distribution's license, the Erlang Public License. See
  24. %% http://www.erlang.org/ for full details.
  25. -module(lager_stdlib).
  26. -export([string_p/1]).
  27. -export([write_time/2, maybe_utc/1]).
  28. -export([is_my_error_report/1, is_my_info_report/1]).
  29. -export([sup_get/2]).
  30. -export([proc_lib_format/2]).
  31. %% from error_logger_file_h
  32. string_p([]) ->
  33. false;
  34. string_p(Term) ->
  35. string_p1(Term).
  36. string_p1([H|T]) when is_integer(H), H >= $\s, H < 256 ->
  37. string_p1(T);
  38. string_p1([$\n|T]) -> string_p1(T);
  39. string_p1([$\r|T]) -> string_p1(T);
  40. string_p1([$\t|T]) -> string_p1(T);
  41. string_p1([$\v|T]) -> string_p1(T);
  42. string_p1([$\b|T]) -> string_p1(T);
  43. string_p1([$\f|T]) -> string_p1(T);
  44. string_p1([$\e|T]) -> string_p1(T);
  45. string_p1([H|T]) when is_list(H) ->
  46. case string_p1(H) of
  47. true -> string_p1(T);
  48. _ -> false
  49. end;
  50. string_p1([]) -> true;
  51. string_p1(_) -> false.
  52. %% From calendar
  53. -type year1970() :: 1970..10000. % should probably be 1970..
  54. -type month() :: 1..12.
  55. -type day() :: 1..31.
  56. -type hour() :: 0..23.
  57. -type minute() :: 0..59.
  58. -type second() :: 0..59.
  59. -type t_time() :: {hour(),minute(),second()}.
  60. -type t_datetime1970() :: {{year1970(),month(),day()},t_time()}.
  61. %% From OTP stdlib's error_logger_tty_h.erl ... These functions aren't
  62. %% exported.
  63. -spec write_time({utc, t_datetime1970()} | t_datetime1970(), string()) -> string().
  64. write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) ->
  65. io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n",
  66. [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]);
  67. write_time({{Y,Mo,D},{H,Mi,S}},Type) ->
  68. io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n",
  69. [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]).
  70. -spec maybe_utc(t_datetime1970()) -> {utc, t_datetime1970()} | t_datetime1970().
  71. maybe_utc(Time) ->
  72. UTC = case application:get_env(sasl, utc_log) of
  73. {ok, Val} ->
  74. Val;
  75. undefined ->
  76. %% Backwards compatible:
  77. case application:get_env(stdlib, utc_log) of
  78. {ok, Val} ->
  79. Val;
  80. undefined ->
  81. false
  82. end
  83. end,
  84. if
  85. UTC =:= true ->
  86. UTCTime = case calendar:local_time_to_universal_time_dst(Time) of
  87. [] -> calendar:local_time();
  88. [T0|_] -> T0
  89. end,
  90. {utc, UTCTime};
  91. true ->
  92. Time
  93. end.
  94. t(X) when is_integer(X) ->
  95. t1(integer_to_list(X));
  96. t(_) ->
  97. "".
  98. t1([X]) -> [$0,X];
  99. t1(X) -> X.
  100. month(1) -> "Jan";
  101. month(2) -> "Feb";
  102. month(3) -> "Mar";
  103. month(4) -> "Apr";
  104. month(5) -> "May";
  105. month(6) -> "Jun";
  106. month(7) -> "Jul";
  107. month(8) -> "Aug";
  108. month(9) -> "Sep";
  109. month(10) -> "Oct";
  110. month(11) -> "Nov";
  111. month(12) -> "Dec".
  112. %% From OTP sasl's sasl_report.erl ... These functions aren't
  113. %% exported.
  114. -spec is_my_error_report(atom()) -> boolean().
  115. is_my_error_report(supervisor_report) -> true;
  116. is_my_error_report(crash_report) -> true;
  117. is_my_error_report(_) -> false.
  118. -spec is_my_info_report(atom()) -> boolean().
  119. is_my_info_report(progress) -> true;
  120. is_my_info_report(_) -> false.
  121. -spec sup_get(term(), [proplists:property()]) -> term().
  122. sup_get(Tag, Report) ->
  123. case lists:keysearch(Tag, 1, Report) of
  124. {value, {_, Value}} ->
  125. Value;
  126. _ ->
  127. ""
  128. end.
  129. %% From OTP stdlib's proc_lib.erl ... These functions aren't exported.
  130. -spec proc_lib_format([term()], pos_integer()) -> string().
  131. proc_lib_format([OwnReport,LinkReport], FmtMaxBytes) ->
  132. OwnFormat = format_report(OwnReport, FmtMaxBytes),
  133. LinkFormat = format_report(LinkReport, FmtMaxBytes),
  134. %% io_lib:format here is OK because we're limiting max length elsewhere.
  135. Str = io_lib:format(" crasher:~n~s neighbours:~n~s",[OwnFormat,LinkFormat]),
  136. lists:flatten(Str).
  137. format_report(Rep, FmtMaxBytes) when is_list(Rep) ->
  138. format_rep(Rep, FmtMaxBytes);
  139. format_report(Rep, FmtMaxBytes) ->
  140. {Str, _} = lager_trunc_io:print(Rep, FmtMaxBytes),
  141. io_lib:format("~p~n", [Str]).
  142. format_rep([{initial_call,InitialCall}|Rep], FmtMaxBytes) ->
  143. [format_mfa(InitialCall, FmtMaxBytes)|format_rep(Rep, FmtMaxBytes)];
  144. format_rep([{error_info,{Class,Reason,StackTrace}}|Rep], FmtMaxBytes) ->
  145. [format_exception(Class, Reason, StackTrace, FmtMaxBytes)|format_rep(Rep, FmtMaxBytes)];
  146. format_rep([{Tag,Data}|Rep], FmtMaxBytes) ->
  147. [format_tag(Tag, Data, FmtMaxBytes)|format_rep(Rep, FmtMaxBytes)];
  148. format_rep(_, _S) ->
  149. [].
  150. format_exception(Class, Reason, StackTrace, FmtMaxBytes) ->
  151. PF = pp_fun(FmtMaxBytes),
  152. StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
  153. %% EI = " exception: ",
  154. EI = " ",
  155. [EI, lib_format_exception(1+length(EI), Class, Reason,
  156. StackTrace, StackFun, PF), "\n"].
  157. format_mfa({M,F,Args}=StartF, FmtMaxBytes) ->
  158. try
  159. A = length(Args),
  160. [" initial call: ",atom_to_list(M),$:,atom_to_list(F),$/,
  161. integer_to_list(A),"\n"]
  162. catch
  163. error:_ ->
  164. format_tag(initial_call, StartF, FmtMaxBytes)
  165. end.
  166. pp_fun(FmtMaxBytes) ->
  167. fun(Term, _I) ->
  168. {Str, _} = lager_trunc_io:print(Term, FmtMaxBytes),
  169. io_lib:format("~s", [Str])
  170. end.
  171. format_tag(Tag, Data, FmtMaxBytes) ->
  172. {Str, _} = lager_trunc_io:print(Data, FmtMaxBytes),
  173. io_lib:format(" ~p: ~s~n", [Tag, Str]).
  174. %% From OTP stdlib's lib.erl ... These functions aren't exported.
  175. lib_format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun)
  176. when is_integer(I), I >= 1, is_function(StackFun, 3),
  177. is_function(FormatFun, 2) ->
  178. Str = n_spaces(I-1),
  179. {Term,Trace1,Trace} = analyze_exception(Class, Reason, StackTrace),
  180. Expl0 = explain_reason(Term, Class, Trace1, FormatFun, Str),
  181. Expl = io_lib:fwrite(<<"~s~s">>, [exited(Class), Expl0]),
  182. case format_stacktrace1(Str, Trace, FormatFun, StackFun) of
  183. [] -> Expl;
  184. Stack -> [Expl, $\n, Stack]
  185. end.
  186. analyze_exception(error, Term, Stack) ->
  187. case {is_stacktrace(Stack), Stack, Term} of
  188. {true, [{_M,_F,As}=MFA|MFAs], function_clause} when is_list(As) ->
  189. {Term,[MFA],MFAs};
  190. {true, [{shell,F,A}], function_clause} when is_integer(A) ->
  191. {Term, [{F,A}], []};
  192. {true, [{_M,_F,_AorAs}=MFA|MFAs], undef} ->
  193. {Term,[MFA],MFAs};
  194. {true, _, _} ->
  195. {Term,[],Stack};
  196. {false, _, _} ->
  197. {{Term,Stack},[],[]}
  198. end;
  199. analyze_exception(_Class, Term, Stack) ->
  200. case is_stacktrace(Stack) of
  201. true ->
  202. {Term,[],Stack};
  203. false ->
  204. {{Term,Stack},[],[]}
  205. end.
  206. is_stacktrace([]) ->
  207. true;
  208. is_stacktrace([{M,F,A}|Fs]) when is_atom(M), is_atom(F), is_integer(A) ->
  209. is_stacktrace(Fs);
  210. is_stacktrace([{M,F,As}|Fs]) when is_atom(M), is_atom(F), length(As) >= 0 ->
  211. is_stacktrace(Fs);
  212. is_stacktrace(_) ->
  213. false.
  214. %% ERTS exit codes (some of them are also returned by erl_eval):
  215. explain_reason(badarg, error, [], _PF, _Str) ->
  216. <<"bad argument">>;
  217. explain_reason({badarg,V}, error=Cl, [], PF, Str) -> % orelse, andalso
  218. format_value(V, <<"bad argument: ">>, Cl, PF, Str);
  219. explain_reason(badarith, error, [], _PF, _Str) ->
  220. <<"bad argument in an arithmetic expression">>;
  221. explain_reason({badarity,{Fun,As}}, error, [], _PF, _Str)
  222. when is_function(Fun) ->
  223. %% Only the arity is displayed, not the arguments As.
  224. io_lib:fwrite(<<"~s called with ~s">>,
  225. [format_fun(Fun), argss(length(As))]);
  226. explain_reason({badfun,Term}, error=Cl, [], PF, Str) ->
  227. format_value(Term, <<"bad function ">>, Cl, PF, Str);
  228. explain_reason({badmatch,Term}, error=Cl, [], PF, Str) ->
  229. format_value(Term, <<"no match of right hand side value ">>, Cl, PF, Str);
  230. explain_reason({case_clause,V}, error=Cl, [], PF, Str) ->
  231. %% "there is no case clause with a true guard sequence and a
  232. %% pattern matching..."
  233. format_value(V, <<"no case clause matching ">>, Cl, PF, Str);
  234. explain_reason(function_clause, error, [{F,A}], _PF, _Str) ->
  235. %% Shell commands
  236. FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]),
  237. [<<"no function clause matching call to ">> | FAs];
  238. explain_reason(function_clause, error=Cl, [{M,F,As}], PF, Str) ->
  239. String = <<"no function clause matching ">>,
  240. format_errstr_call(String, Cl, {M,F}, As, PF, Str);
  241. explain_reason(if_clause, error, [], _PF, _Str) ->
  242. <<"no true branch found when evaluating an if expression">>;
  243. explain_reason(noproc, error, [], _PF, _Str) ->
  244. <<"no such process or port">>;
  245. explain_reason(notalive, error, [], _PF, _Str) ->
  246. <<"the node cannot be part of a distributed system">>;
  247. explain_reason(system_limit, error, [], _PF, _Str) ->
  248. <<"a system limit has been reached">>;
  249. explain_reason(timeout_value, error, [], _PF, _Str) ->
  250. <<"bad receive timeout value">>;
  251. explain_reason({try_clause,V}, error=Cl, [], PF, Str) ->
  252. %% "there is no try clause with a true guard sequence and a
  253. %% pattern matching..."
  254. format_value(V, <<"no try clause matching ">>, Cl, PF, Str);
  255. explain_reason(undef, error, [{M,F,A}], _PF, _Str) ->
  256. %% Only the arity is displayed, not the arguments, if there are any.
  257. io_lib:fwrite(<<"undefined function ~s">>,
  258. [mfa_to_string(M, F, n_args(A))]);
  259. explain_reason({shell_undef,F,A}, error, [], _PF, _Str) ->
  260. %% Give nicer reports for undefined shell functions
  261. %% (but not when the user actively calls shell_default:F(...)).
  262. io_lib:fwrite(<<"undefined shell command ~s/~w">>, [F, n_args(A)]);
  263. %% Exit codes returned by erl_eval only:
  264. explain_reason({argument_limit,_Fun}, error, [], _PF, _Str) ->
  265. io_lib:fwrite(<<"limit of number of arguments to interpreted function"
  266. " exceeded">>, []);
  267. explain_reason({bad_filter,V}, error=Cl, [], PF, Str) ->
  268. format_value(V, <<"bad filter ">>, Cl, PF, Str);
  269. explain_reason({bad_generator,V}, error=Cl, [], PF, Str) ->
  270. format_value(V, <<"bad generator ">>, Cl, PF, Str);
  271. explain_reason({unbound,V}, error, [], _PF, _Str) ->
  272. io_lib:fwrite(<<"variable ~w is unbound">>, [V]);
  273. %% Exit codes local to the shell module (restricted shell):
  274. explain_reason({restricted_shell_bad_return, V}, exit=Cl, [], PF, Str) ->
  275. String = <<"restricted shell module returned bad value ">>,
  276. format_value(V, String, Cl, PF, Str);
  277. explain_reason({restricted_shell_disallowed,{ForMF,As}},
  278. exit=Cl, [], PF, Str) ->
  279. %% ForMF can be a fun, but not a shell fun.
  280. String = <<"restricted shell does not allow ">>,
  281. format_errstr_call(String, Cl, ForMF, As, PF, Str);
  282. explain_reason(restricted_shell_started, exit, [], _PF, _Str) ->
  283. <<"restricted shell starts now">>;
  284. explain_reason(restricted_shell_stopped, exit, [], _PF, _Str) ->
  285. <<"restricted shell stopped">>;
  286. %% Other exit code:
  287. explain_reason(Reason, Class, [], PF, Str) ->
  288. PF(Reason, (iolist_size(Str)+1) + exited_size(Class)).
  289. n_spaces(N) ->
  290. lists:duplicate(N, $\s).
  291. exited_size(Class) ->
  292. iolist_size(exited(Class)).
  293. exited(error) ->
  294. <<"exception error: ">>;
  295. exited(exit) ->
  296. <<"exception exit: ">>;
  297. exited(throw) ->
  298. <<"exception throw: ">>.
  299. format_stacktrace1(S0, Stack0, PF, SF) ->
  300. Stack1 = lists:dropwhile(fun({M,F,A}) -> SF(M, F, A)
  301. end, lists:reverse(Stack0)),
  302. S = [" " | S0],
  303. Stack = lists:reverse(Stack1),
  304. format_stacktrace2(S, Stack, 1, PF).
  305. format_stacktrace2(S, [{M,F,A}|Fs], N, PF) when is_integer(A) ->
  306. [io_lib:fwrite(<<"~s~s ~s">>,
  307. [sep(N, S), origin(N, M, F, A), mfa_to_string(M, F, A)])
  308. | format_stacktrace2(S, Fs, N + 1, PF)];
  309. format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) ->
  310. A = length(As),
  311. CalledAs = [S,<<" called as ">>],
  312. C = format_call("", CalledAs, {M,F}, As, PF),
  313. [io_lib:fwrite(<<"~s~s ~s\n~s~s">>,
  314. [sep(N, S), origin(N, M, F, A), mfa_to_string(M, F, A),
  315. CalledAs, C])
  316. | format_stacktrace2(S, Fs, N + 1, PF)];
  317. format_stacktrace2(_S, [], _N, _PF) ->
  318. "".
  319. argss(0) ->
  320. <<"no arguments">>;
  321. argss(1) ->
  322. <<"one argument">>;
  323. argss(2) ->
  324. <<"two arguments">>;
  325. argss(I) ->
  326. io_lib:fwrite(<<"~w arguments">>, [I]).
  327. format_value(V, ErrStr, Class, PF, Str) ->
  328. Pre1Sz = exited_size(Class),
  329. Str1 = PF(V, Pre1Sz + iolist_size([Str, ErrStr])+1),
  330. [ErrStr | case count_nl(Str1) of
  331. N1 when N1 > 1 ->
  332. Str2 = PF(V, iolist_size(Str) + 1 + Pre1Sz),
  333. case count_nl(Str2) < N1 of
  334. true ->
  335. [$\n, Str, n_spaces(Pre1Sz) | Str2];
  336. false ->
  337. Str1
  338. end;
  339. _ ->
  340. Str1
  341. end].
  342. format_fun(Fun) when is_function(Fun) ->
  343. {module, M} = erlang:fun_info(Fun, module),
  344. {name, F} = erlang:fun_info(Fun, name),
  345. {arity, A} = erlang:fun_info(Fun, arity),
  346. case erlang:fun_info(Fun, type) of
  347. {type, local} when F =:= "" ->
  348. io_lib:fwrite(<<"~w">>, [Fun]);
  349. {type, local} when M =:= erl_eval ->
  350. io_lib:fwrite(<<"interpreted function with arity ~w">>, [A]);
  351. {type, local} ->
  352. mfa_to_string(M, F, A);
  353. {type, external} ->
  354. mfa_to_string(M, F, A)
  355. end.
  356. format_errstr_call(ErrStr, Class, ForMForFun, As, PF, Pre0) ->
  357. Pre1 = [Pre0 | n_spaces(exited_size(Class))],
  358. format_call(ErrStr, Pre1, ForMForFun, As, PF).
  359. format_call(ErrStr, Pre1, ForMForFun, As, PF) ->
  360. Arity = length(As),
  361. [ErrStr |
  362. case is_op(ForMForFun, Arity) of
  363. {yes,Op} ->
  364. format_op(ErrStr, Pre1, Op, As, PF);
  365. no ->
  366. MFs = mf_to_string(ForMForFun, Arity),
  367. I1 = iolist_size([Pre1,ErrStr|MFs]),
  368. S1 = pp_arguments(PF, As, I1),
  369. S2 = pp_arguments(PF, As, iolist_size([Pre1|MFs])),
  370. Long = count_nl(pp_arguments(PF, [a2345,b2345], I1)) > 0,
  371. case Long or (count_nl(S2) < count_nl(S1)) of
  372. true ->
  373. [$\n, Pre1, MFs, S2];
  374. false ->
  375. [MFs, S1]
  376. end
  377. end].
  378. mfa_to_string(M, F, A) ->
  379. io_lib:fwrite(<<"~s/~w">>, [mf_to_string({M, F}, A), A]).
  380. mf_to_string({M, F}, A) ->
  381. case erl_internal:bif(M, F, A) of
  382. true ->
  383. io_lib:fwrite(<<"~w">>, [F]);
  384. false ->
  385. case is_op({M, F}, A) of
  386. {yes, '/'} ->
  387. io_lib:fwrite(<<"~w">>, [F]);
  388. {yes, F} ->
  389. atom_to_list(F);
  390. no ->
  391. io_lib:fwrite(<<"~w:~w">>, [M, F])
  392. end
  393. end;
  394. mf_to_string(Fun, _A) when is_function(Fun) ->
  395. format_fun(Fun);
  396. mf_to_string(F, _A) ->
  397. io_lib:fwrite(<<"~w">>, [F]).
  398. n_args(A) when is_integer(A) ->
  399. A;
  400. n_args(As) when is_list(As) ->
  401. length(As).
  402. origin(1, M, F, A) ->
  403. case is_op({M, F}, n_args(A)) of
  404. {yes, F} -> <<"in operator ">>;
  405. no -> <<"in function ">>
  406. end;
  407. origin(_N, _M, _F, _A) ->
  408. <<"in call from">>.
  409. sep(1, S) -> S;
  410. sep(_, S) -> [$\n | S].
  411. count_nl([E | Es]) ->
  412. count_nl(E) + count_nl(Es);
  413. count_nl($\n) ->
  414. 1;
  415. count_nl(Bin) when is_binary(Bin) ->
  416. count_nl(binary_to_list(Bin));
  417. count_nl(_) ->
  418. 0.
  419. is_op(ForMForFun, A) ->
  420. try
  421. {erlang,F} = ForMForFun,
  422. _ = erl_internal:op_type(F, A),
  423. {yes,F}
  424. catch error:_ -> no
  425. end.
  426. format_op(ErrStr, Pre, Op, [A1, A2], PF) ->
  427. I1 = iolist_size([ErrStr,Pre]),
  428. S1 = PF(A1, I1+1),
  429. S2 = PF(A2, I1+1),
  430. OpS = atom_to_list(Op),
  431. Pre1 = [$\n | n_spaces(I1)],
  432. case count_nl(S1) > 0 of
  433. true ->
  434. [S1,Pre1,OpS,Pre1|S2];
  435. false ->
  436. OpS2 = io_lib:fwrite(<<" ~s ">>, [Op]),
  437. S2_2 = PF(A2, iolist_size([ErrStr,Pre,S1|OpS2])+1),
  438. case count_nl(S2) < count_nl(S2_2) of
  439. true ->
  440. [S1,Pre1,OpS,Pre1|S2];
  441. false ->
  442. [S1,OpS2|S2_2]
  443. end
  444. end.
  445. pp_arguments(PF, As, I) ->
  446. case {As, io_lib:printable_list(As)} of
  447. {[Int | T], true} ->
  448. L = integer_to_list(Int),
  449. Ll = length(L),
  450. A = list_to_atom(lists:duplicate(Ll, $a)),
  451. S0 = binary_to_list(iolist_to_binary(PF([A | T], I+1))),
  452. brackets_to_parens([$[,L,string:sub_string(S0, 2+Ll)]);
  453. _ ->
  454. brackets_to_parens(PF(As, I+1))
  455. end.
  456. brackets_to_parens(S) ->
  457. B = iolist_to_binary(S),
  458. Sz = byte_size(B) - 2,
  459. <<$[,R:Sz/binary,$]>> = B,
  460. [$(,R,$)].