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 + -
显示快捷键?