Shock horror

Ulf Wiger <>
Mon Apr 29 13:26:22 CEST 2002

On Mon, 29 Apr 2002, Joe Armstrong wrote:

>On Mon, 29 Apr 2002, Thomas Arts wrote:

>> Thus, the concern are the nollitons and singletons not in the
>> manual pages, they are the really uglies... You are not going
>> to tell me that you checked all manual entires for the 8148
>> functions, did you?
>  No - whould that I could - that would require a tighter
>integration of the documentaion and code than is used today.
>Hopefully this will be improved in "son of Erlang".

Some analysis can be made, through some rather perverted
processing of the on-line documentation. I included some support
in CCviewer for that, as I implemented a function to lookup all
external calls to exported functions in a lib. I thought it might
be useful to indicate if a called function was undocumented.

My approach was to scan the HTML for e.g <A NAME="activity%2">
(which BTW doesn't exist in mnesia.html, even though
mnesia:activity/2 is a documented exported function). The
documentation is not quite consistent to this level of detail,
but most of the time, it produces the expected results.

The decidedly cludgey code is presented below, if you want to
reuse it.


process_body(Str, Mod, Tab) ->
    process_body(Str, Mod, Tab, false).

process_body("<A NAME=\"" ++ T, Mod, Tab, Flag) ->
    case scan_name(T) of
        {Name, NameStr, Arity, Rest} ->
            case Rest of
                "><STRONG><CODE>" ++ T1 ->
                    case lists:prefix(NameStr ++ "(", T1) of
                        true ->
                            ets:insert(Tab, {{Mod,
                            process_body(T1, Mod, Tab, true);
                        false ->
                            ?dbg("~p (~p) not a prefix of ~p~n",
                                  lists:sublist(T1, 1, 10)]),
                            process_body(T1, Mod, Tab, Flag)
                _ ->
                    ?dbg("Rest (~p) was ~p~n",
                         [Mod, lists:sublist(Rest, 1, 10)]),
                    process_body(Rest, Mod, Tab, Flag)
        {false, Rest} ->
            process_body(Rest, Mod, Tab, Flag)
process_body([H|T], Mod, Tab, Flag) ->
    process_body(T, Mod, Tab, Flag);
process_body([], Mod, Tab, Flag) ->

scan_name("erlang:" ++ [H|T]) when H>=$a, H=<$z ->
    %% Some BIFs are not auto-exported
    scan_name(T, [H], [H|":gnalre"]);
scan_name([H|T]) when H>=$a, H=<$z ->
    scan_name(T, [H], [H]);
scan_name("'" ++ T) ->
    scan_name(T, [$'], ";sopa&");
scan_name("'" ++ T) ->
    scan_name(T, [$'], ";93#&");
scan_name("Module:" ++ T) ->
    %% This is a definition of a behaviour callback function --
    {false, T};
scan_name(Other) ->
    {false, Other}.

scan_name([$"|T], Acc, StrAcc) ->
    {false, T};
scan_name("'%" ++ [H|T], Acc, StrAcc) when H>=$0, H=<$9 ->
    Name = lists:reverse([$'|Acc]),
    NameStr = lists:reverse(";sopa&" ++ Acc),
    scan_arity(T, Name, NameStr, [H]);
scan_name("'%" ++ [H|T], Acc, StrAcc) when H>=$0, H=<$9 ->
    case lists:reverse([$'|Acc]) of
        Name = [$'|_] ->
            NameStr = lists:reverse(";93#&" ++ Acc),
            scan_arity(T, Name, NameStr, [H]);
        _ ->
            {false, T}
scan_name("%" ++ [H|T], Acc, StrAcc) when H>=$0, H=<$9 ->
    Name = lists:reverse(Acc),
    NameStr = lists:reverse(StrAcc),
    scan_arity(T, Name, NameStr, [H]);
scan_name([H|T], Acc, StrAcc) ->
    scan_name(T, [H|Acc], [H|StrAcc]);
scan_name([], Acc, StrAcc) ->
    {false, []}.

scan_arity([H|T], Name, NameStr, Acc) when H>=$0, H=<$9 ->
    scan_arity(T, Name, NameStr, [H|Acc]);
scan_arity([$"|T], Name, NameStr, Acc) ->
    {Name, NameStr, list_to_integer(Acc), T};
scan_arity([], Name, NameStr, Acc) ->
    {false, []}.

Ulf Wiger, Senior Specialist,
   / / /   Architecture & Design of Carrier-Class Software
  / / /    Strategic Product & System Management
 / / /     Ericsson Telecom AB, ATM Multiservice Networks

More information about the erlang-questions mailing list