diff options
author | Siri Hansen <[email protected]> | 2017-09-07 16:16:01 +0200 |
---|---|---|
committer | Siri Hansen <[email protected]> | 2017-09-07 16:16:01 +0200 |
commit | b569db7fd80de6f6f049797fa7676bdfbe55cc4f (patch) | |
tree | ff24ace33a45b2dc75f9d955a88bc92fdc2f2acc /lib/stdlib | |
parent | 8e3baffd206247d3023c3e00d4d0849c23f3fc58 (diff) | |
parent | 87fa9801618397087d6a7b521e370506c5bfff91 (diff) | |
download | otp-b569db7fd80de6f6f049797fa7676bdfbe55cc4f.tar.gz otp-b569db7fd80de6f6f049797fa7676bdfbe55cc4f.tar.bz2 otp-b569db7fd80de6f6f049797fa7676bdfbe55cc4f.zip |
Merge branch 'siri/unicode-merge' into maint
* siri/unicode-merge: (28 commits)
stdlib: use 'unicode' option for regexp in ets
ct: use 'unicode' option for regexps
syntax_tools: add 'unicode' option to re:run for matching paths
kernel: update simple error logger to print Unicode strings
stdlib: add Unicode translation modifier in error_logger_tty_h
wx: add Unicode translation modifier to wx_object
stdlib: add Unicode translation modifier in debug format funs
sasl: set encoding of SASL report log
stdlib: use Unicode translation modifier in error_logger_file_h
observer: Improve handling of Unicode
mnesia: Improve handling of Unicode
stdlib : Improve handling of Unicode
kernel: Improve handling of Unicode
hipe: Improve handling of Unicode
edoc: Improve handling of Unicode
syntax_tools: Improve handling of Unicode
dialyzer: Improve handling of Unicode
et: Improve handling of Unicode
xref: Improve handling of Unicode
fprof: Modify handling of Unicode
eprof: Improve handling of Unicode
eunit: Improve handling of Unicode
stdlib: Improve handling of Unicode in escript
stdlib: Improve handling of Unicode in edlin_expand
stdlib: Modify handling of Unicode in proc_lib
sasl: Improve handling of Unicode
edoc: Improve handling of Unicode
debugger: Improve handling of Unicode
OTP-14462
OTP-14464
Diffstat (limited to 'lib/stdlib')
-rw-r--r-- | lib/stdlib/src/dets.erl | 20 | ||||
-rw-r--r-- | lib/stdlib/src/dets_utils.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/src/edlin_expand.erl | 26 | ||||
-rw-r--r-- | lib/stdlib/src/error_logger_file_h.erl | 36 | ||||
-rw-r--r-- | lib/stdlib/src/error_logger_tty_h.erl | 116 | ||||
-rw-r--r-- | lib/stdlib/src/escript.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/ets.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/gen.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/gen_event.erl | 20 | ||||
-rw-r--r-- | lib/stdlib/src/gen_fsm.erl | 40 | ||||
-rw-r--r-- | lib/stdlib/src/gen_server.erl | 28 | ||||
-rw-r--r-- | lib/stdlib/src/gen_statem.erl | 30 | ||||
-rw-r--r-- | lib/stdlib/src/proc_lib.erl | 24 | ||||
-rw-r--r-- | lib/stdlib/src/qlc.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/shell.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/slave.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/src/supervisor.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/test/Makefile | 1 | ||||
-rw-r--r-- | lib/stdlib/test/edlin_expand_SUITE.erl | 26 | ||||
-rw-r--r-- | lib/stdlib/test/error_logger_h_SUITE.erl | 10 | ||||
-rw-r--r-- | lib/stdlib/test/proc_lib_SUITE.erl | 33 | ||||
-rw-r--r-- | lib/stdlib/test/unicode_expand.erl | 36 |
22 files changed, 262 insertions, 206 deletions
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index 10e8c9c800..4e3fe0e5c1 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -1354,7 +1354,7 @@ open_file_loop2(Head, N) -> ?MODULE, [], Head); Message -> error_logger:format("** dets: unexpected message" - "(ignored): ~w~n", [Message]), + "(ignored): ~tw~n", [Message]), open_file_loop(Head, N) end. @@ -1403,7 +1403,7 @@ apply_op(Op, From, Head, N) -> Head; _Dirty when N =:= 0 -> % dirty or new_dirty %% The updates seems to have declined - dets_utils:vformat("** dets: Auto save of ~p\n", + dets_utils:vformat("** dets: Auto save of ~tp\n", [Head#head.name]), {NewHead, _Res} = perform_save(Head, true), erlang:garbage_collect(), @@ -1587,13 +1587,13 @@ bug_found(Name, Op, Bad, From) -> %% If stream_op/5 found more requests, this is not %% the last operation. error_logger:format - ("** dets: Bug was found when accessing table ~w,~n" - "** dets: operation was ~p and reply was ~w.~n" - "** dets: Stacktrace: ~w~n", + ("** dets: Bug was found when accessing table ~tw,~n" + "** dets: operation was ~tp and reply was ~tw.~n" + "** dets: Stacktrace: ~tw~n", [Name, Op, Bad, erlang:get_stacktrace()]); false -> error_logger:format - ("** dets: Bug was found when accessing table ~w~n", + ("** dets: Bug was found when accessing table ~tw~n", [Name]) end, if @@ -2117,7 +2117,7 @@ do_open_file([Fname, Verbose], Parent, Server, Ref) -> Error; Bad -> error_logger:format - ("** dets: Bug was found in open_file/1, reply was ~w.~n", + ("** dets: Bug was found in open_file/1, reply was ~tw.~n", [Bad]), {error, {dets_bug, Fname, Bad}} end; @@ -2135,7 +2135,7 @@ do_open_file([Tab, OpenArgs, Verb], Parent, Server, _Ref) -> Bad -> error_logger:format ("** dets: Bug was found in open_file/2, arguments were~n" - "** dets: ~w and reply was ~w.~n", + "** dets: ~tw and reply was ~tw.~n", [OpenArgs, Bad]), {error, {dets_bug, Tab, {open_file, OpenArgs}, Bad}} end. @@ -3123,7 +3123,7 @@ check_safe_fixtable(Head) -> ((get(verbose) =:= yes) orelse dets_utils:debug_mode()) of true -> error_logger:format - ("** dets: traversal of ~p needs safe_fixtable~n", + ("** dets: traversal of ~tp needs safe_fixtable~n", [Head#head.name]); false -> ok @@ -3189,7 +3189,7 @@ scan_read(H, From, _To, Min, _L, Ts, R, C) -> err(Error) -> case get(verbose) of yes -> - error_logger:format("** dets: failed with ~w~n", [Error]), + error_logger:format("** dets: failed with ~tw~n", [Error]), Error; undefined -> Error diff --git a/lib/stdlib/src/dets_utils.erl b/lib/stdlib/src/dets_utils.erl index da6ebd18f2..17f55ebdc2 100644 --- a/lib/stdlib/src/dets_utils.erl +++ b/lib/stdlib/src/dets_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2016. All Rights Reserved. +%% Copyright Ericsson AB 2001-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -387,7 +387,7 @@ corrupt_reason(Head, Reason0) -> corrupt(Head, Error) -> case get(verbose) of yes -> - error_logger:format("** dets: Corrupt table ~p: ~tp\n", + error_logger:format("** dets: Corrupt table ~tp: ~tp\n", [Head#head.name, Error]); _ -> ok end, diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl index a1a97af4c5..bdcefda6e5 100644 --- a/lib/stdlib/src/edlin_expand.erl +++ b/lib/stdlib/src/edlin_expand.erl @@ -23,7 +23,7 @@ -export([expand/1, format_matches/1]). --import(lists, [reverse/1, nthtail/2, prefix/2]). +-import(lists, [reverse/1, prefix/2]). %% expand(CurrentBefore) -> %% {yes, Expansion, Matches} | {no, Matches} @@ -75,15 +75,15 @@ to_atom(Str) -> end. match(Prefix, Alts, Extra0) -> - Len = length(Prefix), + Len = string:length(Prefix), Matches = lists:sort( [{S, A} || {H, A} <- Alts, - prefix(Prefix, S=hd(io_lib:fwrite("~w",[H])))]), + prefix(Prefix, S=flat_write(H))]), case longest_common_head([N || {N, _} <- Matches]) of {partial, []} -> {no, [], Matches}; % format_matches(Matches)}; {partial, Str} -> - case nthtail(Len, Str) of + case string:slice(Str, Len) of [] -> {yes, [], Matches}; % format_matches(Matches)}; Remain -> @@ -94,18 +94,21 @@ match(Prefix, Alts, Extra0) -> {"(",[{Str,0}]} -> "()"; {_,_} -> Extra0 end, - {yes, nthtail(Len, Str) ++ Extra, []}; + {yes, string:slice(Str, Len) ++ Extra, []}; no -> {no, [], []} end. +flat_write(T) -> + lists:flatten(io_lib:fwrite("~tw",[T])). + %% Return the list of names L in multiple columns. format_matches(L) -> {S1, Dots} = format_col(lists:sort(L), []), S = case Dots of true -> {_, Prefix} = longest_common_head(vals(L)), - PrefixLen = length(Prefix), + PrefixLen = string:length(Prefix), case PrefixLen =< 3 of true -> S1; % Do not replace the prefix with "...". false -> @@ -128,7 +131,7 @@ format_col([A|T], Width, Len, Acc0, LL, Dots) -> {H0, R} = format_val(A), Hmax = LL - length(R), {H, NewDots} = - case length(H0) > Hmax of + case string:length(H0) > Hmax of true -> {io_lib:format("~-*ts", [Hmax - 3, H0]) ++ "...", true}; false -> {H0, Dots} end, @@ -149,12 +152,12 @@ format_val(H) -> field_width(L, LL) -> field_width(L, 0, LL). field_width([{H,_}|T], W, LL) -> - case length(H) of + case string:length(H) of L when L > W -> field_width(T, L, LL); _ -> field_width(T, W, LL) end; field_width([H|T], W, LL) -> - case length(H) of + case string:length(H) of L when L > W -> field_width(T, L, LL); _ -> field_width(T, W, LL) end; @@ -169,10 +172,11 @@ vals([S|L]) -> [S|vals(L)]. leading_dots([], _Len) -> []; leading_dots([{H, I}|L], Len) -> - [{"..." ++ nthtail(Len, H), I}|leading_dots(L, Len)]; + [{"..." ++ string:slice(H, Len), I}|leading_dots(L, Len)]; leading_dots([H|L], Len) -> - ["..." ++ nthtail(Len, H)|leading_dots(L, Len)]. + ["..." ++ string:slice(H, Len)|leading_dots(L, Len)]. +%% Strings are handled naively, but it should be OK here. longest_common_head([]) -> no; longest_common_head(LL) -> diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl index b7c193f965..58da0cbdd6 100644 --- a/lib/stdlib/src/error_logger_file_h.erl +++ b/lib/stdlib/src/error_logger_file_h.erl @@ -126,7 +126,7 @@ format_body(State, [{Format,Args}|T]) -> S0 catch _:_ -> - format(State, "ERROR: ~p - ~p\n", [Format,Args]) + format(State, "ERROR: ~tp - ~tp\n", [Format,Args]) end, [S|format_body(State, T)]; format_body(_State, []) -> @@ -165,44 +165,26 @@ parse_event({warning_report, _GL, {Pid, std_warning, Args}}) -> parse_event(_) -> ignore. format_term(Term) when is_list(Term) -> - case string_p(Term) of + case string_p(lists:flatten(Term)) of true -> - [{"~s\n",[Term]}]; + [{"~ts\n",[Term]}]; false -> format_term_list(Term) end; format_term(Term) -> - [{"~p\n",[Term]}]. + [{"~tp\n",[Term]}]. format_term_list([{Tag,Data}|T]) -> - [{" ~p: ~p\n",[Tag,Data]}|format_term_list(T)]; + [{" ~tp: ~tp\n",[Tag,Data]}|format_term_list(T)]; format_term_list([Data|T]) -> - [{" ~p\n",[Data]}|format_term_list(T)]; + [{" ~tp\n",[Data]}|format_term_list(T)]; format_term_list([]) -> - []; -format_term_list(_) -> - %% Continue to allow non-proper lists for now. - %% FIXME: Remove this clause in OTP 19. []. string_p([]) -> false; -string_p(Term) -> - string_p1(Term). - -string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 -> - string_p1(T); -string_p1([$\n|T]) -> string_p1(T); -string_p1([$\r|T]) -> string_p1(T); -string_p1([$\t|T]) -> string_p1(T); -string_p1([$\v|T]) -> string_p1(T); -string_p1([$\b|T]) -> string_p1(T); -string_p1([$\f|T]) -> string_p1(T); -string_p1([$\e|T]) -> string_p1(T); -string_p1([H|T]) when is_list(H) -> - string_p1(H) andalso string_p1(T); -string_p1([]) -> true; -string_p1(_) -> false. +string_p(FlatList) -> + io_lib:printable_list(FlatList). get_utc_config() -> %% SASL utc_log configuration overrides stdlib config @@ -225,7 +207,7 @@ header(Time, Title) -> end. header({{Y,Mo,D},{H,Mi,S}}, Title, UTC) -> - io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ~s===~n", + io_lib:format("~n=~ts==== ~p-~s-~p::~s:~s:~s ~s===~n", [Title,D,month(Mo),Y,t(H),t(Mi),t(S),UTC]). t(X) when is_integer(X) -> diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl index 8f0d7b0362..fa940b7264 100644 --- a/lib/stdlib/src/error_logger_tty_h.erl +++ b/lib/stdlib/src/error_logger_tty_h.erl @@ -39,13 +39,16 @@ {user, prev_handler, io_mod=io, - depth=unlimited}). + depth=unlimited, + modifier=""}). %% This one is used when we takeover from the simple error_logger. init({[], {error_logger, Buf}}) -> User = set_group_leader(), Depth = error_logger:get_format_depth(), - State = #st{user=User,prev_handler=error_logger,depth=Depth}, + Modifier = modifier(), + State = #st{user=User,prev_handler=error_logger, + depth=Depth,modifier=Modifier}, write_events(State, Buf), {ok, State}; %% This one is used if someone took over from us, and now wants to @@ -57,7 +60,8 @@ init({[], {error_logger_tty_h, PrevHandler}}) -> init([]) -> User = set_group_leader(), Depth = error_logger:get_format_depth(), - {ok, #st{user=User,prev_handler=[],depth=Depth}}. + Modifier = modifier(), + {ok, #st{user=User,prev_handler=[],depth=Depth,modifier=Modifier}}. handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() -> {ok, State}; @@ -91,8 +95,9 @@ code_change(_OldVsn, State, _Extra) -> write_event(Event, IoMod) -> do_write_event(#st{io_mod=IoMod}, Event). -write_event(Event, IoMod, Depth) -> - do_write_event(#st{io_mod=IoMod,depth=Depth}, Event). +write_event(Event, IoMod, {Depth, Enc}) -> + Modifier = modifier(Enc), + do_write_event(#st{io_mod=IoMod,depth=Depth,modifier=Modifier}, Event). %%% ------------------------------------------------------ @@ -120,12 +125,12 @@ write_events(State, [Ev|Es]) -> write_events(_State, []) -> ok. -do_write_event(State, {Time, Event}) -> - case parse_event(Event) of +do_write_event(#st{modifier=M}=State, {Time, Event}) -> + case parse_event(Event,M) of ignore -> ok; {Title,Pid,FormatList} -> - Header = header(Time, Title), + Header = header(Time, Title, M), Body = format_body(State, FormatList), AtNode = if node(Pid) =/= node() -> @@ -144,13 +149,13 @@ do_write_event(State, {Time, Event}) -> do_write_event(_, _) -> ok. -format_body(State, [{Format,Args}|T]) -> +format_body(#st{modifier=M}=State, [{Format,Args}|T]) -> S = try format(State, Format, Args) of S0 -> S0 catch _:_ -> - format(State, "ERROR: ~p - ~p\n", [Format,Args]) + format(State, "ERROR: ~"++M++"p - ~"++M++"p\n", [Format,Args]) end, [S|format_body(State, T)]; format_body(_State, []) -> @@ -174,62 +179,41 @@ limit_format([H|T], Depth) -> limit_format([], _) -> []. -parse_event({error, _GL, {Pid, Format, Args}}) -> +parse_event({error, _GL, {Pid, Format, Args}},_) -> {"ERROR REPORT",Pid,[{Format,Args}]}; -parse_event({info_msg, _GL, {Pid, Format, Args}}) -> +parse_event({info_msg, _GL, {Pid, Format, Args}},_) -> {"INFO REPORT",Pid,[{Format, Args}]}; -parse_event({warning_msg, _GL, {Pid, Format, Args}}) -> +parse_event({warning_msg, _GL, {Pid, Format, Args}},_) -> {"WARNING REPORT",Pid,[{Format,Args}]}; -parse_event({error_report, _GL, {Pid, std_error, Args}}) -> - {"ERROR REPORT",Pid,format_term(Args)}; -parse_event({info_report, _GL, {Pid, std_info, Args}}) -> - {"INFO REPORT",Pid,format_term(Args)}; -parse_event({warning_report, _GL, {Pid, std_warning, Args}}) -> - {"WARNING REPORT",Pid,format_term(Args)}; -parse_event(_) -> ignore. - -format_term(Term) when is_list(Term) -> - case string_p(Term) of +parse_event({error_report, _GL, {Pid, std_error, Args}},M) -> + {"ERROR REPORT",Pid,format_term(Args,M)}; +parse_event({info_report, _GL, {Pid, std_info, Args}},M) -> + {"INFO REPORT",Pid,format_term(Args,M)}; +parse_event({warning_report, _GL, {Pid, std_warning, Args}},M) -> + {"WARNING REPORT",Pid,format_term(Args,M)}; +parse_event(_,_) -> ignore. + +format_term(Term,M) when is_list(Term) -> + case string_p(lists:flatten(Term)) of true -> - [{"~s\n",[Term]}]; + [{"~"++M++"s\n",[Term]}]; false -> - format_term_list(Term) + format_term_list(Term,M) end; -format_term(Term) -> - [{"~p\n",[Term]}]. - -format_term_list([{Tag,Data}|T]) -> - [{" ~p: ~p\n",[Tag,Data]}|format_term_list(T)]; -format_term_list([Data|T]) -> - [{" ~p\n",[Data]}|format_term_list(T)]; -format_term_list([]) -> - []; -format_term_list(_) -> - %% Continue to allow non-proper lists for now. - %% FIXME: Remove this clause in OTP 19. +format_term(Term,M) -> + [{"~"++M++"p\n",[Term]}]. + +format_term_list([{Tag,Data}|T],M) -> + [{" ~"++M++"p: ~"++M++"p\n",[Tag,Data]}|format_term_list(T,M)]; +format_term_list([Data|T],M) -> + [{" ~"++M++"p\n",[Data]}|format_term_list(T,M)]; +format_term_list([],_) -> []. string_p([]) -> false; -string_p(Term) -> - string_p1(Term). - -string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 -> - string_p1(T); -string_p1([$\n|T]) -> string_p1(T); -string_p1([$\r|T]) -> string_p1(T); -string_p1([$\t|T]) -> string_p1(T); -string_p1([$\v|T]) -> string_p1(T); -string_p1([$\b|T]) -> string_p1(T); -string_p1([$\f|T]) -> string_p1(T); -string_p1([$\e|T]) -> string_p1(T); -string_p1([H|T]) when is_list(H) -> - case string_p1(H) of - true -> string_p1(T); - _ -> false - end; -string_p1([]) -> true; -string_p1(_) -> false. +string_p(FlatList) -> + io_lib:printable_list(FlatList). get_utc_config() -> %% SASL utc_log configuration overrides stdlib config @@ -243,16 +227,16 @@ get_utc_config() -> end end. -header(Time, Title) -> +header(Time, Title, M) -> case get_utc_config() of true -> - header(Time, Title, "UTC "); + header(Time, Title, "UTC ", M); _ -> - header(calendar:universal_time_to_local_time(Time), Title, "") + header(calendar:universal_time_to_local_time(Time), Title, "", M) end. -header({{Y,Mo,D},{H,Mi,S}}, Title, UTC) -> - io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ~s===~n", +header({{Y,Mo,D},{H,Mi,S}}, Title, UTC, M) -> + io_lib:format("~n=~"++M++"s==== ~p-~s-~p::~s:~s:~s ~s===~n", [Title,D,month(Mo),Y,t(H),t(Mi),t(S),UTC]). t(X) when is_integer(X) -> @@ -274,3 +258,13 @@ month(9) -> "Sep"; month(10) -> "Oct"; month(11) -> "Nov"; month(12) -> "Dec". + +modifier() -> + modifier(encoding()). +modifier(latin1) -> + ""; +modifier(_) -> + "t". + +encoding() -> + proplists:get_value(encoding,io:getopts(),latin1). diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index 2093916a7c..2b9d8ff65b 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -860,7 +860,7 @@ code_handler(Name, Args, Dict, File) -> %% io:format("Calling:~p~n",[{Mod,Name,Args}]), apply(Mod, Name, Args); error -> - io:format("Script does not export ~w/~w\n", [Name,Arity]), + io:format("Script does not export ~tw/~w\n", [Name,Arity]), my_halt(127) end end. diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl index 898b2f5bba..b5d3cd3c8d 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -1693,7 +1693,7 @@ choice(Height, Width, P, Mode, Tab, Key, Turn, Opos) -> end, choice(Height, Width, P, Mode, Tab, Key, Turn, Opos); [$/|Regexp] -> %% from regexp - case re:compile(nonl(Regexp)) of + case re:compile(nonl(Regexp),[unicode]) of {ok,Re} -> re_search(Height, Width, Tab, ets:first(Tab), Re, 1, 1); {error,{ErrorString,_Pos}} -> diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 32f43fc706..33af0aed8f 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -422,7 +422,7 @@ debug_options(Name, Opts) -> try sys:debug_options(Options) catch _:_ -> error_logger:format( - "~p: ignoring erroneous debug options - ~p~n", + "~tp: ignoring erroneous debug options - ~tp~n", [Name,Options]), [] end; diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl index da2b0da3ca..a9b98911e2 100644 --- a/lib/stdlib/src/gen_event.erl +++ b/lib/stdlib/src/gen_event.erl @@ -441,15 +441,15 @@ system_replace_state(StateFun, [ServerName, MSL, HibernateAfterTimeout, Hib]) -> print_event(Dev, {in, Msg}, Name) -> case Msg of {notify, Event} -> - io:format(Dev, "*DBG* ~p got event ~p~n", [Name, Event]); + io:format(Dev, "*DBG* ~tp got event ~tp~n", [Name, Event]); {_,_,{call, Handler, Query}} -> - io:format(Dev, "*DBG* ~p(~p) got call ~p~n", + io:format(Dev, "*DBG* ~tp(~tp) got call ~tp~n", [Name, Handler, Query]); _ -> - io:format(Dev, "*DBG* ~p got ~p~n", [Name, Msg]) + io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg]) end; print_event(Dev, Dbg, Name) -> - io:format(Dev, "*DBG* ~p : ~p~n", [Name, Dbg]). + io:format(Dev, "*DBG* ~tp : ~tp~n", [Name, Dbg]). %% server_add_handler(Handler, Args, MSL) -> {Ret, MSL'}. @@ -582,8 +582,8 @@ server_update(Handler1, Func, Event, SName) -> remove, SName, normal), no; {'EXIT', {undef, [{Mod1, handle_info, [_,_], _}|_]}} -> - error_logger:warning_msg("** Undefined handle_info in ~p~n" - "** Unhandled message: ~p~n", [Mod1, Event]), + error_logger:warning_msg("** Undefined handle_info in ~tp~n" + "** Unhandled message: ~tp~n", [Mod1, Event]), {ok, Handler1}; Other -> do_terminate(Mod1, Handler1, {error, Other}, State, @@ -767,10 +767,10 @@ report_error(Handler, Reason, State, LastIn, SName) -> State end, error_msg("** gen_event handler ~p crashed.~n" - "** Was installed in ~p~n" - "** Last event was: ~p~n" - "** When handler state == ~p~n" - "** Reason == ~p~n", + "** Was installed in ~tp~n" + "** Last event was: ~tp~n" + "** When handler state == ~tp~n" + "** Reason == ~tp~n", [handler(Handler),SName,LastIn,FmtState,Reason1]). handler(Handler) when not Handler#handler.id -> diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl index 9ef0ca818c..96a53426e2 100644 --- a/lib/stdlib/src/gen_fsm.erl +++ b/lib/stdlib/src/gen_fsm.erl @@ -452,30 +452,30 @@ system_replace_state(StateFun, [Name, StateName, StateData, Mod, Time, Hibernate print_event(Dev, {in, Msg}, {Name, StateName}) -> case Msg of {'$gen_event', Event} -> - io:format(Dev, "*DBG* ~p got event ~p in state ~w~n", + io:format(Dev, "*DBG* ~tp got event ~tp in state ~tw~n", [Name, Event, StateName]); {'$gen_all_state_event', Event} -> io:format(Dev, - "*DBG* ~p got all_state_event ~p in state ~w~n", + "*DBG* ~tp got all_state_event ~tp in state ~tw~n", [Name, Event, StateName]); {timeout, Ref, {'$gen_timer', Message}} -> io:format(Dev, - "*DBG* ~p got timer ~p in state ~w~n", + "*DBG* ~tp got timer ~tp in state ~tw~n", [Name, {timeout, Ref, Message}, StateName]); {timeout, _Ref, {'$gen_event', Event}} -> io:format(Dev, - "*DBG* ~p got timer ~p in state ~w~n", + "*DBG* ~tp got timer ~tp in state ~tw~n", [Name, Event, StateName]); _ -> - io:format(Dev, "*DBG* ~p got ~p in state ~w~n", + io:format(Dev, "*DBG* ~tp got ~tp in state ~tw~n", [Name, Msg, StateName]) end; print_event(Dev, {out, Msg, To, StateName}, Name) -> - io:format(Dev, "*DBG* ~p sent ~p to ~w~n" - " and switched to state ~w~n", + io:format(Dev, "*DBG* ~tp sent ~tp to ~tw~n" + " and switched to state ~tw~n", [Name, Msg, To, StateName]); print_event(Dev, return, {Name, StateName}) -> - io:format(Dev, "*DBG* ~p switched to state ~w~n", + io:format(Dev, "*DBG* ~tp switched to state ~tw~n", [Name, StateName]). handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, HibernateAfterTimeout) -> %No debug here @@ -500,7 +500,7 @@ handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, HibernateAfterTi exit(R); {'EXIT', {undef, [{Mod, handle_info, [_,_,_], _}|_]}} -> error_logger:warning_msg("** Undefined handle_info in ~p~n" - "** Unhandled message: ~p~n", [Mod, Msg]), + "** Unhandled message: ~tp~n", [Mod, Msg]), loop(Parent, Name, StateName, StateData, Mod, infinity, HibernateAfterTimeout, []); {'EXIT', What} -> terminate(What, Name, Msg, Mod, StateName, StateData, []); @@ -620,29 +620,29 @@ error_info(Reason, Name, Msg, StateName, StateData, Debug) -> _ -> Reason end, - Str = "** State machine ~p terminating \n" ++ + Str = "** State machine ~tp terminating \n" ++ get_msg_str(Msg) ++ - "** When State == ~p~n" - "** Data == ~p~n" - "** Reason for termination = ~n** ~p~n", + "** When State == ~tp~n" + "** Data == ~tp~n" + "** Reason for termination = ~n** ~tp~n", format(Str, [Name, get_msg(Msg), StateName, StateData, Reason1]), sys:print_log(Debug), ok. get_msg_str({'$gen_event', _Event}) -> - "** Last event in was ~p~n"; + "** Last event in was ~tp~n"; get_msg_str({'$gen_sync_event', _Event}) -> - "** Last sync event in was ~p~n"; + "** Last sync event in was ~tp~n"; get_msg_str({'$gen_all_state_event', _Event}) -> - "** Last event in was ~p (for all states)~n"; + "** Last event in was ~tp (for all states)~n"; get_msg_str({'$gen_sync_all_state_event', _Event}) -> - "** Last sync event in was ~p (for all states)~n"; + "** Last sync event in was ~tp (for all states)~n"; get_msg_str({timeout, _Ref, {'$gen_timer', _Msg}}) -> - "** Last timer event in was ~p~n"; + "** Last timer event in was ~tp~n"; get_msg_str({timeout, _Ref, {'$gen_event', _Msg}}) -> - "** Last timer event in was ~p~n"; + "** Last timer event in was ~tp~n"; get_msg_str(_Msg) -> - "** Last message in was ~p~n". + "** Last message in was ~tp~n". get_msg({'$gen_event', Event}) -> Event; get_msg({'$gen_sync_event', Event}) -> Event; diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index a3d53efd0d..7daa7a9fe4 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -621,7 +621,7 @@ try_dispatch(Mod, Func, Msg, State) -> case erlang:function_exported(Mod, handle_info, 2) of false -> error_logger:warning_msg("** Undefined handle_info in ~p~n" - "** Unhandled message: ~p~n", + "** Unhandled message: ~tp~n", [Mod, Msg]), {ok, {noreply, State}}; true -> @@ -785,21 +785,21 @@ system_replace_state(StateFun, [Name, State, Mod, Time, HibernateAfterTimeout]) print_event(Dev, {in, Msg}, Name) -> case Msg of {'$gen_call', {From, _Tag}, Call} -> - io:format(Dev, "*DBG* ~p got call ~p from ~w~n", + io:format(Dev, "*DBG* ~tp got call ~tp from ~w~n", [Name, Call, From]); {'$gen_cast', Cast} -> - io:format(Dev, "*DBG* ~p got cast ~p~n", + io:format(Dev, "*DBG* ~tp got cast ~tp~n", [Name, Cast]); _ -> - io:format(Dev, "*DBG* ~p got ~p~n", [Name, Msg]) + io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg]) end; print_event(Dev, {out, Msg, To, State}, Name) -> - io:format(Dev, "*DBG* ~p sent ~p to ~w, new state ~w~n", + io:format(Dev, "*DBG* ~tp sent ~tp to ~w, new state ~tp~n", [Name, Msg, To, State]); print_event(Dev, {noreply, State}, Name) -> - io:format(Dev, "*DBG* ~p new state ~w~n", [Name, State]); + io:format(Dev, "*DBG* ~tp new state ~tp~n", [Name, State]); print_event(Dev, Event, Name) -> - io:format(Dev, "*DBG* ~p dbg ~p~n", [Name, Event]). + io:format(Dev, "*DBG* ~tp dbg ~tp~n", [Name, Event]). %%% --------------------------------------------------- @@ -881,10 +881,10 @@ error_info(Reason, Name, From, Msg, State, Debug) -> end, {ClientFmt, ClientArgs} = client_stacktrace(From), LimitedState = error_logger:limit_term(State), - error_logger:format("** Generic server ~p terminating \n" - "** Last message in was ~p~n" - "** When Server state == ~p~n" - "** Reason for termination == ~n** ~p~n" ++ ClientFmt, + error_logger:format("** Generic server ~tp terminating \n" + "** Last message in was ~tp~n" + "** When Server state == ~tp~n" + "** Reason for termination == ~n** ~tp~n" ++ ClientFmt, [Name, Msg, LimitedState, Reason1] ++ ClientArgs), sys:print_log(Debug), ok. @@ -898,11 +898,11 @@ client_stacktrace(From) when is_pid(From), node(From) =:= node() -> {"** Client ~p is dead~n", [From]}; [{current_stacktrace, Stacktrace}, {registered_name, []}] -> {"** Client ~p stacktrace~n" - "** ~p~n", + "** ~tp~n", [From, Stacktrace]}; [{current_stacktrace, Stacktrace}, {registered_name, Name}] -> - {"** Client ~p stacktrace~n" - "** ~p~n", + {"** Client ~tp stacktrace~n" + "** ~tp~n", [Name, Stacktrace]} end; client_stacktrace(From) when is_pid(From) -> diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl index b5e9da1e66..1110d18af6 100644 --- a/lib/stdlib/src/gen_statem.erl +++ b/lib/stdlib/src/gen_statem.erl @@ -791,34 +791,34 @@ format_status( print_event(Dev, {in,Event}, {Name,State}) -> io:format( - Dev, "*DBG* ~p receive ~s in state ~p~n", + Dev, "*DBG* ~tp receive ~ts in state ~tp~n", [Name,event_string(Event),State]); print_event(Dev, {out,Reply,{To,_Tag}}, {Name,State}) -> io:format( - Dev, "*DBG* ~p send ~p to ~p from state ~p~n", + Dev, "*DBG* ~tp send ~tp to ~p from state ~tp~n", [Name,Reply,To,State]); print_event(Dev, {terminate,Reason}, {Name,State}) -> io:format( - Dev, "*DBG* ~p terminate ~p in state ~p~n", + Dev, "*DBG* ~tp terminate ~tp in state ~tp~n", [Name,Reason,State]); print_event(Dev, {Tag,Event,NextState}, {Name,State}) -> StateString = case NextState of State -> - io_lib:format("~p", [State]); + io_lib:format("~tp", [State]); _ -> - io_lib:format("~p => ~p", [State,NextState]) + io_lib:format("~tp => ~tp", [State,NextState]) end, io:format( - Dev, "*DBG* ~p ~w ~s in state ~s~n", + Dev, "*DBG* ~tp ~tw ~ts in state ~ts~n", [Name,Tag,event_string(Event),StateString]). event_string(Event) -> case Event of {{call,{Pid,_Tag}},Request} -> - io_lib:format("call ~p from ~w", [Request,Pid]); + io_lib:format("call ~tp from ~w", [Request,Pid]); {EventType,EventContent} -> - io_lib:format("~w ~p", [EventType,EventContent]) + io_lib:format("~tw ~tp", [EventType,EventContent]) end. sys_debug(Debug, #{name := Name}, State, Entry) -> @@ -1732,25 +1732,25 @@ error_info( CallbackMode end, error_logger:format( - "** State machine ~p terminating~n" ++ + "** State machine ~tp terminating~n" ++ case Q of [] -> ""; - _ -> "** Last event = ~p~n" + _ -> "** Last event = ~tp~n" end ++ - "** When server state = ~p~n" ++ - "** Reason for termination = ~w:~p~n" ++ + "** When server state = ~tp~n" ++ + "** Reason for termination = ~w:~tp~n" ++ "** Callback mode = ~p~n" ++ case Q of - [_,_|_] -> "** Queued = ~p~n"; + [_,_|_] -> "** Queued = ~tp~n"; _ -> "" end ++ case P of [] -> ""; - _ -> "** Postponed = ~p~n" + _ -> "** Postponed = ~tp~n" end ++ case FixedStacktrace of [] -> ""; - _ -> "** Stacktrace =~n** ~p~n" + _ -> "** Stacktrace =~n** ~tp~n" end, [Name | case Q of diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl index d4d1bdccec..8e10cbe93b 100644 --- a/lib/stdlib/src/proc_lib.erl +++ b/lib/stdlib/src/proc_lib.erl @@ -823,22 +823,22 @@ to_string(A, _) -> io_lib:write_atom(A). pp_fun({Enc,Depth}) -> - {Letter,Tl} = case Depth of - unlimited -> {"p",[]}; - _ -> {"P",[Depth]} - end, - P = modifier(Enc) ++ Letter, + {P,Tl} = p(Enc, Depth), fun(Term, I) -> io_lib:format("~." ++ integer_to_list(I) ++ P, [Term|Tl]) end. -format_tag(Indent, Tag, Data, {_Enc,Depth}) -> - case Depth of - unlimited -> - io_lib:format("~s~p: ~80.18p~n", [Indent, Tag, Data]); - _ -> - io_lib:format("~s~p: ~80.18P~n", [Indent, Tag, Data, Depth]) - end. +format_tag(Indent, Tag, Data, {Enc,Depth}) -> + {P,Tl} = p(Enc, Depth), + io_lib:format("~s~p: ~80.18" ++ P ++ "\n", [Indent, Tag, Data|Tl]). + +p(Encoding, Depth) -> + {Letter, Tl} = case Depth of + unlimited -> {"p", []}; + _ -> {"P", [Depth]} + end, + P = modifier(Encoding) ++ Letter, + {P, Tl}. modifier(latin1) -> ""; modifier(_) -> "t". diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl index 535ca57a6b..f11f9d0a0b 100644 --- a/lib/stdlib/src/qlc.erl +++ b/lib/stdlib/src/qlc.erl @@ -1132,7 +1132,7 @@ wait_for_request(Parent, MonRef, Post) -> wait_for_request(Parent, MonRef, Post); Other -> error_logger:error_msg( - "The qlc cursor ~w received an unexpected message:\n~p\n", + "The qlc cursor ~w received an unexpected message:\n~tp\n", [self(), Other]), wait_for_request(Parent, MonRef, Post) end. diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index 26b3960f4f..212b143b1d 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -1459,7 +1459,7 @@ check_env(V) -> {ok, Val} -> Txt = io_lib:fwrite ("Invalid value of STDLIB configuration parameter" - "~w: ~tp\n", [V, Val]), + "~tw: ~tp\n", [V, Val]), error_logger:info_report(lists:flatten(Txt)) end. diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl index 5b5c328c0c..d7cf6386f5 100644 --- a/lib/stdlib/src/slave.erl +++ b/lib/stdlib/src/slave.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ start_pseudo(_,_,_) -> ok. %% It's already there Pid :: pid(). relay({badrpc,Reason}) -> - error_msg(" ** exiting relay server ~w :~w **~n", [self(),Reason]), + error_msg(" ** exiting relay server ~w :~tw **~n", [self(),Reason]), exit(Reason); relay(undefined) -> error_msg(" ** exiting relay server ~w **~n", [self()]), diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 1cd65fbf18..7920e55930 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -628,7 +628,7 @@ handle_info({'EXIT', Pid, Reason}, State) -> end; handle_info(Msg, State) -> - error_logger:error_msg("Supervisor received unexpected message: ~p~n", + error_logger:error_msg("Supervisor received unexpected message: ~tp~n", [Msg]), {noreply, State}. diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index 72211332e9..7b79dcf04d 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -36,6 +36,7 @@ MODULES= \ ets_tough_SUITE \ expand_test \ expand_test1 \ + unicode_expand \ ExpandTestCaps \ ExpandTestCaps1 \ filelib_SUITE \ diff --git a/lib/stdlib/test/edlin_expand_SUITE.erl b/lib/stdlib/test/edlin_expand_SUITE.erl index 1f694ea549..5c2b1965ba 100644 --- a/lib/stdlib/test/edlin_expand_SUITE.erl +++ b/lib/stdlib/test/edlin_expand_SUITE.erl @@ -22,7 +22,7 @@ init_per_testcase/2, end_per_testcase/2, init_per_group/2,end_per_group/2]). -export([normal/1, quoted_fun/1, quoted_module/1, quoted_both/1, erl_1152/1, - erl_352/1]). + erl_352/1, unicode/1]). -include_lib("common_test/include/ct.hrl"). @@ -37,7 +37,8 @@ suite() -> {timetrap,{minutes,1}}]. all() -> - [normal, quoted_fun, quoted_module, quoted_both, erl_1152, erl_352]. + [normal, quoted_fun, quoted_module, quoted_both, erl_1152, erl_352, + unicode]. groups() -> []. @@ -150,6 +151,7 @@ quoted_both(Config) when is_list(Config) -> {yes,"weird-fun-name'()",[]} = do_expand("'ExpandTestCaps1':'#"), ok. +%% Note: pull request #1152. erl_1152(Config) when is_list(Config) -> "\n"++"foo"++" "++[1089]++_ = do_format(["foo",[1089]]), ok. @@ -226,6 +228,26 @@ check_trailing([I|Str], ArityStr, Suffix, Dots) -> Rest =:= Suffix end. +unicode(Config) when is_list(Config) -> + {module,unicode_expand} = c:l('unicode_expand'), + {no,[],[{"'кlирилли́ческий атом'",0}, + {"'кlирилли́ческий атом'",1}, + {"'кlирилли́ческий атомB'",1}, + {"module_info",0}, + {"module_info",1}]} = do_expand("unicode_expand:"), + {yes,"рилли́ческий атом", []} = do_expand("unicode_expand:'кlи"), + {yes,"еский атом", []} = do_expand("unicode_expand:'кlирилли́ч"), + {yes,"(",[]} = do_expand("unicode_expand:'кlирилли́ческий атомB'"), + "\n'кlирилли́ческий атом'/0 'кlирилли́ческий атом'/1 " + "'кlирилли́ческий атомB'/1 \nmodule_info/0 " + "module_info/1 \n" = + do_format([{"'кlирилли́ческий атом'",0}, + {"'кlирилли́ческий атом'",1}, + {"'кlирилли́ческий атомB'",1}, + {"module_info",0}, + {"module_info",1}]), + ok. + do_expand(String) -> edlin_expand:expand(lists:reverse(String)). diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl index 30f96e0522..1f2a9fda0b 100644 --- a/lib/stdlib/test/error_logger_h_SUITE.erl +++ b/lib/stdlib/test/error_logger_h_SUITE.erl @@ -162,7 +162,7 @@ tty_log_open(Log) -> {ok,D} -> D; _ -> unlimited end, - error_logger:add_report_handler(?MODULE, {Fd,Depth}), + error_logger:add_report_handler(?MODULE, {Fd,Depth,latin1}), Fd. tty_log_close() -> @@ -393,11 +393,11 @@ dl_format_1([], [], _, Facc, Aacc) -> %%% calling error_logger_tty_h:write_event/2. %%% -init({_,_}=St) -> +init({_,_,_}=St) -> {ok,St}. -handle_event(Event, {Fd,Depth}=St) -> - case error_logger_tty_h:write_event(tag_event(Event), io_lib, Depth) of +handle_event(Event, {Fd,Depth,Enc}=St) -> + case error_logger_tty_h:write_event(tag_event(Event), io_lib, {Depth,Enc}) of ok -> ok; Str when is_list(Str) -> @@ -405,7 +405,7 @@ handle_event(Event, {Fd,Depth}=St) -> end, {ok,St}. -terminate(_Reason, {Fd,_}) -> +terminate(_Reason, {Fd,_,_}) -> ok = file:close(Fd), []. diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index c4fafe82a4..7686889360 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -552,14 +552,17 @@ t_format(_Config) -> t_format() -> error_logger:add_report_handler(?MODULE, self()), - Pid = proc_lib:spawn(fun t_format_looper/0), + Pid = proc_lib:spawn(fun '\x{aaa}t_format_looper'/0), HugeData = gb_sets:from_list(lists:seq(1, 100)), - Pid ! {die,HugeData}, + SomeData1 = list_to_atom([246]), + SomeData2 = list_to_atom([1024]), + Pid ! {SomeData1,SomeData2}, + Pid ! {die,{HugeData,SomeData1,SomeData2}}, Report = receive {crash_report, Pid, Report0} -> Report0 end, - Usz = do_test_format(Report, unlimited), - Tsz = do_test_format(Report, 20), + Usz = do_test_format(Report, latin1, unlimited), + Tsz = do_test_format(Report, latin1, 20), if Tsz >= Usz -> @@ -568,6 +571,16 @@ t_format() -> ok end, + UszU = do_test_format(Report, unicode, unlimited), + TszU = do_test_format(Report, unicode, 20), + + if + TszU >= UszU -> + ct:fail(failed); + true -> + ok + end, + ok. t_format_arbitrary(_Config) -> @@ -597,15 +610,19 @@ do_test_format(Report, Encoding, Depth) -> io:format("*** Depth = ~p, Encoding = ~p", [Depth, Encoding]), S0 = proc_lib:format(Report, Encoding, Depth), S = lists:flatten(S0), - io:put_chars(S), + case Encoding of + latin1 -> io:format("~s\n", [S]); + _ -> io:format("~ts\n", [S]) + end, length(S). -t_format_looper() -> +'\x{aaa}t_format_looper'() -> receive {die,Data} -> exit(Data); - _ -> - t_format_looper() + M -> + put(M, M), + '\x{aaa}t_format_looper'() end. %%----------------------------------------------------------------- diff --git a/lib/stdlib/test/unicode_expand.erl b/lib/stdlib/test/unicode_expand.erl new file mode 100644 index 0000000000..41f741fa84 --- /dev/null +++ b/lib/stdlib/test/unicode_expand.erl @@ -0,0 +1,36 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(unicode_expand). + +-export(['кlирилли́ческий атом'/0, 'кlирилли́ческий атом'/1, + 'кlирилли́ческий атомB'/1]). + +-export_type(['кlирилли́ческий атом'/0]). + +-type 'кlирилли́ческий атом'() :: integer(). + +'кlирилли́ческий атом'() -> + 'кlирилли́ческий атом'('кlирилли́ческий атом'). + +'кlирилли́ческий атом'(_Atom) -> + ok. + +'кlирилли́ческий атомB'(_B) -> + true. |