docb_main.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 618 行 · 第 1/2 页

ERL
618
字号
%% ``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 via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999-2000, Ericsson %% Utvecklings AB. All Rights Reserved.''%% %%     $Id$%%-module(docb_main).-export([process/2,	 parse/2, parse1/2,	 pp/2,	 insert_after/3,	 transform/5, pp/5,	 include_file/2, include/3,	 eval_str/1]).-export([do_parse_sgmls/1]).%%----------------------------------------------------------------------%% process(File, Opts) -> errors | ok%% Parses the source file File and transforms the result to html,%% latex and/or man page format.process(File, Opts) ->    case parse1(File, Opts) of	errors ->	    errors;	{ok, Tree} ->	    From = element(1, Tree),	    Tos0 =		lists:foldl(		  fun(latex, Acc) -> [latex|Acc];		     (html, Acc)  -> [html|Acc];		     ({man, _Section}, Acc) -> [man|Acc];		     (_, Acc) -> Acc		  end, [], Opts),	    %% If no target format is specified, assume HTML:	    Tos = if		      Tos0==[] -> [html];		      true -> Tos0		  end,	    lists:foreach(	      fun(To) ->		      transform(From, To, Opts, File, Tree)	      end, Tos)    end.%%----------------------------------------------------------------------%% parse(File, Opts) -> {ok, Tree} | errors%% Parses the source file File, resulting in a tree structure.parse(File, Opts) ->    case docb_util:lookup_option(src_type, Opts) of	".xml" ->	    parse_xml(File++".xml", Opts);	".sgml" ->	    parse_sgml(File, Opts)    end.%% parse1(File, Opts) -> {ok, Tree} | errors%% Like parse/2, but in the SGML case also prints the parse errors%% (in File.html.sgmls_errs) information to stdout.parse1(File, Opts) ->    parse(File, [{print_parse_errs, true}|Opts]).parse_xml(InFile, Opts) ->    DtdDir = docb_util:dtd_dir(),    ScanOpts = [{validation,true}, {fetch_path, [DtdDir]}],    PrintP = docb_util:lookup_option(print_parse_errs, Opts),    case catch xmerl_scan:file(InFile, ScanOpts) of	{'EXIT', Error} when PrintP ->	    docb_util:message(error,			      "XML validation error:~n~p", [Error]),	    errors;	{'EXIT', _Error} ->	    errors;	{error, Reason} -> % probably file error	    docb_util:message(error, "XML scan error: ~p", [Reason]),	    errors;	{Doc, []} ->	    case catch xmerl:export([Doc], docb_xmerl_tree_cb) of		[Tree] ->		    verify(Tree),		    {ok, Tree};		{'EXIT', Error} ->		    docb_util:message(error,				      "XML export error:~n~p", [Error]),		    errors	    end    end.parse_sgml(InFile, Opts) ->    Pfx = tmp_file_prefix(InFile, Opts),    OutFile = Pfx ++ "sgmls_output",    ErrFile = Pfx ++ "sgmls_errs",    EntVals = lists:usort(docb_util:lookup_options(ent, Opts)),    Ents = lists:flatten([" -ent " ++ Val || Val <- EntVals]),    Cmd = docb_util:old_docb_dir() ++ "/bin/docb_sgmls_run " ++	Ents ++ " " ++ InFile ++ ".sgml " ++ OutFile ++ " " ++ ErrFile,    case os:cmd(Cmd) of	[] ->	    PrintP = docb_util:lookup_option(print_parse_errs, Opts),	    case filelib:file_size(ErrFile) of		0 -> % implies no errors		    parse_sgmls(InFile, OutFile);		_ when PrintP ->		    cat(ErrFile),		    errors;		_ ->		    errors	    end;	Msg ->	    docb_util:message(error, "~p", [Msg]),	    errors    end.tmp_file_prefix(File, Opts) ->    lists:concat(      [File, "." | lists:foldl(		     fun(latex, Acc) -> ["latex."|Acc];			(html, Acc)  -> ["html."|Acc];			({man, Section}, Acc) -> ["man", Section, "."|Acc];			(_, Acc) -> Acc		     end, [], Opts)]).parse_sgmls(InFile, SgmlsFile) ->    case file:open(SgmlsFile, read) of	{ok, Fd} ->	    Res = case (catch do_parse_sgmls(Fd)) of		      {ok, Tree} ->			  {ok, Tree};		      {'EXIT', Reason} ->			  docb_util:message(			    error,			    "Cannot parse sgmls output file "			    "~s, obtained from parsing ~s, "			    "reason: ~w",			    [SgmlsFile, InFile, Reason]),			  errors;		      {error, Reason} ->			  docb_util:message(			    error,			    "Cannot parse sgmls output file "			    "~s, obtained from parsing ~s, "			    "reason: ~w",			    [SgmlsFile, InFile, Reason]),			  errors		  end,	    file:close(Fd),	    case Res of		{ok, Tree0} ->		    verify(Tree0),		    {ok, Tree0};		_Other ->		    errors	    end;	{error, Reason} ->	    docb_util:message(error,			      "Cannot open sgmls output file ~s, "			      "obtained from parsing ~s, reason: ~w",			      [SgmlsFile, InFile, Reason]),	    errors    end.do_parse_sgmls(Fd) ->    do_parse_sgmls(Fd, []).do_parse_sgmls(Fd, Attrs) ->    case get_line(Fd) of	{attrs, A} ->	    do_parse_sgmls(Fd, [A|Attrs]);	{startTag, Tag} ->	    {ok, {Tag, Attrs, get_args(Fd)}};	Other ->	    {error, Other}    end.get_args(Fd) ->    case get_line(Fd) of	{startTag, Tag} ->	    H = {Tag, [], get_args(Fd)},	    [H|get_args(Fd)];	{dataTag, Str} ->	    [{pcdata, [], Str}|get_args(Fd)];	{attrs, A} ->	    get_args_attr(Fd, [A]);	close ->	    [];	ok ->	    []    end.get_args_attr(Fd, Attrs) ->    case get_line(Fd) of	{startTag, Tag} ->	    H = {Tag, lists:reverse(Attrs), get_args(Fd)},	    [H|get_args(Fd)];	{dataTag, Str} ->	    [{pcdata, lists:reverse(Attrs), Str}|get_args(Fd)];	{attrs, A} ->	    get_args_attr(Fd, [A|Attrs]);	close ->	    [];	ok ->	    []    end.get_line(Fd) ->    Str = io:get_line(Fd, ''),    case Str of	[$(|T] ->	    {startTag, tag_name(T)};	[$-|T] ->	    {dataTag, T};	[$)|_T] ->	    close;	[$A|T] ->	    {attrs, attrs(remove_nl(T))};	[$?|_T] ->	    get_line(Fd);	[$C|_] ->	    ok    end.remove_nl([$\n|_]) -> [];remove_nl([H|T])    -> [H|remove_nl(T)];remove_nl([])       -> [].%% attrs%% splits a string like%% AAAAA BBBBB ......%% into {"AAA", "BBB", Rest}attrs(T) ->    {X, T1} = get_item(T),    {Y, T2} = get_item(T1),    T3 = skip_blanks(T2),    {X, Y, T3}.get_item(T) -> get_item(skip_blanks(T), []).get_item([$ |T], L) -> {lists:reverse(L), [$ |T]};get_item([H|T], L)  -> get_item(T, [H|L]);get_item([], L)     -> {lists:reverse(L), []}.skip_blanks([$ |T]) -> skip_blanks(T);skip_blanks(T)      -> T.tag_name(Str) -> tag_name(Str, []).tag_name([H|T], L) when $A =< H, H =< $Z ->    tag_name(T, [H-$A+$a|L]);tag_name([$\n], L) ->    list_to_atom(lists:reverse(L));tag_name([H|T], L) ->    tag_name(T, [H|L]).cat(File) ->    case file:open(File, read) of	{ok, Fd} ->	    cat1(Fd),	    file:close(Fd);	Other ->	    Other    end.cat1(Fd) ->    case io:get_line(Fd, '') of	eof ->	    eof;	Str ->	    io:format("~s", [Str]),	    cat1(Fd)    end.%%----------------------------------------------------------------------verify(Tree) -> verify(Tree, [], 1).verify({pcdata, Optional, _}, Path, Level) ->    verify_optional(Optional, Path, Level);verify({Tag, Optional, Args}, Path, Level) when is_list(Args) ->    case verify_optional(Optional, Path, Level) of	true ->	    verify_list(Args, [Tag|Path], Level);	false ->	    false    end;verify(Other, Path, Level) ->    verify_error(Other, Path, Level).verify_error(X, Path, Level) ->    docb_util:message(error, "Invalid object found at: ~p level:~w~n~s",		      [Path, Level, docb_pretty_format:term(X)]),

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?