diff options
author | Siri Hansen <[email protected]> | 2017-06-30 14:32:01 +0200 |
---|---|---|
committer | Siri Hansen <[email protected]> | 2017-09-05 11:26:24 +0200 |
commit | e1310b8f92a14809dccfca1100a4bf22921991b4 (patch) | |
tree | b93043aef49d533fdea8d19952be72378ac12256 | |
parent | 5c5bd9e0fa4d01382da91ed146b651aa9b212d4a (diff) | |
download | otp-e1310b8f92a14809dccfca1100a4bf22921991b4.tar.gz otp-e1310b8f92a14809dccfca1100a4bf22921991b4.tar.bz2 otp-e1310b8f92a14809dccfca1100a4bf22921991b4.zip |
observer: Improve handling of Unicode
35 files changed, 454 insertions, 350 deletions
diff --git a/lib/observer/src/cdv_atom_cb.erl b/lib/observer/src/cdv_atom_cb.erl index a123354c8f..86cdf2fd6d 100644 --- a/lib/observer/src/cdv_atom_cb.erl +++ b/lib/observer/src/cdv_atom_cb.erl @@ -42,7 +42,7 @@ get_info(_) -> {Info,TW}. format({Bin,q}) when is_binary(Bin) -> - [$'|binary_to_list(Bin)]; + [$'|lists:flatten(io_lib:format("~ts",[Bin]))]; format({Bin,nq}) when is_binary(Bin) -> lists:flatten(io_lib:format("~ts",[Bin])); format(D) -> diff --git a/lib/observer/src/cdv_bin_cb.erl b/lib/observer/src/cdv_bin_cb.erl index 5472d36a6f..5502869973 100644 --- a/lib/observer/src/cdv_bin_cb.erl +++ b/lib/observer/src/cdv_bin_cb.erl @@ -38,6 +38,7 @@ init_bin_page(Parent,{Type,Bin}) -> [{"Format \~p",cdv_html_wx,{Type,format_bin_fun("~p",Bin)}}, {"Format \~tp",cdv_html_wx,{Type,format_bin_fun("~tp",Bin)}}, {"Format \~w",cdv_html_wx,{Type,format_bin_fun("~w",Bin)}}, + {"Format \~tw",cdv_html_wx,{Type,format_bin_fun("~tw",Bin)}}, {"Format \~s",cdv_html_wx,{Type,format_bin_fun("~s",Bin)}}, {"Format \~ts",cdv_html_wx,{Type,format_bin_fun("~ts",Bin)}}, {"Hex",cdv_html_wx,{Type,hex_binary_fun(Bin)}}, @@ -56,7 +57,7 @@ format_bin_fun(Format,Bin) -> binary_to_term_fun(Bin) -> fun() -> try binary_to_term(Bin) of - Term -> plain_html(io_lib:format("~p",[Term])) + Term -> plain_html(io_lib:format("~tp",[Term])) catch error:badarg -> Warning = "This binary can not be converted to an Erlang term", observer_html_lib:warning(Warning) diff --git a/lib/observer/src/cdv_detail_wx.erl b/lib/observer/src/cdv_detail_wx.erl index 27057fd27f..4c26e447a6 100644 --- a/lib/observer/src/cdv_detail_wx.erl +++ b/lib/observer/src/cdv_detail_wx.erl @@ -133,7 +133,7 @@ handle_event(Event, _State) -> error({unhandled_event, Event}). handle_info(_Info, State) -> - %% io:format("~p: ~p, Handle info: ~p~n", [?MODULE, ?LINE, _Info]), + %% io:format("~p: ~p, Handle info: ~tp~n", [?MODULE, ?LINE, _Info]), {noreply, State}. handle_call(Call, From, _State) -> diff --git a/lib/observer/src/cdv_html_wx.erl b/lib/observer/src/cdv_html_wx.erl index 0ab0ba4315..5158e95a65 100644 --- a/lib/observer/src/cdv_html_wx.erl +++ b/lib/observer/src/cdv_html_wx.erl @@ -62,7 +62,7 @@ handle_info(active, State) -> {noreply, State}; handle_info(Info, State) -> - io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -72,7 +72,7 @@ code_change(_, _, State) -> {ok, State}. handle_call(Msg, _From, State) -> - io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast({detail_win_closed, Id},#state{expand_wins=Opened0}=State) -> @@ -80,7 +80,7 @@ handle_cast({detail_win_closed, Id},#state{expand_wins=Opened0}=State) -> {noreply, State#state{expand_wins=Opened}}; handle_cast(Msg, State) -> - io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]), {noreply, State}. handle_event(#wx{event=#wxHtmlLink{type=command_html_link_clicked, @@ -118,7 +118,7 @@ handle_event(#wx{event=#wxHtmlLink{type=command_html_link_clicked, {noreply, NewState}; handle_event(Event, State) -> - io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]), + io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]), {noreply, State}. %%%----------------------------------------------------------------- diff --git a/lib/observer/src/cdv_info_wx.erl b/lib/observer/src/cdv_info_wx.erl index 01fe6b15f2..7e416dd11a 100644 --- a/lib/observer/src/cdv_info_wx.erl +++ b/lib/observer/src/cdv_info_wx.erl @@ -65,7 +65,7 @@ handle_info(active, State) -> {noreply, State}; handle_info(Info, State) -> - io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -88,11 +88,11 @@ handle_call(new_dump, _From, #state{callback=Callback,panel=Panel, {reply, ok, State#state{fpanel=NewFPanel,trunc_warn=TW}}; handle_call(Msg, _From, State) -> - io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast(Msg, State) -> - io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]), {noreply, State}. handle_event(#wx{event=#wxMouse{type=left_down},userData=Target}, State) -> @@ -108,7 +108,7 @@ handle_event(#wx{obj=Obj,event=#wxMouse{type=leave_window}},State) -> {noreply, State}; handle_event(Event, State) -> - io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]), + io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]), {noreply, State}. %%%----------------------------------------------------------------- diff --git a/lib/observer/src/cdv_multi_wx.erl b/lib/observer/src/cdv_multi_wx.erl index b511503752..93f045b1da 100644 --- a/lib/observer/src/cdv_multi_wx.erl +++ b/lib/observer/src/cdv_multi_wx.erl @@ -94,7 +94,7 @@ handle_info(active, State) -> {noreply, NewState}; handle_info(Info, State) -> - io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -112,11 +112,11 @@ handle_call(new_dump, _From, State) -> {reply, ok, NewState}; handle_call(Msg, _From, State) -> - io:format("~p:~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p:~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast(Msg, State) -> - io:format("~p:~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p:~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]), {noreply, State}. handle_event(#wx{event=#wxCommand{type=command_listbox_selected, @@ -136,7 +136,7 @@ handle_event(#wx{event=#wxCommand{type=command_listbox_selected, {noreply,NewState}; handle_event(Event, State) -> - io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]), + io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]), {noreply, State}. %%%%%%%%%%%%%%%%%%%%%%% Internal %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/observer/src/cdv_proc_cb.erl b/lib/observer/src/cdv_proc_cb.erl index 592150146b..f10650bbb7 100644 --- a/lib/observer/src/cdv_proc_cb.erl +++ b/lib/observer/src/cdv_proc_cb.erl @@ -71,7 +71,7 @@ get_details(Id, _) -> Proplist0 = crashdump_viewer:to_proplist(record_info(fields,proc),Info), Proplist = [{expand_table,Tab}|Proplist0], - Title = io_lib:format("~s (~s)",[Info#proc.name, Id]), + Title = io_lib:format("~ts (~s)",[Info#proc.name, Id]), {ok,{Title,Proplist,TW}}; {error,{other_node,NodeId}} -> Info = "The process you are searching for was residing on " diff --git a/lib/observer/src/cdv_table_wx.erl b/lib/observer/src/cdv_table_wx.erl index df16230b70..ba23758ea6 100644 --- a/lib/observer/src/cdv_table_wx.erl +++ b/lib/observer/src/cdv_table_wx.erl @@ -74,7 +74,7 @@ handle_info(active, State) -> {noreply, State}; handle_info(Info, State) -> - io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -84,15 +84,15 @@ code_change(_, _, State) -> {ok, State}. handle_call(Msg, _From, State) -> - io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast(Msg, State) -> - io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]), {noreply, State}. handle_event(Event, State) -> - io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]), + io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]), {noreply, State}. %%%%%%%%%%%%%%%%%%%%%%% Internal %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/observer/src/cdv_term_cb.erl b/lib/observer/src/cdv_term_cb.erl index f0d90dde7c..f206d7e4c9 100644 --- a/lib/observer/src/cdv_term_cb.erl +++ b/lib/observer/src/cdv_term_cb.erl @@ -57,13 +57,7 @@ expand(['#CDVBin',Offset,Size,Pos], true) -> {ok,Bin} = crashdump_viewer:expand_binary({Offset,Size,Pos}), Bin; expand(Bin, Tab) when is_binary(Bin), not is_boolean(Tab) -> - Size = byte_size(Bin), - PrevSize = min(Size, 10) * 8, - <<Preview:PrevSize, _/binary>> = Bin, - Hash = erlang:phash2(Bin), - Key = {Preview, Size, Hash}, - ets:insert(Tab, {Key,Bin}), - ['#OBSBin',Preview,Size,Hash]; + observer_lib:make_obsbin(Bin, Tab); expand([H|T], Expand) -> case expand(T, Expand) of ET when is_list(ET) -> diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl index ebf58865e9..f3daae8e4d 100644 --- a/lib/observer/src/cdv_virtual_list_wx.erl +++ b/lib/observer/src/cdv_virtual_list_wx.erl @@ -73,7 +73,7 @@ start_detail_win(Id) -> "#Port"++_ -> start_detail_win(Id, port); _ -> - io:format("cdv: unknown identifier: ~p~n",[Id]), + io:format("cdv: unknown identifier: ~tp~n",[Id]), ignore end. @@ -195,7 +195,7 @@ call(Holder, What) when is_pid(Holder) -> erlang:demonitor(Ref), Res after 5000 -> - io:format("Hanging call ~p~n",[What]), + io:format("Hanging call ~tp~n",[What]), "" end; call(_,_) -> @@ -214,7 +214,7 @@ handle_info(active, State) -> {noreply, State}; handle_info(Info, State) -> - io:format("~p:~p, Unexpected info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p, Unexpected info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, #state{holder=Holder}) -> @@ -236,7 +236,7 @@ handle_call(new_dump, _From, {reply, ok, State#state{detail_wins=[],holder=NewHolder,trunc_warn=TW}}; handle_call(Msg, _From, State) -> - io:format("~p:~p: Unhandled call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p:~p: Unhandled call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast({start_detail_win,Id}, State) -> @@ -248,7 +248,7 @@ handle_cast({detail_win_closed, Id},#state{detail_wins=Opened}=State) -> {noreply, State#state{detail_wins=Opened2}}; handle_cast(Msg, State) -> - io:format("~p:~p: Unhandled cast ~p~n", [?MODULE, ?LINE, Msg]), + io:format("~p:~p: Unhandled cast ~tp~n", [?MODULE, ?LINE, Msg]), {noreply, State}. %%%%%%%%%%%%%%%%%%%%LOOP%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -322,7 +322,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_activated, {noreply, State}; handle_event(Event, State) -> - io:format("~p:~p: handle event ~p\n", [?MODULE, ?LINE, Event]), + io:format("~p:~p: handle event ~tp\n", [?MODULE, ?LINE, Event]), {noreply, State}. @@ -382,7 +382,7 @@ table_holder(#holder{callback=Callback, attrs=Attrs, info=Info}=S0) -> stop -> ok; What -> - io:format("Table holder got ~p~n",[What]), + io:format("Table holder got ~tp~n",[What]), table_holder(S0) end. diff --git a/lib/observer/src/cdv_wx.erl b/lib/observer/src/cdv_wx.erl index 1e3fb6289e..898f39ded2 100644 --- a/lib/observer/src/cdv_wx.erl +++ b/lib/observer/src/cdv_wx.erl @@ -306,7 +306,7 @@ handle_info({'EXIT', Pid, normal}, #state{server=Pid}=State) -> {stop, normal, State}; handle_info({'EXIT', Pid, _Reason}, State) -> - io:format("Child (~s) crashed exiting: ~p ~p~n", + io:format("Child (~s) crashed exiting: ~p ~tp~n", [pid2panel(Pid, State), Pid,_Reason]), {stop, normal, State}; diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index 8d70f5e2c8..fd8b3b9e67 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -200,13 +200,13 @@ do_script_start(StartFun) -> {'EXIT', Pid, normal} -> ok; {'EXIT', Pid, Reason} -> - io:format("\ncdv crash: ~p\n",[Reason]) + io:format("\ncdv crash: ~tp\n",[Reason]) end; _ -> io:format("\ncdv crash: ~p\n",[unknown_reason]) end; Error -> - io:format("\ncdv start failed: ~p\n",[Error]) + io:format("\ncdv start failed: ~tp\n",[Error]) end. usage() -> @@ -340,7 +340,7 @@ handle_call(general_info,_From,State=#state{file=File}) -> handle_call({expand_binary,{Offset,Size,Pos}},_From,State=#state{file=File}) -> Fd = open(File), pos_bof(Fd,Pos), - {Bin,_Line} = get_binary(Offset,Size,val(Fd)), + {Bin,_Line} = get_binary(Offset,Size,bytes(Fd)), close(Fd), {reply,{ok,Bin},State}; handle_call(procs_summary,_From,State=#state{file=File,wordsize=WS}) -> @@ -512,9 +512,9 @@ unexpected(_Fd,{eof,_LastLine},_Where) -> ok; % truncated file unexpected(Fd,{part,What},Where) -> skip_rest_of_line(Fd), - io:format("WARNING: Found unexpected line in ~s:~n~s ...~n",[Where,What]); + io:format("WARNING: Found unexpected line in ~ts:~n~ts ...~n",[Where,What]); unexpected(_Fd,What,Where) -> - io:format("WARNING: Found unexpected line in ~s:~n~s~n",[Where,What]). + io:format("WARNING: Found unexpected line in ~ts:~n~ts~n",[Where,What]). truncated_warning([]) -> []; @@ -701,9 +701,24 @@ skip(Fd,<<>>) -> end. -val(Fd) -> - val(Fd, "-1"). -val(Fd, NoExist) -> +string(Fd) -> + string(Fd, "-1"). +string(Fd,NoExist) -> + case bytes(Fd,noexist) of + noexist -> NoExist; + Val -> byte_list_to_string(Val) + end. + +byte_list_to_string(ByteList) -> + Bin = list_to_binary(ByteList), + case unicode:characters_to_list(Bin) of + Str when is_list(Str) -> Str; + _ -> ByteList + end. + +bytes(Fd) -> + bytes(Fd, "-1"). +bytes(Fd, NoExist) -> case get_rest_of_line(Fd) of {eof,[]} -> NoExist; [] -> NoExist; @@ -742,7 +757,7 @@ get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,[],Lines) -> put_chunk(Fd,Bin), lists:reverse(Lines); get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,[],[lists:reverse(Acc)|Lines]); + get_lines_to_empty(Fd,Bin,[],[byte_list_to_string(lists:reverse(Acc))|Lines]); get_lines_to_empty(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) -> get_lines_to_empty(Fd,Bin,Acc,Lines); get_lines_to_empty(Fd,<<$\s:8,Bin/binary>>,[],Lines) -> @@ -754,7 +769,7 @@ get_lines_to_empty(Fd,<<>>,Acc,Lines) -> {ok,Bin} -> get_lines_to_empty(Fd,Bin,Acc,Lines); eof -> - lists:reverse(Lines,[lists:reverse(Acc)]) + lists:reverse(Lines,[byte_list_to_string(lists:reverse(Acc))]) end. split(Str) -> @@ -816,7 +831,7 @@ do_read_file(File) -> {ok,Binaries,DumpVsn}; _Other -> R = io_lib:format( - "~s is not an Erlang crash dump~n", + "~ts is not an Erlang crash dump~n", [File]), close(Fd), {error,R} @@ -824,20 +839,20 @@ do_read_file(File) -> {ok,<<"<Erlang crash dump>",_Rest/binary>>} -> %% old version - no longer supported R = io_lib:format( - "The crashdump ~s is in the pre-R10B format, " + "The crashdump ~ts is in the pre-R10B format, " "which is no longer supported.~n", [File]), close(Fd), {error,R}; _Other -> R = io_lib:format( - "~s is not an Erlang crash dump~n", + "~ts is not an Erlang crash dump~n", [File]), close(Fd), {error,R} end; _other -> - R = io_lib:format("~s is not an Erlang crash dump~n",[File]), + R = io_lib:format("~ts is not an Erlang crash dump~n",[File]), {error,R} end. @@ -986,7 +1001,7 @@ general_info(File) -> instr_info=InstrInfo}. get_slogan_and_sysvsn(Fd,Acc) -> - case val(Fd,eof) of + case string(Fd,eof) of "Slogan: " ++ SloganPart when Acc==[] -> get_slogan_and_sysvsn(Fd,[SloganPart]); "System version: " ++ SystemVsn -> @@ -1000,14 +1015,14 @@ get_slogan_and_sysvsn(Fd,Acc) -> get_general_info(Fd,GenInfo) -> case line_head(Fd) of "Compiled" -> - get_general_info(Fd,GenInfo#general_info{compile_time=val(Fd)}); + get_general_info(Fd,GenInfo#general_info{compile_time=bytes(Fd)}); "Taints" -> - Val = case val(Fd) of "-1" -> "(none)"; Line -> Line end, + Val = case string(Fd) of "-1" -> "(none)"; Line -> Line end, get_general_info(Fd,GenInfo#general_info{taints=Val}); "Atoms" -> - get_general_info(Fd,GenInfo#general_info{num_atoms=val(Fd)}); + get_general_info(Fd,GenInfo#general_info{num_atoms=bytes(Fd)}); "Calling Thread" -> - get_general_info(Fd,GenInfo#general_info{thread=val(Fd)}); + get_general_info(Fd,GenInfo#general_info{thread=bytes(Fd)}); "=" ++ _next_tag -> GenInfo; Other -> @@ -1068,15 +1083,15 @@ get_proc_details(File,Pid,WS,DumpVsn,Binaries) -> get_procinfo(Fd,Fun,Proc,WS) -> case line_head(Fd) of "State" -> - State = case val(Fd) of + State = case bytes(Fd) of "Garbing" -> "Garbing\n(limited info)"; State0 -> State0 end, get_procinfo(Fd,Fun,Proc#proc{state=State},WS); "Name" -> - get_procinfo(Fd,Fun,Proc#proc{name=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{name=string(Fd)},WS); "Spawned as" -> - IF = val(Fd), + IF = string(Fd), case Proc#proc.name of undefined -> get_procinfo(Fd,Fun,Proc#proc{name=IF,init_func=IF},WS); @@ -1085,17 +1100,17 @@ get_procinfo(Fd,Fun,Proc,WS) -> end; "Message queue length" -> %% stored as integer so we can sort on it - get_procinfo(Fd,Fun,Proc#proc{msg_q_len=list_to_integer(val(Fd))},WS); + get_procinfo(Fd,Fun,Proc#proc{msg_q_len=list_to_integer(bytes(Fd))},WS); "Reductions" -> %% stored as integer so we can sort on it - get_procinfo(Fd,Fun,Proc#proc{reds=list_to_integer(val(Fd))},WS); + get_procinfo(Fd,Fun,Proc#proc{reds=list_to_integer(bytes(Fd))},WS); "Stack+heap" -> %% stored as integer so we can sort on it get_procinfo(Fd,Fun,Proc#proc{stack_heap= - list_to_integer(val(Fd))*WS},WS); + list_to_integer(bytes(Fd))*WS},WS); "Memory" -> %% stored as integer so we can sort on it - get_procinfo(Fd,Fun,Proc#proc{memory=list_to_integer(val(Fd))},WS); + get_procinfo(Fd,Fun,Proc#proc{memory=list_to_integer(bytes(Fd))},WS); {eof,_} -> Proc; % truncated file Other -> @@ -1117,67 +1132,67 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) -> case LineHead of %% - START - moved from get_procinfo - "Spawned by" -> - case val(Fd) of + case bytes(Fd) of "[]" -> get_procinfo(Fd,Fun,Proc,WS); Parent -> get_procinfo(Fd,Fun,Proc#proc{parent=Parent},WS) end; "Started" -> - get_procinfo(Fd,Fun,Proc#proc{start_time=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{start_time=bytes(Fd)},WS); "Last scheduled in for" -> get_procinfo(Fd,Fun,Proc#proc{current_func= {"Last scheduled in for", - val(Fd)}},WS); + string(Fd)}},WS); "Current call" -> get_procinfo(Fd,Fun,Proc#proc{current_func={"Current call", - val(Fd)}},WS); + string(Fd)}},WS); "Number of heap fragments" -> - get_procinfo(Fd,Fun,Proc#proc{num_heap_frag=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{num_heap_frag=bytes(Fd)},WS); "Heap fragment data" -> - get_procinfo(Fd,Fun,Proc#proc{heap_frag_data=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{heap_frag_data=bytes(Fd)},WS); "OldHeap" -> - Bytes = list_to_integer(val(Fd))*WS, + Bytes = list_to_integer(bytes(Fd))*WS, get_procinfo(Fd,Fun,Proc#proc{old_heap=Bytes},WS); "Heap unused" -> - Bytes = list_to_integer(val(Fd))*WS, + Bytes = list_to_integer(bytes(Fd))*WS, get_procinfo(Fd,Fun,Proc#proc{heap_unused=Bytes},WS); "OldHeap unused" -> - Bytes = list_to_integer(val(Fd))*WS, + Bytes = list_to_integer(bytes(Fd))*WS, get_procinfo(Fd,Fun,Proc#proc{old_heap_unused=Bytes},WS); "New heap start" -> - get_procinfo(Fd,Fun,Proc#proc{new_heap_start=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{new_heap_start=bytes(Fd)},WS); "New heap top" -> - get_procinfo(Fd,Fun,Proc#proc{new_heap_top=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{new_heap_top=bytes(Fd)},WS); "Stack top" -> - get_procinfo(Fd,Fun,Proc#proc{stack_top=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{stack_top=bytes(Fd)},WS); "Stack end" -> - get_procinfo(Fd,Fun,Proc#proc{stack_end=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{stack_end=bytes(Fd)},WS); "Old heap start" -> - get_procinfo(Fd,Fun,Proc#proc{old_heap_start=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{old_heap_start=bytes(Fd)},WS); "Old heap top" -> - get_procinfo(Fd,Fun,Proc#proc{old_heap_top=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{old_heap_top=bytes(Fd)},WS); "Old heap end" -> - get_procinfo(Fd,Fun,Proc#proc{old_heap_end=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{old_heap_end=bytes(Fd)},WS); %% - END - moved from get_procinfo - "Last calls" -> get_procinfo(Fd,Fun,Proc#proc{last_calls=get_lines_to_empty(Fd)},WS); "Link list" -> - {Links,Monitors,MonitoredBy} = parse_link_list(val(Fd),[],[],[]), + {Links,Monitors,MonitoredBy} = parse_link_list(bytes(Fd),[],[],[]), get_procinfo(Fd,Fun,Proc#proc{links=Links, monitors=Monitors, mon_by=MonitoredBy},WS); "Program counter" -> - get_procinfo(Fd,Fun,Proc#proc{prog_count=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{prog_count=string(Fd)},WS); "CP" -> - get_procinfo(Fd,Fun,Proc#proc{cp=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{cp=string(Fd)},WS); "arity = " ++ Arity -> %%! Temporary workaround get_procinfo(Fd,Fun,Proc#proc{arity=Arity--"\r\n"},WS); "Run queue" -> - get_procinfo(Fd,Fun,Proc#proc{run_queue=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{run_queue=string(Fd)},WS); "Internal State" -> - get_procinfo(Fd,Fun,Proc#proc{int_state=val(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{int_state=string(Fd)},WS); "=" ++ _next_tag -> Proc; Other -> @@ -1204,7 +1219,7 @@ parse_link_list(", "++Rest,Links,Monitors,MonitoredBy) -> parse_link_list([],Links,Monitors,MonitoredBy) -> {lists:reverse(Links),lists:reverse(Monitors),lists:reverse(MonitoredBy)}; parse_link_list(Unexpected,Links,Monitors,MonitoredBy) -> - io:format("WARNING: found unexpected data in link list:~n~s~n",[Unexpected]), + io:format("WARNING: found unexpected data in link list:~n~ts~n",[Unexpected]), parse_link_list([],Links,Monitors,MonitoredBy). @@ -1363,7 +1378,7 @@ read_stack_dump(Fd,Pid,BinAddrAdj,Dict) -> end. read_stack_dump1(Fd,BinAddrAdj,Dict,Acc) -> %% This function is never called if the dump is truncated in {?proc_heap,Pid} - case val(Fd) of + case bytes(Fd) of "=" ++ _next_tag -> lists:reverse(Acc); Line -> @@ -1391,7 +1406,7 @@ read_messages(Fd,Pid,BinAddrAdj,Dict) -> end. read_messages1(Fd,BinAddrAdj,Dict,Acc) -> %% This function is never called if the dump is truncated in {?proc_heap,Pid} - case val(Fd) of + case bytes(Fd) of "=" ++ _next_tag -> lists:reverse(Acc); Line -> @@ -1419,7 +1434,7 @@ read_dictionary(Fd,Pid,BinAddrAdj,Dict) -> end. read_dictionary1(Fd,BinAddrAdj,Dict,Acc) -> %% This function is never called if the dump is truncated in {?proc_heap,Pid} - case val(Fd) of + case bytes(Fd) of "=" ++ _next_tag -> lists:reverse(Acc); Line -> @@ -1451,7 +1466,7 @@ read_heap(BinAddrAdj,Dict0) -> end_of_heap -> Dict0; Fd -> - case val(Fd) of + case bytes(Fd) of "=" ++ _next_tag -> put(fd, end_of_heap), Dict0; @@ -1498,42 +1513,42 @@ get_portinfo(Fd,Port) -> case line_head(Fd) of "Slot" -> %% stored as integer so we can sort on it - get_portinfo(Fd,Port#port{slot=list_to_integer(val(Fd))}); + get_portinfo(Fd,Port#port{slot=list_to_integer(bytes(Fd))}); "Connected" -> %% stored as pid so we can sort on it - Connected0 = val(Fd), + Connected0 = bytes(Fd), Connected = try list_to_pid(Connected0) catch error:badarg -> Connected0 end, get_portinfo(Fd,Port#port{connected=Connected}); "Links" -> - Pids = split_pid_list_no_space(val(Fd)), + Pids = split_pid_list_no_space(bytes(Fd)), Links = [{Pid,Pid} || Pid <- Pids], get_portinfo(Fd,Port#port{links=Links}); "Registered as" -> - get_portinfo(Fd,Port#port{name=val(Fd)}); + get_portinfo(Fd,Port#port{name=string(Fd)}); "Monitors" -> - Monitors0 = string:tokens(val(Fd),"()"), + Monitors0 = string:tokens(bytes(Fd),"()"), Monitors = [begin [Pid,Ref] = string:tokens(Mon,","), {Pid,Pid++" ("++Ref++")"} end || Mon <- Monitors0], get_portinfo(Fd,Port#port{monitors=Monitors}); "Port controls linked-in driver" -> - Str = lists:flatten(["Linked in driver: " | val(Fd)]), + Str = lists:flatten(["Linked in driver: " | string(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); "Port controls forker process" -> - Str = lists:flatten(["Forker process: " | val(Fd)]), + Str = lists:flatten(["Forker process: " | string(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); "Port controls external process" -> - Str = lists:flatten(["External proc: " | val(Fd)]), + Str = lists:flatten(["External proc: " | string(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); "Port is a file" -> - Str = lists:flatten(["File: "| val(Fd)]), + Str = lists:flatten(["File: "| string(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); "Port is UNIX fd not opened by emulator" -> - Str = lists:flatten(["UNIX fd not opened by emulator: "| val(Fd)]), + Str = lists:flatten(["UNIX fd not opened by emulator: "| string(Fd)]), get_portinfo(Fd,Port#port{controls=Str}); "=" ++ _next_tag -> Port; @@ -1566,23 +1581,23 @@ tab_is_named(#ets_table{}) -> "no". get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> case line_head(Fd) of "Slot" -> - get_etsinfo(Fd,EtsTable#ets_table{slot=list_to_integer(val(Fd))},WS); + get_etsinfo(Fd,EtsTable#ets_table{slot=list_to_integer(bytes(Fd))},WS); "Table" -> - get_etsinfo(Fd,EtsTable#ets_table{id=val(Fd)},WS); + get_etsinfo(Fd,EtsTable#ets_table{id=string(Fd)},WS); "Name" -> - get_etsinfo(Fd,EtsTable#ets_table{name=val(Fd)},WS); + get_etsinfo(Fd,EtsTable#ets_table{name=string(Fd)},WS); "Ordered set (AVL tree), Elements" -> skip_rest_of_line(Fd), get_etsinfo(Fd,EtsTable#ets_table{data_type="tree"},WS); "Buckets" -> %% A bug in erl_db_hash.c prints a space after the buckets %% - need to strip the string to make list_to_integer/1 happy. - Buckets = list_to_integer(string:strip(val(Fd))), + Buckets = list_to_integer(string:strip(bytes(Fd))), get_etsinfo(Fd,EtsTable#ets_table{buckets=Buckets},WS); "Objects" -> - get_etsinfo(Fd,EtsTable#ets_table{size=list_to_integer(val(Fd))},WS); + get_etsinfo(Fd,EtsTable#ets_table{size=list_to_integer(bytes(Fd))},WS); "Words" -> - Words = list_to_integer(val(Fd)), + Words = list_to_integer(bytes(Fd)), Bytes = case Words of -1 -> -1; % probably truncated @@ -1592,37 +1607,37 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> "=" ++ _next_tag -> EtsTable; "Chain Length Min" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_min=>Val}},WS); "Chain Length Avg" -> - Val = try list_to_float(string:strip(val(Fd))) catch _:_ -> "-" end, + Val = try list_to_float(string:strip(bytes(Fd))) catch _:_ -> "-" end, get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_avg=>Val}},WS); "Chain Length Max" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_max=>Val}},WS); "Chain Length Std Dev" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_stddev=>Val}},WS); "Chain Length Expected Std Dev" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_exp_stddev=>Val}},WS); "Fixed" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{fixed=>Val}},WS); "Type" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{data_type=Val},WS); "Protection" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{protection=>Val}},WS); "Compressed" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{compressed=>Val}},WS); "Write Concurrency" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{write_c=>Val}},WS); "Read Concurrency" -> - Val = val(Fd), + Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{read_c=>Val}},WS); Other -> unexpected(Fd,Other,"ETS info"), @@ -1672,9 +1687,9 @@ get_timerinfo(Fd,Id) -> get_timerinfo_1(Fd,Timer) -> case line_head(Fd) of "Message" -> - get_timerinfo_1(Fd,Timer#timer{msg=val(Fd)}); + get_timerinfo_1(Fd,Timer#timer{msg=string(Fd)}); "Time left" -> - TimeLeft = list_to_integer(val(Fd) -- " ms"), + TimeLeft = list_to_integer(bytes(Fd) -- " ms"), get_timerinfo_1(Fd,Timer#timer{time=TimeLeft}); "=" ++ _next_tag -> Timer; @@ -1743,37 +1758,37 @@ get_nodeinfo(Fd,Channel,Type,Start) -> get_nodeinfo(Fd,Nod) -> case line_head(Fd) of "Name" -> - get_nodeinfo(Fd,Nod#nod{name=val(Fd)}); + get_nodeinfo(Fd,Nod#nod{name=bytes(Fd)}); "Controller" -> - get_nodeinfo(Fd,Nod#nod{controller=val(Fd)}); + get_nodeinfo(Fd,Nod#nod{controller=bytes(Fd)}); "Creation" -> %% Throwing away elements like "(refc=1)", which might be %% printed from a debug compiled emulator. Creations = lists:flatmap(fun(C) -> try [list_to_integer(C)] catch error:badarg -> [] end - end, string:tokens(val(Fd)," ")), + end, string:tokens(bytes(Fd)," ")), get_nodeinfo(Fd,Nod#nod{creation={creations,Creations}}); "Remote link" -> - Procs = val(Fd), % e.g. "<0.31.0> <4322.54.0>" + Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>" {Local,Remote} = split(Procs), Str = Local++" <-> "++Remote, NewRemLinks = [{Local,Str} | Nod#nod.remote_links], get_nodeinfo(Fd,Nod#nod{remote_links=NewRemLinks}); "Remote monitoring" -> - Procs = val(Fd), % e.g. "<0.31.0> <4322.54.0>" + Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>" {Local,Remote} = split(Procs), Str = Local++" -> "++Remote, NewRemMon = [{Local,Str} | Nod#nod.remote_mon], get_nodeinfo(Fd,Nod#nod{remote_mon=NewRemMon}); "Remotely monitored by" -> - Procs = val(Fd), % e.g. "<0.31.0> <4322.54.0>" + Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>" {Local,Remote} = split(Procs), Str = Local++" <- "++Remote, NewRemMonBy = [{Local,Str} | Nod#nod.remote_mon_by], get_nodeinfo(Fd,Nod#nod{remote_mon_by=NewRemMonBy}); "Error" -> - get_nodeinfo(Fd,Nod#nod{error="ERROR: "++val(Fd)}); + get_nodeinfo(Fd,Nod#nod{error="ERROR: "++string(Fd)}); "=" ++ _next_tag -> Nod; Other -> @@ -1817,9 +1832,9 @@ loaded_mods(File) -> get_loaded_mod_totals(Fd,{CC,OC}) -> case line_head(Fd) of "Current code" -> - get_loaded_mod_totals(Fd,{val(Fd),OC}); + get_loaded_mod_totals(Fd,{bytes(Fd),OC}); "Old code" -> - get_loaded_mod_totals(Fd,{CC,val(Fd)}); + get_loaded_mod_totals(Fd,{CC,bytes(Fd)}); "=" ++ _next_tag -> {CC,OC}; Other -> @@ -1830,10 +1845,10 @@ get_loaded_mod_totals(Fd,{CC,OC}) -> get_loaded_mod_info(Fd,LM,Fun) -> case line_head(Fd) of "Current size" -> - CS = list_to_integer(val(Fd)), + CS = list_to_integer(bytes(Fd)), get_loaded_mod_info(Fd,LM#loaded_mod{current_size=CS},Fun); "Old size" -> - OS = list_to_integer(val(Fd)), + OS = list_to_integer(bytes(Fd)), get_loaded_mod_info(Fd,LM#loaded_mod{old_size=OS},Fun); "=" ++ _next_tag -> LM; @@ -1849,16 +1864,16 @@ main_modinfo(_Fd,LM,_LineHead) -> all_modinfo(Fd,LM,LineHead) -> case LineHead of "Current attributes" -> - Str = hex_to_str(val(Fd,"")), + Str = hex_to_str(bytes(Fd,"")), LM#loaded_mod{current_attrib=Str}; "Current compilation info" -> - Str = hex_to_str(val(Fd,"")), + Str = hex_to_str(bytes(Fd,"")), LM#loaded_mod{current_comp_info=Str}; "Old attributes" -> - Str = hex_to_str(val(Fd,"")), + Str = hex_to_str(bytes(Fd,"")), LM#loaded_mod{old_attrib=Str}; "Old compilation info" -> - Str = hex_to_str(val(Fd,"")), + Str = hex_to_str(bytes(Fd,"")), LM#loaded_mod{old_comp_info=Str}; Other -> unexpected(Fd,Other,"loaded modules info"), @@ -1868,7 +1883,7 @@ all_modinfo(Fd,LM,LineHead) -> hex_to_str(Hex) -> Term = hex_to_term(Hex,[]), - io_lib:format("~p~n",[Term]). + io_lib:format("~tp~n",[Term]). hex_to_term([X,Y|Hex],Acc) -> MS = hex_to_dec([X]), @@ -1909,17 +1924,17 @@ funs(File) -> get_funinfo(Fd,Fu) -> case line_head(Fd) of "Module" -> - get_funinfo(Fd,Fu#fu{module=val(Fd)}); + get_funinfo(Fd,Fu#fu{module=bytes(Fd)}); "Uniq" -> - get_funinfo(Fd,Fu#fu{uniq=list_to_integer(val(Fd))}); + get_funinfo(Fd,Fu#fu{uniq=list_to_integer(bytes(Fd))}); "Index" -> - get_funinfo(Fd,Fu#fu{index=list_to_integer(val(Fd))}); + get_funinfo(Fd,Fu#fu{index=list_to_integer(bytes(Fd))}); "Address" -> - get_funinfo(Fd,Fu#fu{address=val(Fd)}); + get_funinfo(Fd,Fu#fu{address=bytes(Fd)}); "Native_address" -> - get_funinfo(Fd,Fu#fu{native_address=val(Fd)}); + get_funinfo(Fd,Fu#fu{native_address=bytes(Fd)}); "Refc" -> - get_funinfo(Fd,Fu#fu{refc=list_to_integer(val(Fd))}); + get_funinfo(Fd,Fu#fu{refc=list_to_integer(bytes(Fd))}); "=" ++ _next_tag -> Fu; Other -> @@ -1999,7 +2014,7 @@ get_meminfo(Fd,Acc) -> {eof,_last_line} -> lists:reverse(Acc); Key -> - get_meminfo(Fd,[{list_to_atom(Key),val(Fd)}|Acc]) + get_meminfo(Fd,[{list_to_atom(Key),bytes(Fd)}|Acc]) end. %%----------------------------------------------------------------- @@ -2023,7 +2038,7 @@ get_allocareainfo(Fd,Acc) -> {eof,_last_line} -> lists:reverse(Acc); Key -> - Val = val(Fd), + Val = bytes(Fd), AllocInfo = case split(Val) of {Alloc,[]} -> @@ -2061,7 +2076,7 @@ get_allocatorinfo1(Fd,Acc,Max) -> {eof,_last_line} -> pad_and_reverse(Acc,Max,[]); Key -> - Values = get_all_vals(val(Fd),[]), + Values = get_all_vals(bytes(Fd),[]), L = length(Values), Max1 = if L > Max -> L; true -> Max end, get_allocatorinfo1(Fd,[{Key,Values}|Acc],Max1) @@ -2316,13 +2331,13 @@ get_hashtableinfo(Fd,Name,Start) -> get_hashtableinfo1(Fd,HashTable) -> case line_head(Fd) of "size" -> - get_hashtableinfo1(Fd,HashTable#hash_table{size=val(Fd)}); + get_hashtableinfo1(Fd,HashTable#hash_table{size=bytes(Fd)}); "used" -> - get_hashtableinfo1(Fd,HashTable#hash_table{used=val(Fd)}); + get_hashtableinfo1(Fd,HashTable#hash_table{used=bytes(Fd)}); "objs" -> - get_hashtableinfo1(Fd,HashTable#hash_table{objs=val(Fd)}); + get_hashtableinfo1(Fd,HashTable#hash_table{objs=bytes(Fd)}); "depth" -> - get_hashtableinfo1(Fd,HashTable#hash_table{depth=val(Fd)}); + get_hashtableinfo1(Fd,HashTable#hash_table{depth=bytes(Fd)}); "=" ++ _next_tag -> HashTable; Other -> @@ -2353,15 +2368,15 @@ get_indextableinfo(Fd,Name,Start) -> get_indextableinfo1(Fd,IndexTable) -> case line_head(Fd) of "size" -> - get_indextableinfo1(Fd,IndexTable#index_table{size=val(Fd)}); + get_indextableinfo1(Fd,IndexTable#index_table{size=bytes(Fd)}); "used" -> - get_indextableinfo1(Fd,IndexTable#index_table{used=val(Fd)}); + get_indextableinfo1(Fd,IndexTable#index_table{used=bytes(Fd)}); "limit" -> - get_indextableinfo1(Fd,IndexTable#index_table{limit=val(Fd)}); + get_indextableinfo1(Fd,IndexTable#index_table{limit=bytes(Fd)}); "rate" -> - get_indextableinfo1(Fd,IndexTable#index_table{rate=val(Fd)}); + get_indextableinfo1(Fd,IndexTable#index_table{rate=bytes(Fd)}); "entries" -> - get_indextableinfo1(Fd,IndexTable#index_table{entries=val(Fd)}); + get_indextableinfo1(Fd,IndexTable#index_table{entries=bytes(Fd)}); "=" ++ _next_tag -> IndexTable; Other -> @@ -2393,45 +2408,45 @@ get_schedulerinfo(Fd,Name,Start) -> get_schedulerinfo1(Fd,Sched=#sched{details=Ds}) -> case line_head(Fd) of "Current Process" -> - get_schedulerinfo1(Fd,Sched#sched{process=val(Fd, "None")}); + get_schedulerinfo1(Fd,Sched#sched{process=bytes(Fd, "None")}); "Current Port" -> - get_schedulerinfo1(Fd,Sched#sched{port=val(Fd, "None")}); + get_schedulerinfo1(Fd,Sched#sched{port=bytes(Fd, "None")}); "Run Queue Max Length" -> - RQMax = list_to_integer(val(Fd)), + RQMax = list_to_integer(bytes(Fd)), RQ = RQMax + Sched#sched.run_q, get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_max=>RQMax}}); "Run Queue High Length" -> - RQHigh = list_to_integer(val(Fd)), + RQHigh = list_to_integer(bytes(Fd)), RQ = RQHigh + Sched#sched.run_q, get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_high=>RQHigh}}); "Run Queue Normal Length" -> - RQNorm = list_to_integer(val(Fd)), + RQNorm = list_to_integer(bytes(Fd)), RQ = RQNorm + Sched#sched.run_q, get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_norm=>RQNorm}}); "Run Queue Low Length" -> - RQLow = list_to_integer(val(Fd)), + RQLow = list_to_integer(bytes(Fd)), RQ = RQLow + Sched#sched.run_q, get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_low=>RQLow}}); "Run Queue Port Length" -> - RQ = list_to_integer(val(Fd)), + RQ = list_to_integer(bytes(Fd)), get_schedulerinfo1(Fd,Sched#sched{port_q=RQ}); "Scheduler Sleep Info Flags" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{sleep_info=>val(Fd, "None")}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{sleep_info=>bytes(Fd, "None")}}); "Scheduler Sleep Info Aux Work" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{sleep_aux=>val(Fd, "None")}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{sleep_aux=>bytes(Fd, "None")}}); "Run Queue Flags" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{runq_flags=>val(Fd, "None")}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{runq_flags=>bytes(Fd, "None")}}); "Current Process State" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_state=>val(Fd)}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_state=>bytes(Fd)}}); "Current Process Internal State" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_int_state=>val(Fd)}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_int_state=>bytes(Fd)}}); "Current Process Program counter" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_prg_cnt=>val(Fd)}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_prg_cnt=>string(Fd)}}); "Current Process CP" -> - get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_cp=>val(Fd)}}); + get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_cp=>string(Fd)}}); "Current Process Limited Stack Trace" -> %% If there shall be last in scheduler information block Sched#sched{details=get_limited_stack(Fd, 0, Ds)}; @@ -2443,7 +2458,7 @@ get_schedulerinfo1(Fd,Sched=#sched{details=Ds}) -> end. get_limited_stack(Fd, N, Ds) -> - case val(Fd) of + case string(Fd) of Addr = "0x" ++ _ -> get_limited_stack(Fd, N+1, Ds#{{currp_stack, N} => Addr}); "=" ++ _next_tag -> @@ -2595,7 +2610,7 @@ skip_dist_ext([C|Cs], KeptCs) -> parse_atom([$A|Line0], D) -> {N,":"++Line1} = get_hex(Line0), {Chars, Line} = get_chars(N, Line1), - {list_to_atom(Chars), Line, D}. + {binary_to_atom(list_to_binary(Chars),utf8), Line, D}. parse_atom_translation_table(0, Line0, As) -> {list_to_tuple(lists:reverse(As)), Line0}; @@ -2614,7 +2629,7 @@ deref_ptr(Ptr, Line, BinAddrAdj, D0) -> end_of_heap -> {['#CDVIncompleteHeap'],Line,D0}; Fd -> - case val(Fd) of + case bytes(Fd) of "="++_ -> put(fd, end_of_heap), deref_ptr(Ptr, Line, BinAddrAdj, D0); @@ -2759,7 +2774,7 @@ tag_to_atom("scheduler") -> ?scheduler; tag_to_atom("timer") -> ?timer; tag_to_atom("visible_node") -> ?visible_node; tag_to_atom(UnknownTag) -> - io:format("WARNING: Found unexpected tag:~s~n",[UnknownTag]), + io:format("WARNING: Found unexpected tag:~ts~n",[UnknownTag]), list_to_atom(UnknownTag). %%%----------------------------------------------------------------- diff --git a/lib/observer/src/etop_tr.erl b/lib/observer/src/etop_tr.erl index 8e43f8bb35..1e48fefca4 100644 --- a/lib/observer/src/etop_tr.erl +++ b/lib/observer/src/etop_tr.erl @@ -89,14 +89,14 @@ handle_data(Last, {_, Pid, out, _, Time2} = G, Store) -> end, New; false -> - io:format("Erlang top got garbage ~p~n", [G]), + io:format("Erlang top got garbage ~tp~n", [G]), Last end; handle_data(_W, {drop, D}, _) -> %% Error case we are missing data here! io:format("Erlang top dropped data ~p~n", [D]), []; handle_data(Last, G, _) -> - io:format("Erlang top got garbage ~p~n", [G]), + io:format("Erlang top got garbage ~tp~n", [G]), Last. elapsed({Me1, S1, Mi1}, {Me2, S2, Mi2}) -> diff --git a/lib/observer/src/etop_txt.erl b/lib/observer/src/etop_txt.erl index 183641119a..cd3ec62c13 100644 --- a/lib/observer/src/etop_txt.erl +++ b/lib/observer/src/etop_txt.erl @@ -48,7 +48,6 @@ do_update(Prev,Config) -> do_update(standard_io,Info,Prev,Config). do_update(Fd,Info,Prev,Config) -> - Encoding = encoding(Fd), {Cpu,NProcs,RQ,Clock} = loadinfo(Info,Prev), io:nl(Fd), writedoubleline(Fd), @@ -72,7 +71,7 @@ do_update(Fd,Info,Prev,Config) -> io:nl(Fd), writepinfo_header(Fd), writesingleline(Fd), - writepinfo(Fd,Info#etop_info.procinfo,Encoding), + writepinfo(Fd,Info#etop_info.procinfo,modifier(Fd)), writedoubleline(Fd), io:nl(Fd), Info. @@ -93,26 +92,27 @@ writepinfo(Fd,[#etop_proc_info{pid=Pid, cf=MFA, mq=MQ} |T], - Encoding) -> - io:fwrite(Fd,proc_format(Encoding), - [Pid,to_list(Name,Encoding),Time,Reds,Mem,MQ, - formatmfa(MFA,Encoding)]), - writepinfo(Fd,T,Encoding); + Modifier) -> + io:fwrite(Fd,proc_format(Modifier), + [Pid,to_string(Name,Modifier),Time,Reds,Mem,MQ, + to_string(MFA,Modifier)]), + writepinfo(Fd,T,Modifier); writepinfo(_Fd,[],_) -> ok. +proc_format(Modifier) -> + "~-15w~-20"++Modifier++"s~8w~8w~8w~8w ~-20"++Modifier++"s~n". -formatmfa({M, F, A},latin1) -> - io_lib:format("~w:~w/~w",[M, F, A]); -formatmfa({M, F, A},_) -> - io_lib:format("~w:~tw/~w",[M, F, A]); -formatmfa(Other,_) -> - %% E.g. when running hipe - the current_function for some - %% processes will be 'undefined' - io_lib:format("~w",[Other]). +to_string({M,F,A},Modifier) -> + io_lib:format("~w:~"++Modifier++"w/~w",[M,F,A]); +to_string(Other,Modifier) -> + io_lib:format("~"++Modifier++"w",[Other]). -to_list(Name,_) when is_atom(Name) -> atom_to_list(Name); -to_list({_M,_F,_A}=MFA,Encoding) -> formatmfa(MFA,Encoding). +modifier(Device) -> + case encoding(Device) of + latin1 -> ""; + _ -> "t" + end. encoding(Device) -> case io:getopts(Device) of @@ -122,7 +122,3 @@ encoding(Device) -> latin1 end. -proc_format(latin1) -> - "~-15w~-20s~8w~8w~8w~8w ~-20s~n"; -proc_format(_) -> - "~-15w~-20ts~8w~8w~8w~8w ~-20ts~n". diff --git a/lib/observer/src/multitrace.erl b/lib/observer/src/multitrace.erl index a01eeec6ae..82aec05e0d 100644 --- a/lib/observer/src/multitrace.erl +++ b/lib/observer/src/multitrace.erl @@ -103,16 +103,16 @@ print_func(Out,{trace_ts,P,call,{M,F,A},C,Ts},N) -> io:format(Out, "~w: ~s~n" "Process : ~w~n" - "Call : ~w:~w/~w~n" - "Arguments : ~p~n" - "Caller : ~w~n~n", + "Call : ~w:~tw/~w~n" + "Arguments : ~tp~n" + "Caller : ~tw~n~n", [N,ts(Ts),P,M,F,length(A),A,C]); print_func(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) -> io:format(Out, "~w: ~s~n" "Process : ~w~n" - "Return from : ~w:~w/~w~n" - "Return value : ~p~n~n", + "Return from : ~w:~tw/~w~n" + "Return value : ~tp~n~n", [N,ts(Ts),P,M,F,A,R]). @@ -181,7 +181,7 @@ handle_schedule(Out,{trace_ts,P,out,Info,Ts},_TI,S) -> "out:~n" "Process : ~w~n" "Time : ~s~n" - "Function : ~w~n~n",[P,ts(Ts),Info]), + "Function : ~tw~n~n",[P,ts(Ts),Info]), case lists:keysearch(P,1,S) of {value,{P,List}} -> lists:keyreplace(P,1,S,{P,[{out,Ts}|List]}); @@ -193,7 +193,7 @@ handle_schedule(Out,{trace_ts,P,in,Info,Ts},_TI,S) -> "in:~n" "Process : ~w~n" "Time : ~s~n" - "Function : ~w~n~n",[P,ts(Ts),Info]), + "Function : ~tw~n~n",[P,ts(Ts),Info]), case lists:keysearch(P,1,S) of {value,{P,List}} -> lists:keyreplace(P,1,S,{P,[{in,Ts}|List]}); diff --git a/lib/observer/src/observer_alloc_wx.erl b/lib/observer/src/observer_alloc_wx.erl index ef425f0874..7f4b3dd484 100644 --- a/lib/observer/src/observer_alloc_wx.erl +++ b/lib/observer/src/observer_alloc_wx.erl @@ -80,7 +80,7 @@ init([Notebook, Parent, Config]) -> } } catch _:Err -> - io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]), + io:format("~p crashed ~tp: ~tp~n",[?MODULE, Err, erlang:get_stacktrace()]), {stop, Err} end. @@ -183,7 +183,7 @@ handle_info({'EXIT', Old, _}, State = #state{appmon=Old}) -> {noreply, State#state{active=false, appmon=undefined}}; handle_info(_Event, State) -> - %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]), + %% io:format("~p:~p: ~tp~n",[?MODULE,?LINE,_Event]), {noreply, State}. terminate(_Event, #state{}) -> diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl index bc4f1fe117..2a481966da 100644 --- a/lib/observer/src/observer_app_wx.erl +++ b/lib/observer/src/observer_app_wx.erl @@ -320,7 +320,7 @@ handle_info({'EXIT', _, noconnection}, State) -> handle_info({'EXIT', _, normal}, State) -> {noreply, State}; handle_info(_Event, State) -> - %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]), + %% io:format("~p:~p: ~tp~n",[?MODULE,?LINE,_Event]), {noreply, State}. %%%%%%%%%% diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl index 1f1306c370..3dfcc42ada 100644 --- a/lib/observer/src/observer_html_lib.erl +++ b/lib/observer/src/observer_html_lib.erl @@ -142,13 +142,13 @@ dict_table(Tab,{Key0,Value0}, Even) -> tr(color(Even), [td("VALIGN=center",pre(Key)), td(pre(Value))]). proc_state(Tab,{Key0,Value0}, Even) -> - Key = lists:flatten(io_lib:format("~s",[Key0])), + Key = lists:flatten(io_lib:format("~ts",[Key0])), Value = all_or_expand(Tab,Value0), tr(color(Even), [td("VALIGN=center",Key), td(pre(Value))]). all_or_expand(Tab,Term) -> - Preview = io_lib:format("~P",[Term,8]), - Check = io_lib:format("~P",[Term,100]), + Preview = io_lib:format("~tP",[Term,8]), + Check = io_lib:format("~tP",[Term,100]), Exp = Preview=/=Check, all_or_expand(Tab,Term,Preview,Exp). all_or_expand(_Tab,Term,Str,false) @@ -166,13 +166,8 @@ all_or_expand(Tab,Term,Preview,true) "Click to expand above term")]; all_or_expand(Tab,Bin,_PreviewStr,_Expand) when is_binary(Bin) -> - Size = byte_size(Bin), - PrevSize = min(Size, 10) * 8, - <<Preview:PrevSize, _/binary>> = Bin, - Hash = erlang:phash2(Bin), - Key = {Preview, Size, Hash}, - ets:insert(Tab,{Key,Bin}), - Term = io_lib:format("~p", [['#OBSBin',Preview,Size,Hash]]), + OBSBin = observer_lib:make_obsbin(Bin,Tab), + Term = io_lib:format("~tp", [OBSBin]), href_proc_port(lists:flatten(Term), true). color(true) -> io_lib:format("BGCOLOR=\"#~2.16.0B~2.16.0B~2.16.0B\"", tuple_to_list(?BG_EVEN)); @@ -339,9 +334,11 @@ href_proc_bin(From, T, Acc, LTB) -> BinStr = case string:tokens(OffsetSizePos,",.| \n") of [Offset,SizeStr,Pos] when From =:= cdv -> - Id = {list_to_integer(Offset),10,list_to_integer(Pos)}, + Size = list_to_integer(SizeStr), + PreviewSize = min(Size,10), + Id = {list_to_integer(Offset),PreviewSize,list_to_integer(Pos)}, {ok,PreviewBin} = crashdump_viewer:expand_binary(Id), - PreviewStr = preview_string(list_to_integer(SizeStr), PreviewBin), + PreviewStr = preview_string(Size, PreviewBin), if LTB -> href("TARGET=\"expanded\"", ["#Binary?offset="++Offset++ @@ -351,14 +348,14 @@ href_proc_bin(From, T, Acc, LTB) -> true -> PreviewStr end; - [Preview,SizeStr,Md5] when From =:= obs -> + [PreviewIntStr,SizeStr,Md5] when From =:= obs -> Size = list_to_integer(SizeStr), - PrevSize = min(Size, 10) * 8, - PreviewStr = preview_string(Size, - <<(list_to_integer(Preview)):PrevSize>>), + PreviewInt = list_to_integer(PreviewIntStr), + PrevSize = (trunc(math:log2(PreviewInt)/8)+1)*8, + PreviewStr = preview_string(Size,<<PreviewInt:PrevSize>>), if LTB -> href("TARGET=\"expanded\"", - ["#OBSBinary?key1="++Preview++ + ["#OBSBinary?key1="++PreviewIntStr++ "&key2="++SizeStr++ "&key3="++Md5], PreviewStr); @@ -372,14 +369,14 @@ href_proc_bin(From, T, Acc, LTB) -> preview_string(Size, PreviewBin) when Size > 10 -> ["<<", - remove_lgt(io_lib:format("~p",[PreviewBin])), + remove_lgt(io_lib:format("~tp",[PreviewBin])), "...(", observer_lib:to_str({bytes,Size}), ")", ">>"]; preview_string(_, PreviewBin) -> ["<<", - remove_lgt(io_lib:format("~p",[PreviewBin])), + remove_lgt(io_lib:format("~tp",[PreviewBin])), ">>"]. remove_lgt(Deep) -> diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl index 8b6036f52a..463fb5b8ef 100644 --- a/lib/observer/src/observer_lib.erl +++ b/lib/observer/src/observer_lib.erl @@ -30,7 +30,8 @@ create_attrs/0, set_listctrl_col_size/2, create_status_bar/1, - html_window/1, html_window/2 + html_window/1, html_window/2, + make_obsbin/2 ]). -include_lib("wx/include/wx.hrl"). @@ -300,7 +301,7 @@ to_str(Float) when is_float(Float) -> to_str({trunc, Float}) when is_float(Float) -> float_to_list(Float, [{decimals,0}]); to_str(Term) -> - io_lib:format("~w", [Term]). + io_lib:format("~tw", [Term]). create_menus([], _MenuBar, _Type) -> ok; create_menus(Menus, MenuBar, Type) -> @@ -520,7 +521,7 @@ link_entry2(Panel,{Target,Str},Cursor) -> TC. to_link(RegName={Name, Node}) when is_atom(Name), is_atom(Node) -> - Str = io_lib:format("{~p,~p}", [Name, Node]), + Str = io_lib:format("{~tp,~p}", [Name, Node]), {RegName, Str}; to_link(TI = {_Target, _Identifier}) -> TI; @@ -641,11 +642,11 @@ parse_string(Str) -> Tokens = case erl_scan:string(Str, 1, [text]) of {ok, Ts, _} -> Ts; {error, {_SLine, SMod, SError}, _} -> - throw(io_lib:format("~s", [SMod:format_error(SError)])) + throw(io_lib:format("~ts", [SMod:format_error(SError)])) end, case lib:extended_parse_term(Tokens) of {error, {_PLine, PMod, PError}} -> - throw(io_lib:format("~s", [PMod:format_error(PError)])); + throw(io_lib:format("~ts", [PMod:format_error(PError)])); Res -> Res end catch @@ -769,3 +770,26 @@ update_progress_text(PD,Text) -> end. finish_progress(PD) -> wxProgressDialog:destroy(PD). + +make_obsbin(Bin,Tab) -> + Size = byte_size(Bin), + Preview = + try + %% The binary might be a unicode string, in which case we + %% don't want to split it in the middle of a grapheme + %% cluster - thus trying string:length and slice. + PL1 = min(string:length(Bin), 10), + PB1 = string:slice(Bin,0,PL1), + PS1 = byte_size(PB1) * 8, + <<P1:PS1>> = PB1, + P1 + catch _:_ -> + %% Probably not a string, so just split anywhere + PS2 = min(Size, 10) * 8, + <<P2:PS2, _/binary>> = Bin, + P2 + end, + Hash = erlang:phash2(Bin), + Key = {Preview, Size, Hash}, + ets:insert(Tab, {Key,Bin}), + ['#OBSBin',Preview,Size,Hash]. diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl index fcc51310c8..5adfadb16e 100644 --- a/lib/observer/src/observer_perf_wx.erl +++ b/lib/observer/src/observer_perf_wx.erl @@ -87,7 +87,7 @@ init([Notebook, Parent, Config]) -> }, {Panel, State0} catch _:Err -> - io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]), + io:format("~p crashed ~tp: ~tp~n",[?MODULE, Err, erlang:get_stacktrace()]), {stop, Err} end. @@ -235,7 +235,7 @@ handle_info({'EXIT', Old, _}, State = #state{appmon=Old}) -> {noreply, State#state{active=false, appmon=undefined}}; handle_info(_Event, State) -> - %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]), + %% io:format("~p:~p: ~tp~n",[?MODULE,?LINE,_Event]), {noreply, State}. %%%%%%%%%% diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl index 8339267659..5908e99e36 100644 --- a/lib/observer/src/observer_port_wx.erl +++ b/lib/observer/src/observer_port_wx.erl @@ -338,7 +338,7 @@ handle_info({info, {port_info_not_available,NodeName}}, {noreply, State}; handle_info({error, Error}, #state{panel=Panel} = State) -> - Str = io_lib:format("ERROR: ~s~n",[Error]), + Str = io_lib:format("ERROR: ~ts~n",[Error]), observer_lib:display_info_dialog(Panel, Str), {noreply, State}; diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl index 3083297f31..2e5fe0bc1a 100644 --- a/lib/observer/src/observer_pro_wx.erl +++ b/lib/observer/src/observer_pro_wx.erl @@ -217,7 +217,7 @@ call(Holder, What) -> erlang:demonitor(Ref), Res after 2000 -> - io:format("Hanging call ~p~n",[What]), + io:format("Hanging call ~tp~n",[What]), "" end. @@ -256,7 +256,7 @@ handle_info(not_active, #state{timer=Timer0}=State) -> {noreply, State#state{timer=Timer}}; handle_info(Info, State) -> - io:format("~p:~p, Unexpected info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p, Unexpected info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, #state{holder=Holder}) -> @@ -273,11 +273,11 @@ handle_call(get_config, _, #state{holder=Holder, timer=Timer}=State) -> {reply, Conf#{acc=>Accum}, State}; handle_call(Msg, _From, State) -> - io:format("~p:~p: Unhandled call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p:~p: Unhandled call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast(Msg, State) -> - io:format("~p:~p: Unhandled cast ~p~n", [?MODULE, ?LINE, Msg]), + io:format("~p:~p: Unhandled cast ~tp~n", [?MODULE, ?LINE, Msg]), {noreply, State}. %%%%%%%%%%%%%%%%%%%%LOOP%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -401,7 +401,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_activated}}, {noreply, State#state{procinfo_menu_pids=Opened2}}; handle_event(Event, State) -> - io:format("~p:~p: handle event ~p\n", [?MODULE, ?LINE, Event]), + io:format("~p:~p: handle event ~tp\n", [?MODULE, ?LINE, Event]), {noreply, State}. @@ -559,7 +559,7 @@ table_holder(#holder{info=Info, attrs=Attrs, %% Node crashed will be noticed soon.. table_holder(S0#holder{backend_pid=undefined}); _What -> - %% io:format("~p: Table holder got ~p~n",[?MODULE, _What]), + %% io:format("~p: Table holder got ~tp~n",[?MODULE, _What]), table_holder(S0) end. diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl index 10decd8b62..963def958b 100644 --- a/lib/observer/src/observer_procinfo.erl +++ b/lib/observer/src/observer_procinfo.erl @@ -56,7 +56,7 @@ init([Pid, ParentFrame, Parent]) -> Table = ets:new(observer_expand,[set,public]), Title=case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, registered_name]) of [] -> io_lib:format("~p",[Pid]); - {registered_name, Registered} -> io_lib:format("~p (~p)",[Registered, Pid]); + {registered_name, Registered} -> io_lib:format("~tp (~p)",[Registered, Pid]); undefined -> throw(process_undefined) end, Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [atom_to_list(node(Pid)), $:, Title], @@ -171,7 +171,7 @@ handle_info({get_debug_info, From}, State = #state{notebook=Notebook}) -> From ! {procinfo_debug, Notebook}, {noreply, State}; handle_info(_Info, State) -> - %% io:format("~p: ~p, Handle info: ~p~n", [?MODULE, ?LINE, Info]), + %% io:format("~p: ~p, Handle info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. handle_call(Call, From, _State) -> @@ -263,7 +263,7 @@ init_stack_page(Parent, Pid) -> wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({M,F,A})), FileLine = case Info of [{file,File},{line,Line}] -> - io_lib:format("~s:~w", [File,Line]); + io_lib:format("~ts:~w", [File,Line]); _ -> [] end, @@ -487,5 +487,5 @@ io_request({put_chars, Encoding, Module, Function, Args}, State) -> {error, {error, Function}, State} end; io_request(_Req, State) -> - %% io:format("~p: Unknown req: ~p ~n",[?LINE, _Req]), + %% io:format("~p: Unknown req: ~tp ~n",[?LINE, _Req]), {ok, {error, request}, State}. diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl index 2e1af3ada9..8c2ffd77b4 100644 --- a/lib/observer/src/observer_sys_wx.erl +++ b/lib/observer/src/observer_sys_wx.erl @@ -199,7 +199,7 @@ handle_info(not_active, #sys_wx_state{timer = Timer} = State) -> {noreply, State#sys_wx_state{timer = observer_lib:stop_timer(Timer)}}; handle_info(Info, State) -> - io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]), + io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]), {noreply, State}. terminate(_Reason, _State) -> @@ -212,11 +212,11 @@ handle_call(get_config, _, #sys_wx_state{timer=Timer}=State) -> {reply, observer_lib:timer_config(Timer), State}; handle_call(Msg, _From, State) -> - io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]), {reply, ok, State}. handle_cast(Msg, State) -> - io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]), + io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]), {noreply, State}. handle_event(#wx{id = ?ID_REFRESH, event = #wxCommand{type = command_menu_selected}}, @@ -235,5 +235,5 @@ handle_event(#wx{id = ?ID_REFRESH_INTERVAL, {noreply, State#sys_wx_state{timer=Timer}}; handle_event(Event, State) -> - io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]), + io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]), {noreply, State}. diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl index b960c61ff0..8127248262 100644 --- a/lib/observer/src/observer_trace_wx.erl +++ b/lib/observer/src/observer_trace_wx.erl @@ -683,7 +683,7 @@ handle_event(#wx{id=?REMOVE_NODES}, #state{n_view=Nview, nodes=Ns0} = State) -> {noreply, State#state{nodes = Ns}}; handle_event(#wx{id=ID, event = What}, State) -> - io:format("~p:~p: Unhandled event: ~p, ~p ~n", [?MODULE, ?LINE, ID, What]), + io:format("~p:~p: Unhandled event: ~p, ~tp ~n", [?MODULE, ?LINE, ID, What]), {noreply, State}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -729,7 +729,7 @@ handle_info({update_ms, NewMs}, State) -> {noreply, State#state{match_specs=NewMs}}; handle_info(Any, State) -> - io:format("~p~p: received unexpected message: ~p\n", [?MODULE, self(), Any]), + io:format("~p~p: received unexpected message: ~tp\n", [?MODULE, self(), Any]), {noreply, State}. terminate(_Reason, #state{nodes=_Nodes}) -> @@ -1046,33 +1046,33 @@ format_trace(Trace, Size, TS0={_,_,MS}) -> case element(4, Trace) of {dbg,ok} -> ""; Message -> - io_lib:format("~s (~100p) << ~100p~n", [TS,From,Message]) + io_lib:format("~s (~100p) << ~100tp~n", [TS,From,Message]) end; 'send' -> Message = element(4, Trace), To = element(5, Trace), - io_lib:format("~s (~100p) ~100p ! ~100p~n", [TS,From,To,Message]); + io_lib:format("~s (~100p) ~100p ! ~100tp~n", [TS,From,To,Message]); call -> case element(4, Trace) of MFA when Size == 5 -> Message = element(5, Trace), - io_lib:format("~s (~100p) call ~s (~100p) ~n", [TS,From,ffunc(MFA),Message]); + io_lib:format("~s (~100p) call ~ts (~100tp) ~n", [TS,From,ffunc(MFA),Message]); MFA -> - io_lib:format("~s (~100p) call ~s~n", [TS,From,ffunc(MFA)]) + io_lib:format("~s (~100p) call ~ts~n", [TS,From,ffunc(MFA)]) end; return_from -> MFA = element(4, Trace), Ret = element(5, Trace), - io_lib:format("~s (~100p) returned from ~s -> ~100p~n", [TS,From,ffunc(MFA),Ret]); + io_lib:format("~s (~100p) returned from ~ts -> ~100tp~n", [TS,From,ffunc(MFA),Ret]); return_to -> MFA = element(4, Trace), - io_lib:format("~s (~100p) returning to ~s~n", [TS,From,ffunc(MFA)]); + io_lib:format("~s (~100p) returning to ~ts~n", [TS,From,ffunc(MFA)]); spawn when Size == 5 -> Pid = element(4, Trace), MFA = element(5, Trace), - io_lib:format("~s (~100p) spawn ~100p as ~s~n", [TS,From,Pid,ffunc(MFA)]); + io_lib:format("~s (~100p) spawn ~100p as ~ts~n", [TS,From,Pid,ffunc(MFA)]); Op -> - io_lib:format("~s (~100p) ~100p ~s~n", [TS,From,Op,ftup(Trace,4,Size)]) + io_lib:format("~s (~100p) ~100p ~ts~n", [TS,From,Op,ftup(Trace,4,Size)]) end. %%% These f* functions returns non-flat strings @@ -1080,24 +1080,24 @@ format_trace(Trace, Size, TS0={_,_,MS}) -> %% {M,F,[A1, A2, ..., AN]} -> "M:F(A1, A2, ..., AN)" %% {M,F,A} -> "M:F/A" ffunc({M,F,Argl}) when is_list(Argl) -> - io_lib:format("~100p:~100p(~s)", [M, F, fargs(Argl)]); + io_lib:format("~100p:~100tp(~ts)", [M, F, fargs(Argl)]); ffunc({M,F,Arity}) -> - io_lib:format("~100p:~100p/~100p", [M,F,Arity]); -ffunc(X) -> io_lib:format("~100p", [X]). + io_lib:format("~100p:~100tp/~100p", [M,F,Arity]); +ffunc(X) -> io_lib:format("~100tp", [X]). %% Integer -> "Integer" %% [A1, A2, ..., AN] -> "A1, A2, ..., AN" fargs(Arity) when is_integer(Arity) -> integer_to_list(Arity); fargs([]) -> []; -fargs([A]) -> io_lib:format("~100p", [A]); %% last arg -fargs([A|Args]) -> [io_lib:format("~100p,", [A]) | fargs(Args)]; -fargs(A) -> io_lib:format("~100p", [A]). % last or only arg +fargs([A]) -> io_lib:format("~100tp", [A]); %% last arg +fargs([A|Args]) -> [io_lib:format("~100tp,", [A]) | fargs(Args)]; +fargs(A) -> io_lib:format("~100tp", [A]). % last or only arg %% {A_1, A_2, ..., A_N} -> "A_Index A_Index+1 ... A_Size" ftup(Trace, Index, Index) -> - io_lib:format("~100p", [element(Index, Trace)]); + io_lib:format("~100tp", [element(Index, Trace)]); ftup(Trace, Index, Size) -> - [io_lib:format("~100p ", [element(Index, Trace)]) + [io_lib:format("~100tp ", [element(Index, Trace)]) | ftup(Trace, Index+1, Size)]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1125,18 +1125,19 @@ get_config(#state{def_proc_flags = ProcFlags, write_file(Frame, Filename, Config) -> Str = - ["%%%\n%%% This file is generated by Observer\n", + ["%%% ",epp:encoding_to_string(utf8), "\n" + "%%%\n%%% This file is generated by Observer\n", "%%%\n%%% DO NOT EDIT!\n%%%\n", - [io_lib:format("~p.~n",[MSTerm]) || + [io_lib:format("~tp.~n",[MSTerm]) || MSTerm <- proplists:get_value(match_specs, Config)], io_lib:format("~p.~n",[lists:keyfind(procflags, 1, Config)]), io_lib:format("~p.~n",[lists:keyfind(portflags, 1, Config)]), - io_lib:format("~p.~n",[lists:keyfind(output, 1, Config)]), - [io_lib:format("~p.~n",[ModuleTerm]) || + io_lib:format("~tp.~n",[lists:keyfind(output, 1, Config)]), + [io_lib:format("~tp.~n",[ModuleTerm]) || ModuleTerm <- proplists:get_value(trace_p, Config)] ], - case file:write_file(Filename, list_to_binary(Str)) of + case file:write_file(Filename, unicode:characters_to_binary(Str)) of ok -> success; {error, Reason} -> @@ -1200,7 +1201,7 @@ make_ms(MS) -> make_ms(Name,Term,FunStr). make_ms(Name, Term, FunStr) -> - #match_spec{name=Name, term=Term, str=io_lib:format("~w", Term), func = FunStr}. + #match_spec{name=Name, term=Term, str=io_lib:format("~tw", Term), func = FunStr}. parse_tp({tp, Mod, FAs}, State) -> Patterns = [#tpattern{m=Mod,fa={F,A}, ms=make_ms(List)} || diff --git a/lib/observer/src/observer_traceoptions_wx.erl b/lib/observer/src/observer_traceoptions_wx.erl index 285c298c4b..4f46426cf6 100644 --- a/lib/observer/src/observer_traceoptions_wx.erl +++ b/lib/observer/src/observer_traceoptions_wx.erl @@ -487,7 +487,7 @@ edit_ms(TextCtrl, Label0, Parent) -> _ -> Label0 end, #match_spec{name=Label, term=MatchSpec, - str=io_lib:format("~w",[MatchSpec]), + str=io_lib:format("~tw",[MatchSpec]), func=Str} catch throw:cancel -> @@ -511,18 +511,18 @@ ms_from_string(Str) -> Tokens = case erl_scan:string(Str) of {ok, Ts, _} -> Ts; {error, {SLine, SMod, SError}, _} -> - throw(io_lib:format("~w: ~s", [SLine,SMod:format_error(SError)])) + throw(io_lib:format("~w: ~ts", [SLine,SMod:format_error(SError)])) end, Exprs = case erl_parse:parse_exprs(Tokens) of {ok, T} -> T; {error, {PLine, PMod, PError}} -> - throw(io_lib:format("~w: ~s", [PLine,PMod:format_error(PError)])) + throw(io_lib:format("~w: ~ts", [PLine,PMod:format_error(PError)])) end, Term = case Exprs of [{'fun', _, {clauses, Clauses}}|_] -> case ms_transform:transform_from_shell(dbg,Clauses,orddict:new()) of {error, [{_,[{MSLine,Mod,MSInfo}]}],_} -> - throw(io_lib:format("~w: ~p", [MSLine,Mod:format_error(MSInfo)])); + throw(io_lib:format("~w: ~tp", [MSLine,Mod:format_error(MSInfo)])); {error, _} -> throw("Could not convert fun() to match spec"); Ms -> @@ -536,7 +536,7 @@ ms_from_string(Str) -> {error, List} -> throw([[Error, $\n] || {_, Error} <- List]) end catch error:_Reason -> - %% io:format("Bad term: ~s~n ~p in ~p~n", [Str, _Reason, erlang:get_stacktrace()]), + %% io:format("Bad term: ~ts~n ~tp in ~tp~n", [Str, _Reason, erlang:get_stacktrace()]), throw("Invalid term") end. @@ -556,7 +556,8 @@ filter_listbox_data(Input, Data, ListBox) -> filter_listbox_data(Input, Data, ListBox, true). filter_listbox_data(Input, Data, ListBox, AddClientData) -> - FilteredData = [X || X = {Str, _} <- Data, re:run(Str, Input) =/= nomatch], + FilteredData = [X || X = {Str, _} <- Data, + re:run(Str, Input, [unicode]) =/= nomatch], wxListBox:clear(ListBox), wxListBox:appendStrings(ListBox, [Str || {Str,_} <- FilteredData]), AddClientData andalso @@ -648,9 +649,9 @@ parse_function_names(Choices) -> parse_function_names([], Acc) -> lists:reverse(Acc); parse_function_names([{H, Term}|T], Acc) -> - IsFun = re:run(H, ".*-fun-\\d*?-"), - IsLc = re:run(H, ".*-lc\\$\\^\\d*?/\\d*?-\\d*?-"), - IsLbc = re:run(H, ".*-lbc\\$\\^\\d*?/\\d*?-\\d*?-"), + IsFun = re:run(H, ".*-fun-\\d*?-", [unicode,ucp]), + IsLc = re:run(H, ".*-lc\\$\\^\\d*?/\\d*?-\\d*?-", [unicode,ucp]), + IsLbc = re:run(H, ".*-lbc\\$\\^\\d*?/\\d*?-\\d*?-", [unicode,ucp]), Parsed = if IsFun =/= nomatch -> "Fun: " ++ H; IsLc =/= nomatch -> "List comprehension: " ++ H; diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl index 789e060cfb..d6dcee2cda 100644 --- a/lib/observer/src/observer_tv_table.erl +++ b/lib/observer/src/observer_tv_table.erl @@ -258,7 +258,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_selected, itemIndex=Index} State = #state{pid=Pid, grid=Grid, status=StatusBar}) -> N = wxListCtrl:getItemCount(Grid), Str = get_row(Pid, Index, all), - wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w: ~s",[N, Str])), + wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w: ~ts",[N, Str])), {noreply, State#state{selected=Index}}; handle_event(#wx{event=#wxList{type=command_list_item_activated, itemIndex=Index}}, @@ -278,7 +278,7 @@ handle_event(#wx{id=?ID_DELETE}, State = #state{grid=Grid, pid=Pid, status=StatusBar, selected=Index}) -> Str = get_row(Pid, Index, all), Pid ! {delete, Index}, - wxStatusBar:setStatusText(StatusBar, io_lib:format("Deleted object: ~s",[Str])), + wxStatusBar:setStatusText(StatusBar, io_lib:format("Deleted object: ~ts",[Str])), wxListCtrl:setItemState(Grid, Index, 0, ?wxLIST_STATE_FOCUSED), {noreply, State#state{selected=undefined}}; @@ -338,7 +338,7 @@ handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{type=command_text_enter,cmdS Pid ! {mark_search_hit, false}, case search(Pid, Str, Pos, Dir, Case) of false -> - wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~s",[Str])), + wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~ts",[Str])), Pid ! {mark_search_hit, Find#find.start}, wxListCtrl:refreshItem(Grid, Find#find.start), {noreply, State#state{search=Search#search{find=Find#find{found=false}}}}; @@ -372,7 +372,7 @@ handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{cmdString=Str}}, Pid ! {mark_search_hit, false}, case search(Pid, Str, Cont#find.start, Dir, Case) of false -> - wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~s",[Str])), + wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~ts",[Str])), {noreply, State}; Row -> wxListCtrl:ensureVisible(Grid, Row), @@ -395,19 +395,19 @@ handle_event(#wx{id=?ID_REFRESH_INTERVAL}, {noreply, State#state{timer=Timer}}; handle_event(_Event, State) -> - %io:format("~p:~p, handle event ~p\n", [?MODULE, ?LINE, Event]), + %io:format("~p:~p, handle event ~tp\n", [?MODULE, ?LINE, Event]), {noreply, State}. handle_sync_event(_Event, _Obj, _State) -> - %io:format("~p:~p, handle sync_event ~p\n", [?MODULE, ?LINE, Event]), + %io:format("~p:~p, handle sync_event ~tp\n", [?MODULE, ?LINE, Event]), ok. handle_call(_Event, _From, State) -> - %io:format("~p:~p, handle call (~p) ~p\n", [?MODULE, ?LINE, From, Event]), + %io:format("~p:~p, handle call (~p) ~tp\n", [?MODULE, ?LINE, From, Event]), {noreply, State}. handle_cast(_Event, State) -> - %io:format("~p:~p, handle cast ~p\n", [?MODULE, ?LINE, Event]), + %io:format("~p:~p, handle cast ~tp\n", [?MODULE, ?LINE, Event]), {noreply, State}. handle_info({no_rows, N}, State = #state{grid=Grid, status=StatusBar}) -> @@ -433,7 +433,7 @@ handle_info(refresh_interval, State = #state{pid=Pid}) -> handle_info({error, Error}, State = #state{frame=Frame}) -> ErrorStr = try io_lib:format("~ts", [Error]), Error - catch _:_ -> io_lib:format("~p", [Error]) + catch _:_ -> io_lib:format("~tp", [Error]) end, Dlg = wxMessageDialog:new(Frame, ErrorStr), wxMessageDialog:showModal(Dlg), @@ -441,7 +441,7 @@ handle_info({error, Error}, State = #state{frame=Frame}) -> {noreply, State}; handle_info(_Event, State) -> - %% io:format("~p:~p, handle info ~p\n", [?MODULE, ?LINE, _Event]), + %% io:format("~p:~p, handle info ~tp\n", [?MODULE, ?LINE, _Event]), {noreply, State}. terminate(_Event, #state{pid=Pid, attrs=Attrs}) -> @@ -554,7 +554,7 @@ table_holder(S0 = #holder{parent=Parent, pid=Pid, table=Table}) -> edit_row(Row, Term, S0), table_holder(S0); What -> - io:format("Table holder got ~p~n",[What]), + io:format("Table holder got ~tp~n",[What]), Parent ! {refresh, 0, S0#holder.n-1}, table_holder(S0) end. @@ -641,7 +641,7 @@ search([Str, Row, Dir0, CaseSens], true -> 1; false -> -1 end, - Res = case re:compile(Str, Opt) of + Res = case re:compile(Str, [unicode|Opt]) of {ok, Re} -> re_search(Row, Dir, N, Re, Table); {error, _} -> false end, @@ -665,7 +665,7 @@ get_row(From, Row, Col, Table) -> [Object|_] when Col =:= all -> From ! {self(), format(Object)}; [Object|_] when Col =:= all_multiline -> - From ! {self(), io_lib:format("~p", [Object])}; + From ! {self(), io_lib:format("~tp", [Object])}; [Object|_] when Col =:= term -> From ! {self(), Object}; [Object|_] when tuple_size(Object) >= Col -> @@ -801,7 +801,7 @@ format(Bin) when is_binary(Bin), byte_size(Bin) > 100 -> io_lib:format("<<#Bin:~w>>", [byte_size(Bin)]); format(Bin) when is_binary(Bin) -> try - true = printable_list(unicode:characters_to_list(Bin)), + true = io_lib:printable_list(unicode:characters_to_list(Bin)), io_lib:format("<<\"~ts\">>", [Bin]) catch _:_ -> io_lib:format("~w", [Bin]) @@ -809,7 +809,7 @@ format(Bin) when is_binary(Bin) -> format(Float) when is_float(Float) -> io_lib:format("~.3g", [Float]); format(Term) -> - io_lib:format("~w", [Term]). + io_lib:format("~tw", [Term]). format_tuple(Tuple, I, Max) when I < Max -> [format(element(I, Tuple)), $,|format_tuple(Tuple, I+1, Max)]; @@ -820,7 +820,7 @@ format_tuple(_Tuple, 1, 0) -> format_list([]) -> "[]"; format_list(List) -> - case printable_list(List) of + case io_lib:printable_list(List) of true -> io_lib:format("\"~ts\"", [map_printable_list(List)]); false -> [$[ | make_list(List)] end. @@ -849,26 +849,3 @@ map_printable_list([$\e|Cs]) -> map_printable_list([]) -> []; map_printable_list([C|Cs]) -> [C|map_printable_list(Cs)]. - -%% printable_list([Char]) -> bool() -%% Return true if CharList is a list of printable characters, else -%% false. - -printable_list([C|Cs]) when is_integer(C), C >= $ , C =< 255 -> - printable_list(Cs); -printable_list([$\n|Cs]) -> - printable_list(Cs); -printable_list([$\r|Cs]) -> - printable_list(Cs); -printable_list([$\t|Cs]) -> - printable_list(Cs); -printable_list([$\v|Cs]) -> - printable_list(Cs); -printable_list([$\b|Cs]) -> - printable_list(Cs); -printable_list([$\f|Cs]) -> - printable_list(Cs); -printable_list([$\e|Cs]) -> - printable_list(Cs); -printable_list([]) -> true; -printable_list(_Other) -> false. %Everything else is false diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl index 9564bdfa1c..e16f3cab6b 100644 --- a/lib/observer/src/observer_tv_wx.erl +++ b/lib/observer/src/observer_tv_wx.erl @@ -252,7 +252,7 @@ handle_info(not_active, State = #state{timer = Timer0}) -> {noreply, State#state{timer=Timer}}; handle_info({error, Error}, #state{panel=Panel,opt=Opt}=State) -> - Str = io_lib:format("ERROR: ~s~n",[Error]), + Str = io_lib:format("ERROR: ~ts~n",[Error]), observer_lib:display_info_dialog(Panel,Str), case Opt#opt.type of mnesia -> wxMenuBar:check(observer_wx:get_menubar(), ?ID_ETS, true); diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl index 9b9e80f479..be93b1d5f1 100644 --- a/lib/observer/src/observer_wx.erl +++ b/lib/observer/src/observer_wx.erl @@ -459,7 +459,7 @@ handle_info({'EXIT', Pid, Reason}, State) -> normal -> {noreply, State}; _ -> - io:format("Observer: Child (~s) crashed exiting: ~p ~p~n", + io:format("Observer: Child (~s) crashed exiting: ~p ~tp~n", [pid2panel(Pid, State), Pid, Reason]), {stop, normal, State} end; @@ -504,7 +504,7 @@ save_config(Panels) -> File = config_file(), case filelib:ensure_dir(File) of ok -> - Format = [io_lib:format("~p.~n",[Conf]) || Conf <- Configs], + Format = [io_lib:format("~tp.~n",[Conf]) || Conf <- Configs], _ = file:write_file(File, Format); _ -> ignore diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl index 09b0bc6710..940fdc9818 100644 --- a/lib/observer/src/ttb.erl +++ b/lib/observer/src/ttb.erl @@ -635,7 +635,7 @@ stop(Opts) when is_list(Opts) -> ok; {_, {stopped, _}} -> %% Printout moved out of the ttb loop to avoid occasional deadlock - io:format("Stored logs in ~s~n", [element(2, Result)]); + io:format("Stored logs in ~ts~n", [element(2, Result)]); {_, _} -> ok end, @@ -792,7 +792,7 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) -> write_config(?last_config, all), Localhost = host(node()), Dir = get_fetch_dir(UserDir, proplists:get_value(logfile, SessionInfo)), - file:make_dir(Dir), + ok = filelib:ensure_dir(filename:join(Dir,"*")), %% The nodes are traversed twice here because %% the meta tracing in observer_backend must be %% stopped before dbg is stopped, and dbg must @@ -900,21 +900,29 @@ fetch_report(Localhost, Dir, Node, MetaFile) -> fetch(Localhost,Dir,Node,MetaFile) -> case (host(Node) == Localhost) orelse is_local(MetaFile) of - true -> % same host, just move the files + true -> % same host, just move the files Files = get_filenames(Node,MetaFile), lists:foreach( - fun(File0) -> - Dest = filename:join(Dir,filename:basename(File0)), - file:rename(File0, Dest) - end, - Files); + fun(File0) -> + Dest = filename:join(Dir,filename:basename(File0)), + file:rename(File0, Dest) + end, + Files); false -> {ok, LSock} = gen_tcp:listen(0, [binary,{packet,2},{active,false}]), {ok,Port} = inet:port(LSock), - rpc:cast(Node,observer_backend,ttb_fetch, - [MetaFile,{Port,Localhost}]), + Enc = file:native_name_encoding(), + Args = + case rpc:call(Node,erlang,function_exported, + [observer_backend,ttb_fetch,3]) of + true -> + [MetaFile,{Port,Localhost},Enc]; + false -> + [MetaFile,{Port,Localhost}] + end, + rpc:cast(Node,observer_backend,ttb_fetch,Args), {ok, Sock} = gen_tcp:accept(LSock), - receive_files(Dir,Sock,undefined), + receive_files(Dir,Sock,undefined,Enc), ok = gen_tcp:close(LSock), ok = gen_tcp:close(Sock) end. @@ -929,25 +937,48 @@ get_filenames(_N, {local,F,_}) -> get_filenames(N, F) -> rpc:call(N, observer_backend,ttb_get_filenames,[F]). -receive_files(Dir,Sock,Fd) -> +receive_files(Dir,Sock,Fd,Enc) -> case gen_tcp:recv(Sock, 0) of {ok, <<0,Bin/binary>>} -> file:write(Fd,Bin), - receive_files(Dir,Sock,Fd); - {ok, <<1,Bin/binary>>} -> - File0 = binary_to_list(Bin), + receive_files(Dir,Sock,Fd,Enc); + {ok, <<Code,Bin/binary>>} when Code==1; Code==2; Code==3 -> + File0 = decode_filename(Code,Bin,Enc), File = filename:join(Dir,File0), {ok,Fd1} = file:open(File,[raw,write]), - receive_files(Dir,Sock,Fd1); + receive_files(Dir,Sock,Fd1,Enc); {error, closed} -> ok = file:close(Fd) end. +decode_filename(1,Bin,_Enc) -> + %% Old version of observer_backend - filename encoded with + %% list_to_binary + binary_to_list(Bin); +decode_filename(2,Bin,Enc) -> + %% Successfully encoded filename with correct encoding + unicode:characters_to_list(Bin,Enc); +decode_filename(3,Bin,latin1) -> + %% Filename encoded with faulty encoding. This has to be utf8 + %% remote and latin1 here, and the filename actually containing + %% characters outside the latin1 range. So making an escaped + %% variant of the filename and warning about it. + File0 = unicode:characters_to_list(Bin,utf8), + File = [ case X of + High when High > 255 -> + ["\\\\x{",erlang:integer_to_list(X, 16),$}]; + Low -> + Low + end || X <- File0 ], + io:format("Warning: fetching file with faulty filename encoding ~ts~n" + "Will be written as ~ts~n", + [File0,File]), + File. + host(Node) -> [_name,Host] = string:tokens(atom_to_list(Node),"@"), Host. - wait_for_fetch([]) -> ok; wait_for_fetch(Nodes) -> @@ -1087,7 +1118,7 @@ read_traci(File) -> {ok,B} -> interpret_binary(B,dict:new(),[]); _ -> - io:format("Warning: no meta data file: ~s~n",[MetaFile]), + io:format("Warning: no meta data file: ~ts~n",[MetaFile]), {dict:new(),[]} end. @@ -1303,7 +1334,7 @@ get_term(B) -> end. display_warning(Item,Warning) -> - io:format("Warning: {~w,~w}~n",[Warning,Item]). + io:format("Warning: {~tw,~tw}~n",[Warning,Item]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/observer/src/ttb_et.erl b/lib/observer/src/ttb_et.erl index 95e8e9aa07..1b828eebc0 100644 --- a/lib/observer/src/ttb_et.erl +++ b/lib/observer/src/ttb_et.erl @@ -137,13 +137,13 @@ processes(E0) -> E = label(E0), {{FromProc,FromNode},{ToProc,ToNode}} = get_actors(E#event.from,E#event.to), - {true,E#event{from = io_lib:format("~w~n~w",[FromProc,FromNode]), - to = io_lib:format("~w~n~w",[ToProc,ToNode])}}. + {true,E#event{from = io_lib:format("~tw~n~w",[FromProc,FromNode]), + to = io_lib:format("~tw~n~w",[ToProc,ToNode])}}. mods_and_procs(E) -> ActorFun = fun({M,_F,_A},{Proc,Node}) -> - io_lib:format("~w~n~w~n~w",[M,Proc,Node]) + io_lib:format("~w~n~tw~n~w",[M,Proc,Node]) end, calltrace_filter(E,ActorFun). @@ -155,13 +155,13 @@ modules(E) -> funcs_and_procs(E) -> ActorFun = fun({M,F,A},{Proc,Node}) -> - io_lib:format("~s~n~w~n~w",[mfa(M,F,A),Proc,Node]) + io_lib:format("~ts~n~tw~n~w",[mfa(M,F,A),Proc,Node]) end, calltrace_filter(E,ActorFun). functions(E) -> ActorFun = fun({M,F,A},{_Proc,Node}) -> - io_lib:format("~s~n~w",[mfa(M,F,A),Node]) + io_lib:format("~ts~n~w",[mfa(M,F,A),Node]) end, calltrace_filter(E,ActorFun). @@ -221,7 +221,7 @@ label(Event=#event{label=L,contents=C}) -> false -> Event end. label(L,{M,F,A}) -> label(L,M,F,A); -label(L,Other) -> io_lib:format("~w ~w",[L,Other]). +label(L,Other) -> io_lib:format("~w ~tw",[L,Other]). label(call,M,F,A) -> "call " ++ mfa(M,F,A); label(return_from,M,F,A) -> "return_from " ++ mfa(M,F,A); label(return_to,M,F,A) -> "return_to " ++ mfa(M,F,A); diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile index 6100af5e17..fcb1b73911 100644 --- a/lib/observer/test/Makefile +++ b/lib/observer/test/Makefile @@ -27,7 +27,8 @@ MODULES = \ ttb_SUITE \ client \ server \ - crashdump_helper + crashdump_helper \ + crashdump_helper_unicode ERL_FILES= $(MODULES:%=%.erl) @@ -46,7 +47,7 @@ RELSYSDIR = $(RELEASE_PATH)/observer_test # FLAGS # ---------------------------------------------------- ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += +ERL_COMPILE_FLAGS += +nowarn_export_all EBIN = . diff --git a/lib/observer/test/crashdump_helper_unicode.erl b/lib/observer/test/crashdump_helper_unicode.erl new file mode 100644 index 0000000000..60c3d20315 --- /dev/null +++ b/lib/observer/test/crashdump_helper_unicode.erl @@ -0,0 +1,22 @@ +-module(crashdump_helper_unicode). +-behaviour(gen_server). +-export([start/0, init/1, handle_call/3, handle_cast/2]). +-record(state, {s,a,b,lb}). + +start() -> + gen_server:start({local, 'unicode_reg_name_αβ'}, ?MODULE, [], []). + +init([]) -> + process_flag(trap_exit, true), + ets:new('tab_αβ',[set,named_table]), + Bin = <<"bin αβ"/utf8>>, + LongBin = <<"long bin αβ - a utf8 binary which can be expanded αβ"/utf8>>, + {ok, #state{s = "unicode_string_αβ", + a = 'unicode_atom_αβ', + b = Bin, + lb = LongBin}}. + +handle_call(_Info, _From, State) -> + {reply, ok, State}. +handle_cast(_Info, State) -> + {noreply, State}. diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 1fd94ffb3c..77cf086d4b 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -427,6 +427,18 @@ special(File,Procs) -> {ok,_,[TW]} = crashdump_viewer:general_info(), {match,_} = re:run(TW,"CRASH DUMP SIZE LIMIT REACHED"), ok; + ".unicode" -> + #proc{pid=Pid0} = + lists:keyfind("'unicode_reg_name_αβ'",#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" unicode registered name ok",[]), + + {ok,[#ets_table{id="'tab_αβ'",name="'tab_αβ'"}],[]} = + crashdump_viewer:ets_tables(Pid), + io:format(" unicode table name ok",[]), + + ok; _ -> ok end, @@ -492,7 +504,8 @@ do_create_dumps(DataDir,Rel) -> CD5 = dump_with_args(DataDir,Rel,"trunc.bytes", "-env ERL_CRASH_DUMP_BYTES " ++ integer_to_list(Bytes)), - {[CD1,CD2,CD3,CD4,CD5], DosDump}; + CD6 = dump_with_unicode_atoms(DataDir,Rel,"unicode"), + {[CD1,CD2,CD3,CD4,CD5,CD6], DosDump}; _ -> {[CD1,CD2], DosDump} end. @@ -573,6 +586,16 @@ dump_with_strange_module_name(DataDir,Rel,DumpName) -> ?t:stop_node(n1), CD. +dump_with_unicode_atoms(DataDir,Rel,DumpName) -> + Opt = rel_opt(Rel), + Pz = "-pz \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"", + PzOpt = [{args,Pz}], + {ok,N1} = ?t:start_node(n1,peer,Opt ++ PzOpt), + {ok,_Pid} = rpc:call(N1,crashdump_helper_unicode,start,[]), + CD = dump(N1,DataDir,Rel,DumpName), + ?t:stop_node(n1), + CD. + dump(Node,DataDir,Rel,DumpName) -> Crashdump = filename:join(DataDir, dump_prefix(Rel)++DumpName), rpc:call(Node,os,putenv,["ERL_CRASH_DUMP",Crashdump]), diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl index 7f0c1ac6e4..1b075a507d 100644 --- a/lib/runtime_tools/src/observer_backend.erl +++ b/lib/runtime_tools/src/observer_backend.erl @@ -36,6 +36,7 @@ ttb_write_binary/2, ttb_stop/1, ttb_fetch/2, + ttb_fetch/3, ttb_resume_trace/0, ttb_get_filenames/1]). -define(CHUNKSIZE,8191). % 8 kbytes - 1 byte @@ -658,22 +659,42 @@ stop_seq_trace() -> %% Fetch ttb logs from remote node ttb_fetch(MetaFile,{Port,Host}) -> + ttb_fetch(MetaFile,{Port,Host},undefined). +ttb_fetch(MetaFile,{Port,Host},MasterEnc) -> erlang:process_flag(priority,low), Files = ttb_get_filenames(MetaFile), {ok, Sock} = gen_tcp:connect(Host, Port, [binary, {packet, 2}]), - send_files({Sock,Host},Files), + send_files({Sock,Host},Files,MasterEnc,file:native_name_encoding()), ok = gen_tcp:close(Sock). -send_files({Sock,Host},[File|Files]) -> +send_files({Sock,Host},[File|Files],MasterEnc,MyEnc) -> {ok,Fd} = file:open(File,[raw,read,binary]), - ok = gen_tcp:send(Sock,<<1,(list_to_binary(filename:basename(File)))/binary>>), + Basename = filename:basename(File), + {Code,FilenameBin} = encode_filename(Basename,MasterEnc,MyEnc), + ok = gen_tcp:send(Sock,<<Code,FilenameBin/binary>>), send_chunks(Sock,Fd), ok = file:delete(File), - send_files({Sock,Host},Files); -send_files({_Sock,_Host},[]) -> + send_files({Sock,Host},Files,MasterEnc,MyEnc); +send_files({_Sock,_Host},[],_MasterEnc,_MyEnc) -> done. +encode_filename(Basename,undefined,MyEnc) -> + %% Compatible with old version of ttb.erl, but no longer crashing + %% for code points > 255. + {1,unicode:characters_to_binary(Basename,MyEnc,MyEnc)}; +encode_filename(Basename,MasterEnc,MyEnc) -> + case unicode:characters_to_binary(Basename,MyEnc,MasterEnc) of + Bin when is_binary(Bin) -> + %% Encoding succeeded + {2,Bin}; + _ -> + %% Can't convert Basename from my encoding to the master + %% node's encoding. Doing my best and hoping that master + %% node can fix it... + {3,unicode:characters_to_binary(Basename,MyEnc,MyEnc)} + end. + send_chunks(Sock,Fd) -> case file:read(Fd,?CHUNKSIZE) of {ok,Bin} -> |