diff options
Diffstat (limited to 'lib/test_server/src/erl2html2.erl')
-rw-r--r-- | lib/test_server/src/erl2html2.erl | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl new file mode 100644 index 0000000000..c94d4627f9 --- /dev/null +++ b/lib/test_server/src/erl2html2.erl @@ -0,0 +1,182 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. 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% +%% + +%%%------------------------------------------------------------------ +%%% Purpose:Convert Erlang files to html. (Pretty faaast... :-) +%%%------------------------------------------------------------------ + +%-------------------------------------------------------------------- +% Some stats (Sparc5@110Mhz): +% 4109 lines (erl_parse.erl): 3.00 secs +% 1847 lines (application_controller.erl): 0.57 secs +% 3160 lines (test_server.erl): 1.00 secs +% 1199 lines (ts_estone.erl): 0.35 secs +% +% Avg: ~4.5e-4s/line, or ~0.45s/1000 lines, or ~2200 lines/sec. +%-------------------------------------------------------------------- + +-module(erl2html2). +-export([convert/2]). + +convert([], _Dest) -> % Fake clause. + ok; +convert(File, Dest) -> + case file:read_file(File) of + {ok, Bin} -> + Code=binary_to_list(Bin), + statistics(runtime), + %% The generated code uses the BGCOLOR attribute in the + %% BODY tag, which wasn't valid until HTML 3.2. Also, + %% good HTML should either override all colour attributes + %% or none of them -- *never* just a few. + %% + %% FIXME: The colours should *really* be set with + %% stylesheets... + Html0 + = ["<!DOCTYPE HTML PUBLIC " + "\"-//W3C//DTD HTML 3.2 Final//EN\">\n" + "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n" + "<html>\n" + "<head><title>", File, "</title></head>\n\n" + "<body bgcolor=\"white\" text=\"black\"" + " link=\"blue\" vlink=\"purple\" alink=\"red\">\n"], + {Html1, Lines} = root(Code, [], 1), + Html = [Html0, + "<pre>\n", Html1, "</pre>\n", + footer(Lines),"</body>\n</html>\n"], + file:write_file(Dest, Html); + {error, Reason} -> + {error, Reason} + end. + +root([], Res, Line) -> + {Res, Line}; +root([Char0|Code], Res, Line0) -> + Char = [Char0], + case Char of + "-" -> + {Match, Line1, NewCode0, AttName} = + read_to_char(Line0+1, Code, [], [$(, $.]), + {_, Line2, NewCode, Stuff} = read_to_char(Line1, NewCode0, [], $\n), + NewRes = [Res,linenum(Line0),"-<b>",AttName, + "</b>",Match, Stuff, "\n"], + root(NewCode, NewRes, Line2); + "%" -> + {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), + NewRes = [Res,linenum(Line0),"<i>%",Stuff,"</i>\n"], + root(NewCode, NewRes, Line); + "\n" -> + root(Code, [Res,linenum(Line0), "\n"], Line0+1); + " " -> + {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), + root(NewCode, [Res,linenum(Line0)," ",Stuff, "\n"], + Line); + "\t" -> + {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), + root(NewCode, [Res,linenum(Line0),"\t",Stuff, "\n"], + Line); + [Chr|_] when Chr>96, Chr<123 -> + %% Assumed to be function/clause start. + %% FIXME: This will trivially generate non-unique anchors + %% (one for each clause) --- which is illegal HTML. + {_, Line1, NewCode0, FName0} = read_to_char(Line0+1, Code, [], $(), + {_, Line2, NewCode, Stuff} = + read_to_char(Line1,NewCode0, [], $\n), + FuncName = [[Chr],FName0], + NewRes=[Res,"<a name=",FuncName,">", + linenum(Line0),"<b>",FuncName,"</b></a>", + "(",Stuff, "\n"], + root(NewCode, NewRes, Line2); + Chr -> + {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), + root(NewCode, [Res,linenum(Line0),Chr,Stuff, "\n"], + Line) + end. + +read_to_char(Line0, [], Res, _Chr) -> + {nomatch, Line0, [], Res}; +read_to_char(Line0, [Char|Code], Res, Chr) -> + case Char of + Chr -> {Char, Line0, Code, Res}; + _ when is_list(Chr) -> + case lists:member(Char,Chr) of + true -> + {Char, Line0, Code, Res}; + false -> + {Line,NewCode,NewRes} = maybe_convert(Line0,Code,Res,Char), + read_to_char(Line, NewCode, NewRes, Chr) + end; + _ -> + {Line,NewCode,NewRes} = maybe_convert(Line0,Code,Res,Char), + read_to_char(Line,NewCode, NewRes, Chr) + end. + +maybe_convert(Line0,Code,Res,Chr) -> + case Chr of + %% Quoted stuff should not have the highlighting like normal code + %% FIXME: unbalanced quotes (e.g. in comments) will cause trouble with + %% highlighting and line numbering in the rest of the module. + $" -> + {_, Line1, NewCode, Stuff0} = read_to_char(Line0, Code, [], $"), + {Line2,Stuff} = add_linenumbers(Line1,lists:flatten(Stuff0),[]), + {Line2,NewCode,[Res,$",Stuff,$"]}; + %% These chars have meaning in HTML, and *must* *not* be + %% written as themselves. + $& -> + {Line0, Code, [Res,"&"]}; + $< -> + {Line0, Code, [Res,"<"]}; + $> -> + {Line0, Code, [Res,">"]}; + %% Everything else is simply copied. + OtherChr -> + {Line0, Code, [Res,OtherChr]} + end. + +add_linenumbers(Line,[Chr|Chrs],Res) -> + case Chr of + $\n -> add_linenumbers(Line+1,Chrs,[Res,$\n,linenum(Line)]); + _ -> add_linenumbers(Line,Chrs,[Res,Chr]) + end; +add_linenumbers(Line,[],Res) -> + {Line,Res}. + +%% Make nicely indented line numbers. +linenum(Line) -> + Num = integer_to_list(Line), + A = case Line rem 10 of + 0 -> "<a name=\"" ++ Num ++"\"></a>"; + _ -> [] + end, + Pred = + case length(Num) of + Length when Length < 5 -> + lists:duplicate(5-Length,$\s); + _ -> + [] + end, + [A,Pred,integer_to_list(Line),":"]. + +footer(Lines) -> + {_, Time} = statistics(runtime), +% io:format("Converted ~p lines in ~.2f Seconds.~n", +% [Lines, Time/1000]), + S = "<i>The transformation of this file (~p lines) took ~.2f seconds</i>", + F = lists:flatten(io_lib:format(S, [Lines, Time/1000])), + ["<hr size=1>",F,"<br>\n"]. |