%% ===================================================================== %% This library is free software; you can redistribute it and/or modify %% it under the terms of the GNU Lesser General Public License as %% published by the Free Software Foundation; either version 2 of the %% License, or (at your option) any later version. %% %% This library is distributed in the hope that it will be useful, but %% WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %% Lesser General Public License for more details. %% %% You should have received a copy of the GNU Lesser General Public %% License along with this library; if not, write to the Free Software %% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 %% USA %% %% @copyright 2003 Richard Carlsson %% @author Richard Carlsson %% @see edoc %% @end %% ===================================================================== %% @doc Interface for calling EDoc from Erlang startup options. %% %% The following is an example of typical usage in a Makefile: %% ```docs: %% erl -noshell -run edoc_run application "'$(APP_NAME)'" \ %% '"."' '[{def,{vsn,"$(VSN)"}}]' %% ''' %% (note the single-quotes to avoid shell expansion, and the %% double-quotes enclosing the strings). %% %% New feature in version 0.6.9: It is no longer %% necessary to write `-s init stop' last on the command line in order %% to make the execution terminate. The termination (signalling success %% or failure to the operating system) is now built into these %% functions. -module(edoc_run). -export([file/1, application/1, files/1, toc/1]). -compile({no_auto_import,[error/1]}). -import(edoc_report, [report/2, error/1]). -type args() :: [string()]. %% @spec application([string()]) -> none() %% %% @doc Calls {@link edoc:application/3} with the corresponding %% arguments. The strings in the list are parsed as Erlang constant %% terms. The list can be either `[App]', `[App, Options]' or `[App, %% Dir, Options]'. In the first case {@link edoc:application/1} is %% called instead; in the second case, {@link edoc:application/2} is %% called. %% %% The function call never returns; instead, the emulator is %% automatically terminated when the call has completed, signalling %% success or failure to the operating system. -spec application(args()) -> no_return(). application(Args) -> F = fun () -> case parse_args(Args) of [App] -> edoc:application(App); [App, Opts] -> edoc:application(App, Opts); [App, Dir, Opts] -> edoc:application(App, Dir, Opts); _ -> invalid_args("edoc_run:application/1", Args) end end, run(F). %% @spec files([string()]) -> none() %% %% @doc Calls {@link edoc:files/2} with the corresponding arguments. The %% strings in the list are parsed as Erlang constant terms. The list can %% be either `[Files]' or `[Files, Options]'. In the first case, {@link %% edoc:files/1} is called instead. %% %% The function call never returns; instead, the emulator is %% automatically terminated when the call has completed, signalling %% success or failure to the operating system. -spec files(args()) -> no_return(). files(Args) -> F = fun () -> case parse_args(Args) of [Files] -> edoc:files(Files); [Files, Opts] -> edoc:files(Files, Opts); _ -> invalid_args("edoc_run:files/1", Args) end end, run(F). %% @hidden Not official yet -spec toc(args()) -> no_return(). toc(Args) -> F = fun () -> case parse_args(Args) of [Dir, Paths] -> edoc:toc(Dir,Paths); [Dir, Paths, Opts] -> edoc:toc(Dir,Paths,Opts); _ -> invalid_args("edoc_run:toc/1", Args) end end, run(F). %% @spec file([string()]) -> none() %% %% @deprecated This is part of the old interface to EDoc and is mainly %% kept for backwards compatibility. The preferred way of generating %% documentation is through one of the functions {@link application/1} %% and {@link files/1}. %% %% @doc Calls {@link edoc:file/2} with the corresponding arguments. The %% strings in the list are parsed as Erlang constant terms. The list can %% be either `[File]' or `[File, Options]'. In the first case, an empty %% list of options is passed to {@link edoc:file/2}. %% %% The following is an example of typical usage in a Makefile: %% ```$(DOCDIR)/%.html:%.erl %% erl -noshell -run edoc_run file '"$<"' '[{dir,"$(DOCDIR)"}]' \ %% -s init stop''' %% %% The function call never returns; instead, the emulator is %% automatically terminated when the call has completed, signalling %% success or failure to the operating system. -spec file(args()) -> no_return(). file(Args) -> F = fun () -> case parse_args(Args) of [File] -> edoc:file(File, []); [File, Opts] -> edoc:file(File, Opts); _ -> invalid_args("edoc_run:file/1", Args) end end, run(F). -spec invalid_args(string(), args()) -> no_return(). invalid_args(Where, Args) -> report("invalid arguments to ~ts: ~w.", [Where, Args]), shutdown_error(). run(F) -> wait_init(), case catch {ok, F()} of {ok, _} -> shutdown_ok(); {'EXIT', E} -> report("edoc terminated abnormally: ~P.", [E, 10]), shutdown_error(); Thrown -> report("internal error: throw without catch in edoc: ~P.", [Thrown, 15]), shutdown_error() end. wait_init() -> case erlang:whereis(code_server) of undefined -> erlang:yield(), wait_init(); _ -> ok end. %% When and if a function init:stop/1 becomes generally available, we %% can use that instead of delay-and-pray when there is an error. -spec shutdown_ok() -> no_return(). shutdown_ok() -> %% shut down emulator nicely, signalling "normal termination" init:stop(). -spec shutdown_error() -> no_return(). shutdown_error() -> %% delay 1 second to allow I/O to finish receive after 1000 -> ok end, %% stop emulator the hard way with a nonzero exit value halt(1). parse_args([A | As]) when is_atom(A) -> [parse_arg(atom_to_list(A)) | parse_args(As)]; parse_args([A | As]) -> [parse_arg(A) | parse_args(As)]; parse_args([]) -> []. parse_arg(A) -> case catch {ok, edoc_lib:parse_expr(A, 1)} of {ok, Expr} -> case catch erl_parse:normalise(Expr) of {'EXIT', _} -> report("bad argument: '~ts':", [A]), exit(error); Term -> Term end; {error, _, D} -> report("error parsing argument '~ts'", [A]), error(D), exit(error) end.