diff options
Diffstat (limited to 'lib/percept/src')
-rw-r--r-- | lib/percept/src/egd.erl | 38 | ||||
-rw-r--r-- | lib/percept/src/egd.hrl | 16 | ||||
-rw-r--r-- | lib/percept/src/egd_render.erl | 22 | ||||
-rw-r--r-- | lib/percept/src/percept.erl | 56 | ||||
-rw-r--r-- | lib/percept/src/percept.hrl | 21 | ||||
-rw-r--r-- | lib/percept/src/percept_db.erl | 31 | ||||
-rw-r--r-- | lib/percept/src/percept_html.erl | 52 |
7 files changed, 108 insertions, 128 deletions
diff --git a/lib/percept/src/egd.erl b/lib/percept/src/egd.erl index 7972fde597..4fb5b6c46a 100644 --- a/lib/percept/src/egd.erl +++ b/lib/percept/src/egd.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -46,10 +46,10 @@ %% @type color() %% @type render_option() = {render_engine, opaque} | {render_engine, alpha} --type(egd_image() :: pid()). --type(point() :: {non_neg_integer(), non_neg_integer()}). --type(render_option() :: {'render_engine', 'opaque'} | {'render_engine', 'alpha'}). --type(color() :: {float(), float(), float(), float()}). +-type egd_image() :: pid(). +-type point() :: {non_neg_integer(), non_neg_integer()}. +-type render_option() :: {'render_engine', 'opaque'} | {'render_engine', 'alpha'}. +-type color() :: {float(), float(), float(), float()}. %%========================================================================== %% @@ -60,7 +60,7 @@ %% @spec create(integer(), integer()) -> egd_image() %% @doc Creates an image area and returns its reference. --spec(create/2 :: (Width :: integer(), Height :: integer()) -> egd_image()). +-spec create(Width :: integer(), Height :: integer()) -> egd_image(). create(Width,Height) -> spawn_link(fun() -> init(trunc(Width),trunc(Height)) end). @@ -69,16 +69,17 @@ create(Width,Height) -> %% @spec destroy(egd_image()) -> ok %% @doc Destroys the image. --spec(destroy/1 :: (Image :: egd_image()) -> ok). +-spec destroy(Image :: egd_image()) -> ok. destroy(Image) -> cast(Image, destroy), ok. -%% @spec render(egd_image()) -> binary() +%% @spec render(egd_image()) -> binary() %% @equiv render(Image, png, [{render_engine, opaque}]) +-spec render(Image :: egd_image()) -> binary(). render(Image) -> render(Image, png, [{render_engine, opaque}]). @@ -94,10 +95,10 @@ render(Image, Type) -> %% binary can either be a raw bitmap with rgb tripplets or a binary in png %% format. --spec(render/3 :: ( +-spec render( Image :: egd_image(), Type :: 'png' | 'raw_bitmap' | 'eps', - Options :: [render_option()]) -> binary()). + Options :: [render_option()]) -> binary(). render(Image, Type, Options) -> {render_engine, RenderType} = proplists:lookup(render_engine, Options), @@ -116,11 +117,11 @@ information(Pid) -> %% @spec line(egd_image(), point(), point(), color()) -> ok %% @doc Creates a line object from P1 to P2 in the image. --spec(line/4 :: ( +-spec line( Image :: egd_image(), P1 :: point(), P2 :: point(), - Color :: color()) -> 'ok'). + Color :: color()) -> 'ok'. line(Image, P1, P2, Color) -> cast(Image, {line, P1, P2, Color}), @@ -132,9 +133,8 @@ line(Image, P1, P2, Color) -> %% Name = black | silver | gray | white | maroon | red | purple | fuchia | green | lime | olive | yellow | navy | blue | teal | aqua %% @doc Creates a color reference. --spec(color/1 :: ( - Value :: {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} | atom()) -> - color()). +-spec color(Value :: {byte(), byte(), byte()} | {byte(), byte(), byte(), byte()} | atom()) -> + color(). color(Color) -> egd_primitives:color(Color). diff --git a/lib/percept/src/egd.hrl b/lib/percept/src/egd.hrl index 274986db65..2e8f5ebc50 100644 --- a/lib/percept/src/egd.hrl +++ b/lib/percept/src/egd.hrl @@ -1,24 +1,24 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% --type(rgba_float() :: {float(), float(), float(), float()}). --type(rgba_byte() :: {byte(), byte(), byte(), byte()}). --type(rgb() :: {byte(), byte(), byte()}). +-type rgba_float() :: {float(), float(), float(), float()}. +-type rgba_byte() :: {byte(), byte(), byte(), byte()}. +-type rgb() :: {byte(), byte(), byte()}. -record(image_object, { type, diff --git a/lib/percept/src/egd_render.erl b/lib/percept/src/egd_render.erl index 4a0247dd33..7fd1072ab1 100644 --- a/lib/percept/src/egd_render.erl +++ b/lib/percept/src/egd_render.erl @@ -29,7 +29,8 @@ -include("egd.hrl"). -define('DummyC',0). -binary(Image) -> binary(Image, opaque). +binary(Image) -> + binary(Image, opaque). binary(Image, Type) -> parallel_binary(precompile(Image),Type). @@ -42,9 +43,8 @@ parallel_binary(Image = #image{ height = Height },Type) -> W = Image#image.width, Bg = Image#image.background, Os = Image#image.objects, - erlang:list_to_binary(lists:map(fun - (Y) -> scanline(Y, Os, {0,0,W - 1, Bg}, Type) - end, lists:seq(1, Height))); + erlang:list_to_binary([scanline(Y, Os, {0,0,W - 1, Bg}, Type) + || Y <- lists:seq(1, Height)]); Np -> Pids = start_workers(Np, Type), Handler = handle_workers(Height, Pids), @@ -54,7 +54,9 @@ parallel_binary(Image = #image{ height = Height },Type) -> Res end. -start_workers(Np, Type) -> start_workers(Np, Type, []). +start_workers(Np, Type) -> + start_workers(Np, Type, []). + start_workers( 0, _, Pids) -> Pids; start_workers(Np, Type, Pids) when Np > 0 -> start_workers(Np - 1, Type, [spawn_link(fun() -> worker(Type) end)|Pids]). @@ -90,7 +92,9 @@ init_workers(Image, Handler, [Pid|Pids]) -> Handler ! {Pid, scan_complete}, init_workers(Image, Handler, Pids). -handle_workers(H, Pids) -> spawn_link(fun() -> handle_workers(H, H, length(Pids)) end). +handle_workers(H, Pids) -> + spawn_link(fun() -> handle_workers(H, H, length(Pids)) end). + handle_workers(_, 0, _) -> ok; handle_workers(H, Hi, Np) when H > 0 -> N = trunc(Hi/(2*Np)), @@ -110,7 +114,9 @@ finish_workers([Pid|Pids]) -> Pid ! {self(), done}, finish_workers(Pids). -receive_binaries(H) -> receive_binaries(H, []). +receive_binaries(H) -> + receive_binaries(H, []). + receive_binaries(0, Bins) -> erlang:list_to_binary(Bins); receive_binaries(H, Bins) when H > 0 -> receive @@ -118,7 +124,6 @@ receive_binaries(H, Bins) when H > 0 -> receive_binaries(H - 1, [Bin|Bins]) end. - scanline(Y, Os, {_,_,Width,_}=LSB, Type) -> OLSs = parse_objects_on_line(Y-1, Width, Os), RLSs = resulting_line_spans([LSB|OLSs],Type), @@ -190,7 +195,6 @@ modify_layers(Layers,[{{_,Z,start},C}|Trans]) -> modify_layers(Layers,[{{_,Z,stop },C}|Trans]) -> modify_layers(remove_layer(Layers, Z, C), Trans). - add_layer([{Z1,_}=H|Layers],Z,C) when Z1 > Z -> [H|add_layer(Layers,Z,C)]; add_layer(Layers,Z,C) -> diff --git a/lib/percept/src/percept.erl b/lib/percept/src/percept.erl index af1a920efd..f5e0f7e469 100644 --- a/lib/percept/src/percept.erl +++ b/lib/percept/src/percept.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -50,7 +50,7 @@ %% @type percept_option() = procs | ports | exclusive --type(percept_option() :: 'procs' | 'ports' | 'exclusive' | 'scheduler'). +-type percept_option() :: 'procs' | 'ports' | 'exclusive' | 'scheduler'. %%========================================================================== %% @@ -85,8 +85,8 @@ stop(_State) -> %% profiling --spec(profile/1 :: (Filename :: string()) -> - {'ok', port()} | {'already_started', port()}). +-spec profile(Filename :: file:filename()) -> + {'ok', port()} | {'already_started', port()}. profile(Filename) -> percept_profile:start(Filename, [procs]). @@ -94,10 +94,9 @@ profile(Filename) -> %% @spec profile(Filename::string(), [percept_option()]) -> {ok, Port} | {already_started, Port} %% @see percept_profile --spec(profile/2 :: ( - Filename :: string(), - Options :: [percept_option()]) -> - {'ok', port()} | {'already_started', port()}). +-spec profile(Filename :: file:filename(), + Options :: [percept_option()]) -> + {'ok', port()} | {'already_started', port()}. profile(Filename, Options) -> percept_profile:start(Filename, Options). @@ -105,16 +104,15 @@ profile(Filename, Options) -> %% @spec profile(Filename::string(), MFA::mfa(), [percept_option()]) -> ok | {already_started, Port} | {error, not_started} %% @see percept_profile --spec(profile/3 :: ( - Filename :: string(), - Entry :: {atom(), atom(), list()}, - Options :: [percept_option()]) -> - 'ok' | {'already_started', port()} | {'error', 'not_started'}). +-spec profile(Filename :: file:filename(), + Entry :: {atom(), atom(), list()}, + Options :: [percept_option()]) -> + 'ok' | {'already_started', port()} | {'error', 'not_started'}. profile(Filename, MFA, Options) -> percept_profile:start(Filename, MFA, Options). --spec(stop_profile/0 :: () -> 'ok' | {'error', 'not_started'}). +-spec stop_profile() -> 'ok' | {'error', 'not_started'}. %% @spec stop_profile() -> ok | {'error', 'not_started'} %% @see percept_profile @@ -125,8 +123,8 @@ stop_profile() -> %% @spec analyze(string()) -> ok | {error, Reason} %% @doc Analyze file. --spec(analyze/1 :: (Filename :: string()) -> - 'ok' | {'error', any()}). +-spec analyze(Filename :: file:filename()) -> + 'ok' | {'error', any()}. analyze(Filename) -> case percept_db:start() of @@ -142,9 +140,8 @@ analyze(Filename) -> %% Reason = term() %% @doc Starts webserver. --spec(start_webserver/0 :: () -> - {'started', string(), pos_integer()} | - {'error', any()}). +-spec start_webserver() -> + {'started', string(), pos_integer()} | {'error', any()}. start_webserver() -> start_webserver(0). @@ -156,9 +153,8 @@ start_webserver() -> %% @doc Starts webserver. If port number is 0, an available port number will %% be assigned by inets. --spec(start_webserver/1 :: (Port :: non_neg_integer()) -> - {'started', string(), pos_integer()} | - {'error', any()}). +-spec start_webserver(Port :: non_neg_integer()) -> + {'started', string(), pos_integer()} | {'error', any()}. start_webserver(Port) when is_integer(Port) -> application:load(percept), @@ -255,20 +251,20 @@ trace_parser(Trace, {Count, Pid}) -> find_service_pid_from_port([], _) -> undefined; find_service_pid_from_port([{_, Pid, Options} | Services], Port) -> - case lists:keysearch(port, 1, Options) of + case lists:keyfind(port, 1, Options) of false -> find_service_pid_from_port(Services, Port); - {value, {port, Port}} -> + {port, Port} -> Pid end. find_service_port_from_pid([], _) -> undefined; find_service_port_from_pid([{_, Pid, Options} | _], Pid) -> - case lists:keysearch(port, 1, Options) of + case lists:keyfind(port, 1, Options) of false -> undefined; - {value, {port, Port}} -> + {port, Port} -> Port end; find_service_port_from_pid([{_, _, _} | Services], Pid) -> diff --git a/lib/percept/src/percept.hrl b/lib/percept/src/percept.hrl index a9afceb6d1..36b6f63a4d 100644 --- a/lib/percept/src/percept.hrl +++ b/lib/percept/src/percept.hrl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -23,10 +23,10 @@ %%% Type definitions %%% %%% ------------------- %%% --type(timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}). --type(true_mfa() :: {atom(), atom(), byte() | list()}). --type(state() :: 'active' | 'inactive'). --type(scheduler_id() :: {'scheduler_id', non_neg_integer()}). +-type timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}. +-type true_mfa() :: {atom(), atom(), byte() | list()}. +-type state() :: 'active' | 'inactive'. +-type scheduler_id() :: {'scheduler_id', non_neg_integer()}. %%% ------------------- %%% %%% Records %%% @@ -40,8 +40,7 @@ runnable_count = 0 %:: non_neg_integer() }). --record( - information, { +-record(information, { id ,%:: pid() | port(), name = undefined ,%:: atom() | string() | 'undefined', entry = undefined ,%:: true_mfa() | 'undefined', diff --git a/lib/percept/src/percept_db.erl b/lib/percept/src/percept_db.erl index dc85fa3510..edb0d79a29 100644 --- a/lib/percept/src/percept_db.erl +++ b/lib/percept/src/percept_db.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -72,7 +72,7 @@ %% Pid = pid() %% @doc Starts or restarts the percept database. --spec(start/0 :: () -> {'started', pid()} | {'restarted', pid()}). +-spec start() -> {'started', pid()} | {'restarted', pid()}. start() -> case erlang:whereis(percept_db) of @@ -92,7 +92,7 @@ start() -> %% Pid = pid() %% @doc Stops the percept database. --spec(stop/0 :: () -> 'not_started' | {'stopped', pid()}). +-spec stop() -> 'not_started' | {'stopped', pid()}. stop() -> case erlang:whereis(percept_db) of @@ -392,23 +392,14 @@ consolidate_runnability_loop(Key) -> consolidate_runnability_loop(ets:next(pdb_activity, Key)). list_all_ts() -> - ATs = [ Act#activity.timestamp || - Act <- select_query({activity, []})], - STs = [ Act#activity.timestamp || - Act <- select_query({scheduler, []})], + ATs = [Act#activity.timestamp || Act <- select_query({activity, []})], + STs = [Act#activity.timestamp || Act <- select_query({scheduler, []})], ITs = lists:flatten([ [I#information.start, I#information.stop] || I <- select_query({information, all})]), - % Filter out all undefined (non ts) - TsList = lists:filter( - fun(Element) -> - case Element of - {_,_,_} -> true; - _ -> false - end - end, ATs ++ STs ++ ITs), - TsList. + %% Filter out all undefined (non ts) + [Elem || Elem = {_,_,_} <- ATs ++ STs ++ ITs]. %% get_runnable_count(Type, State) -> RunnableCount %% In: diff --git a/lib/percept/src/percept_html.erl b/lib/percept/src/percept_html.erl index ffce7a98fa..7e0ea45783 100644 --- a/lib/percept/src/percept_html.erl +++ b/lib/percept/src/percept_html.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% -module(percept_html). @@ -172,12 +172,12 @@ div_tag_graph() -> width:40px; height:40px;\"></div></div>". --spec(url_graph/5 :: ( +-spec url_graph( Widht :: non_neg_integer(), Height :: non_neg_integer(), Min :: float(), Max :: float(), - Pids :: [pid()]) -> string()). + Pids :: [pid()]) -> string(). url_graph(W, H, Min, Max, []) -> "/cgi-bin/percept_graph/graph?range_min=" ++ term2html(float(Min)) @@ -508,10 +508,7 @@ cl_deltas([A,B|Ls], Out) -> cl_deltas([B|Ls], [B - A | Out]). join_strings(Strings) -> lists:flatten(Strings). --spec(join_strings_with/2 :: ( - Strings :: [string()], - Separator :: string()) -> - string()). +-spec join_strings_with(Strings :: [string()], Separator :: string()) -> string(). join_strings_with([S1, S2 | R], S) -> join_strings_with([join_strings_with(S1,S2,S) | R], S); @@ -522,7 +519,7 @@ join_strings_with(S1, S2, S) -> %%% Generic erlang2html --spec(html_table/1 :: (Rows :: [[string() | {'td' | 'th', string()}]]) -> string()). +-spec html_table(Rows :: [[string() | {'td' | 'th', string()}]]) -> string(). html_table(Rows) -> "<table>" ++ html_table_row(Rows) ++ "</table>". @@ -539,7 +536,7 @@ html_table_data([Data|Row]) -> "<td>" ++ Data ++ "</td>" ++ html_table_dat --spec(table_line/1 :: (Table :: [any()]) -> string()). +-spec table_line(Table :: [any()]) -> string(). table_line(List) -> table_line(List, ["<tr>"]). table_line([], Out) -> lists:flatten(lists:reverse(["</tr>\n"|Out])); @@ -548,16 +545,12 @@ table_line([Element | Elements], Out) when is_list(Element) -> table_line([Element | Elements], Out) -> table_line(Elements, ["<td>" ++ term2html(Element) ++ "</td>"|Out]). --spec(term2html/1 :: (any()) -> string()). +-spec term2html(any()) -> string(). term2html(Term) when is_float(Term) -> lists:flatten(io_lib:format("~.4f", [Term])); term2html(Term) -> lists:flatten(io_lib:format("~p", [Term])). --spec(mfa2html/1 :: (MFA :: { - atom(), - atom(), - list() | integer()}) -> - string()). +-spec mfa2html(MFA :: {atom(), atom(), list() | integer()}) -> string(). mfa2html({Module, Function, Arguments}) when is_list(Arguments) -> lists:flatten(io_lib:format("~p:~p/~p", [Module, Function, length(Arguments)])); @@ -566,7 +559,7 @@ mfa2html({Module, Function, Arity}) when is_integer(Arity) -> mfa2html(_) -> "undefined". --spec(pid2html/1 :: (Pid :: pid() | port()) -> string()). +-spec pid2html(Pid :: pid() | port()) -> string(). pid2html(Pid) when is_pid(Pid) -> PidString = term2html(Pid), @@ -577,14 +570,14 @@ pid2html(Pid) when is_port(Pid) -> pid2html(_) -> "undefined". --spec(image_string/1 :: (Request :: string()) -> string()). +-spec image_string(Request :: string()) -> string(). image_string(Request) -> "<img border=0 src=\"/cgi-bin/percept_graph/" ++ Request ++ " \">". --spec(image_string/2 :: (atom() | string(), list()) -> string()). +-spec image_string(atom() | string(), list()) -> string(). image_string(Request, Options) when is_atom(Request), is_list(Options) -> image_string(image_string_head(erlang:atom_to_list(Request), Options, [])); @@ -610,13 +603,13 @@ image_string_tail(Request, [{Type, Value} | Opts], Out) -> %%% percept conversions --spec(pid2value/1 :: (Pid :: pid()) -> string()). +-spec pid2value(Pid :: pid()) -> string(). pid2value(Pid) -> String = lists:flatten(io_lib:format("~p", [Pid])), lists:sublist(String, 2, erlang:length(String)-2). --spec(value2pid/1 :: (Value :: string()) -> pid()). +-spec value2pid(Value :: string()) -> pid(). value2pid(Value) -> String = lists:flatten("<" ++ Value ++ ">"), @@ -625,10 +618,8 @@ value2pid(Value) -> %%% get value --spec(get_option_value/2 :: ( - Option :: string(), - Options :: [{string(),any()}]) -> - {'error', any()} | bool() | pid() | [pid()] | number()). +-spec get_option_value(Option :: string(), Options :: [{string(),any()}]) -> + {'error', any()} | boolean() | pid() | [pid()] | number(). get_option_value(Option, Options) -> case catch get_option_value0(Option, Options) of @@ -662,8 +653,7 @@ get_default_option_value(Option) -> _ -> {error, {undefined_default_option, Option}} end. --spec(get_number_value/1 :: (Value :: string()) -> - number() | {'error', 'illegal_number'}). +-spec get_number_value(string()) -> number() | {'error', 'illegal_number'}. get_number_value(Value) -> % Try float @@ -710,7 +700,7 @@ menu() -> <li><a href=/cgi-bin/percept_html/page>overview</a></li> </ul></div>\n". --spec(error_msg/1 :: (Error :: string()) -> string()). +-spec error_msg(Error :: string()) -> string(). error_msg(Error) -> "<table width=300> |