From 75bc5e521dcc9ab798acefb5400f5f15354f08fd Mon Sep 17 00:00:00 2001 From: Lars G Thorsen Date: Thu, 11 Feb 2010 07:13:28 +0000 Subject: OTP-8343 The documentation is now possible to build in an open source environment after a number of bugs are fixed and some features are added in the documentation build process. - The arity calculation is updated. - The module prefix used in the function names for bif's are removed in the generated links so the links will look like "http://www.erlang.org/doc/man/erlang.html#append_element-2" instead of "http://www.erlang.org/doc/man/erlang.html#erlang:append_element- 2". - Enhanced the menu positioning in the html documentation when a new page is loaded. - A number of corrections in the generation of man pages (thanks to Sergei Golovan) - The legal notice is taken from the xml book file so OTP's build process can be used for non OTP applications. --- system/doc/installation_guide/Makefile | 20 +- system/doc/top/Makefile | 52 ++--- system/doc/top/bin/.gitignore | 0 system/doc/top/bin/otp_man_index | 106 --------- system/doc/top/src/erl_html_tools.erl | 293 +++++++++++-------------- system/doc/top/src/erlresolvelinks.erl | 158 ++++++++----- system/doc/top/src/otp_man_index.erl | 197 +++++++++++++++++ system/doc/top/templates/applications.html.src | 21 +- system/doc/top/templates/index.html.src | 10 +- 9 files changed, 483 insertions(+), 374 deletions(-) create mode 100644 system/doc/top/bin/.gitignore delete mode 100755 system/doc/top/bin/otp_man_index create mode 100644 system/doc/top/src/otp_man_index.erl (limited to 'system/doc') diff --git a/system/doc/installation_guide/Makefile b/system/doc/installation_guide/Makefile index c51f0ee5f3..ec60105ae0 100644 --- a/system/doc/installation_guide/Makefile +++ b/system/doc/installation_guide/Makefile @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1996-2010. 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% # # @@ -53,6 +53,12 @@ XML_FILES = \ $(BOOK_FILES) $(XML_CHAPTER_FILES) \ $(XML_PART_FILES) +# ---------------------------------------------------- +# Readme for X-compiling +# ---------------------------------------------------- +XCOMP_README_FILE = $(ERL_TOP)/xcomp/README.md +README_FILE = $(ERL_TOP)/README + # ---------------------------------------------------- HTML_FILES = \ @@ -92,8 +98,10 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_docs_spec: docs $(INSTALL_DIR) $(RELSYSDIR) - $(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \ + $(INSTALL_DATA) $(README_FILE) $(GIF_FILES) $(HTMLDIR)/*.html \ $(RELSYSDIR) + $(INSTALL_DIR) $(RELSYSDIR)/xcomp + $(INSTALL_DATA) $(XCOMP_README_FILE) $(RELSYSDIR)/xcomp release_spec: diff --git a/system/doc/top/Makefile b/system/doc/top/Makefile index 08fe265336..154deb006b 100644 --- a/system/doc/top/Makefile +++ b/system/doc/top/Makefile @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 1999-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1999-2010. 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% # # @@ -103,7 +103,8 @@ JAVASCRIPT = $(HTMLDIR)/js/erlresolvelinks.js JAVASCRIPT_BUILD_SCRIPT = $(EBIN)/erlresolvelinks.$(EMULATOR) JAVASCRIPT_BUILD_SCRIPT_SRC = src/erlresolvelinks.erl -MAN_INDEX_SCRIPT = $(ERL_TOP)/system/doc/top/bin/otp_man_index +MAN_INDEX_SCRIPT = $(EBIN)/otp_man_index.$(EMULATOR) +MAN_INDEX_SRC = src/otp_man_index.erl MAN_INDEX = $(HTMLDIR)/man_index.html GLOSSARY = $(HTMLDIR)/glossary.html @@ -116,14 +117,11 @@ $(INDEX_SCRIPT): $(INDEX_SRC) $(ERLC) -o$(EBIN) +warn_unused_vars $< # We don't list toc_*.html as targets because we don't know -$(HTMLDIR)/index.html: $(INDEX_SCRIPT) -ifneq ($(INSTALLROOT),) +$(HTMLDIR)/index.html + $(HTMLDIR)/applications.html: $(INDEX_SCRIPT) echo "Generating index $@" - $(ERL) -noshell -pa $(EBIN) -s erl_html_tools top_index $(INSTALLROOT) \ + $(ERL) -noshell -pa $(EBIN) -s erl_html_tools top_index $(ERL_TOP) \ $(HTMLDIR) $(SYSTEM_VSN) -s erlang halt -else - @echo "INSTALLROOT unset, no indexes built." -endif + #-------------------------------------------------------------------------- @@ -131,25 +129,19 @@ $(JAVASCRIPT_BUILD_SCRIPT): $(JAVASCRIPT_BUILD_SCRIPT_SRC) $(ERLC) -o$(EBIN) +warn_unused_vars $< $(JAVASCRIPT): $(JAVASCRIPT_BUILD_SCRIPT) -ifneq ($(INSTALLROOT),) - echo "Generating javascript for resolving HTML links" - erl -noshell -pa $(EBIN) -s erlresolvelinks make $(INSTALLROOT) \ - . -s erlang halt - mkdir $(HTMLDIR)/js - mv erlresolvelinks.js $(JAVASCRIPT) # not portable !!! -else - @echo "INSTALLROOT unset, no javascript generated." -endif + erl -noshell -pa $(EBIN) -s erlresolvelinks make -s erlang halt + $(INSTALL_DIR) $(HTMLDIR)/js + $(INSTALL_DATA) erlresolvelinks.js $(JAVASCRIPT) #-------------------------------------------------------------------------- +$(MAN_INDEX_SCRIPT): $(MAN_INDEX_SRC) + $(ERLC) -o$(EBIN) +warn_unused_vars $< + $(MAN_INDEX): $(MAN_INDEX_SCRIPT) -ifneq ($(INSTALLROOT),) - echo "Generating index $@" - (cd $(INSTALLROOT); perl $< ) > $@ -else - @echo "INSTALLROOT unset, no manual index built." -endif + $(ERL) -noshell -pa $(EBIN) -s otp_man_index gen $(ERL_TOP) $@ \ + -s erlang halt + #-------------------------------------------------------------------------- $(HTMLDIR)/highlights.html: highlights.xml @@ -230,13 +222,11 @@ release_docs_spec: docs $(INSTALL_DIR) $(RELSYSDIR)/pdf $(INSTALL_DATA) \ $(TOP_PDF_FILE) $(RELSYSDIR)/pdf -#$(TOP_HTML_FILES) -ifneq ($(INSTALLROOT),) - $(INSTALL_DATA) $(INDEX_FILES) $(MAN_INDEX) $(TOP_HTML_FILES) $(RELSYSDIR) + $(INSTALL_DATA) $(TOP_HTML_FILES) $(RELSYSDIR) $(INSTALL_DIR) $(RELSYSDIR)/js $(INSTALL_DATA) \ $(JAVASCRIPT) $(RELSYSDIR)/js -endif + $(INSTALL_DATA) $(INDEX_FILES) $(MAN_INDEX) $(TOP_HTML_FILES) $(RELSYSDIR) release_spec: diff --git a/system/doc/top/bin/.gitignore b/system/doc/top/bin/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/doc/top/bin/otp_man_index b/system/doc/top/bin/otp_man_index deleted file mode 100755 index 57a0f12d32..0000000000 --- a/system/doc/top/bin/otp_man_index +++ /dev/null @@ -1,106 +0,0 @@ -#!/opt/local/bin/perl - -use File::Find; -use strict; - -######################################### -# Usage: -# $ cd $ERLANG_RELEASE -# otp_man_index > doc/man_index.html -######################################### - -my (@list,$info); - -find(\&wanted,'.'); - -header(); - -foreach $info (sort {lc($a->[0]) cmp lc($b->[0])} @list) { - my ($module,$application,$dir,$path) = @$info; - - my $idx = -f "$dir/index.html" ? "$dir/index.html" : "$dir/../index.html"; - # Remove .html extension from module name, if there is one - if ($module =~ /(\w+).html$/) { - $module = "$1"; - } - print " \n"; - print " $module\n"; - print " $application\n"; - print " \n"; -} - -footer(); - -########################################################################### - -sub wanted { - return unless /\.html$/ and -f $_; - - open(FILE,$_) or die "ERROR: Can't open $File::Find::name: $!\n"; - my $line; - - while (defined ($line = )) { - if ($line =~ //) { - close FILE; - my $path = $File::Find::name; - $path =~ s/\.\///; # Remove './' prefix - my $dir = $File::Find::dir; - $dir =~ s/\.\///; # Remove './' prefix - $dir =~ m&([^/]+)/doc/html$&; - my $application = $1; - push(@list, [$_,$application,$dir,$path]); - return; - } - } - close FILE; -} - - -sub header { - print < - - - - - Erlang/OTP Manual Page Index - - -
- - -[Up | -Erlang] -
-

Manual Page Index
-

-
-

- - - - -EOS -} - -sub footer { - my $year = (localtime)[5] + 1900; - print < - -

-

-
- -Copyright © 1991-$year - -Ericsson AB - -
- - -EOS -} diff --git a/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl index d93516768e..8a5c744128 100644 --- a/system/doc/top/src/erl_html_tools.erl +++ b/system/doc/top/src/erl_html_tools.erl @@ -1,130 +1,66 @@ -%% ``The contents of this file are subject to the Erlang Public License, +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2010. 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 via the world wide web at http://www.erlang.org/. -%% +%% 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. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% --module(erl_html_tools). - -%% This file contains tools for updating HTML files in an installed system -%% depending on the installed applications. Currently the only use is -%% to update the top index file. - - -%% ------ VERY IMPORTANT ------ %% -%% Original location for this file: -%% /clearcase/otp/internal_tools/integration/scripts/make_index/ -%% When updating this file, copy the source to -%% /home/otp/patch/share/program/ -%% and place .beam files (compiled with correct release) in all -%% /home/otp/patch/share/program/ -%% for releases >= R9C +%% %CopyrightEnd% %% -%% ---------------------------- - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% This program generate the top index files for the OTP documentation. -% Part of the HTML code is in templates, like "index.html.src" and -% part is written out from this module. So the program and the templates -% has to match. -% -% The templates are searched from the current directory, a directory -% "templates" relative to the current directory or at RootDir. -% -% RootDir is given as an argument or assumed to be code:root_dir(), -% i.e. the root of the system running this program. -% -% The output is put into DestDir or RootDir if not given. -% -% The functions to call are -% -% top_index() -% top_index([RootDir]) -% top_index([RootDir,DestDir,OtpRel]) -% top_index(RootDir) -% top_index(RootDir, DestDir, OtpRel) -% -% where RootDir can be a string or an atom. -% -% -% USING THIS SCRIPT FROM THE UNIX COMMAND LINE -% -------------------------------------------- -% If the Erlang started is the same as the Erlang to create index.html -% for the use -% -% % erl -noshell -s erl_html_tools top_index -% -% If you want to create an index for another Erlang installation or -% documentation located separate from the object code, then use -% -% % erl -noshell -s erl_html_tools top_index /path/to/erlang/root -% -% -% COLLECTING INFORMATION -% ---------------------- -% This script assumes that all applications have an "info" file -% in their top directory. This file should have some keywords with -% values defined. The keys are 'group' and 'short' (for "short -% description). See the OTP applications for examples. -% -% Some HTML code is generated by this program, others are taken from -% the file "index.html.src" that may be located in the patch directory -% or in the "$ERLANG_ROOT/doc/" directory. -% -% The code for creating the top index page assumes all applications -% have a file "info" with some fields filled in -% -% short: Text Short text describing the application -% group: tag [Heading] Group tag optionally followed by a description. -% Only one app need to describe the group but -% more than one can. -% -% FIXME: Check that there is documentation for the application, not just -% an info file. -% FIXME: Use records, it is now unreadable :-( -% FIXME: Use a separate URL and URLIndexFile -% FIXME: Pass the OTP release name as an argument instead of in -% process dictionary (for elegance). +%%----------------------------------------------------------------- +%% File: erl_html_tools.erl +%% +%% Description: +%% This file generates the top index of the documentation. +%% +%%----------------------------------------------------------------- +-module(erl_html_tools). -export([top_index/0,top_index/1,top_index/3,top_index_silent/3]). -% This is the order groups are inserted into the file. Groups -% not in this list is inserted in undefined order. +-include_lib("kernel/include/file.hrl"). group_order() -> [ - basic, - dat, - oam, - orb, - comm, - tools + {basic, "Basic"}, + {dat, "Database"}, + {oam, "Operation & Maintenance"}, + {comm, "Interface and Communication"}, + {tools, "Tools"}, + {test, "Test"}, + {doc, "Documentation"}, + {orb, "Object Request Broker & IDL"}, + {misc, "Miscellaneous"} ]. top_index() -> - top_index(code:root_dir()). + case os:getenv("ERL_TOP") of + false -> + io:format("Variable ERL_TOP is required\n",[]); + Value -> + {_,RelName} = init:script_id(), + top_index(Value, filename:join(Value, "doc"), RelName) + end. -top_index([RootDir]) when atom(RootDir) -> - top_index(atom_to_list(RootDir)); -top_index([RootDir,DestDir,OtpRel]) +top_index([RootDir, DestDir, OtpRel]) when is_atom(RootDir), is_atom(DestDir), is_atom(OtpRel) -> top_index(atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpRel)); -top_index(RootDir) -> +top_index(RootDir) when is_atom(RootDir) -> {_,RelName} = init:script_id(), top_index(RootDir, filename:join(RootDir, "doc"), RelName). + + top_index(RootDir, DestDir, OtpRel) -> report("****\nRootDir: ~p", [RootDir]), report("****\nDestDir: ~p", [DestDir]), @@ -145,7 +81,9 @@ top_index_silent(RootDir, DestDir, OtpRel) -> Result = top_index(RootDir, DestDir, OtpRel), erase(silent), Result. - + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Main loop - process templates @@ -173,7 +111,7 @@ process_multi_template(BaseName0, Template, DestDir, Info) -> BaseName1 = filename:basename(BaseName0, Ext), [_|BaseName2] = lists:reverse(BaseName1), BaseName = lists:reverse(BaseName2), - Groups0 = [{[$_|atom_to_list(G)],G} || G <- group_order()], + Groups0 = [{[$_|atom_to_list(G)],G} || {G, _} <- group_order()], Groups = [{"",basic}|Groups0], process_multi_template_1(Groups, BaseName, Ext, Template, DestDir, Info). @@ -240,34 +178,47 @@ find_information(Bases) -> find_application_paths([]) -> []; -find_application_paths([{URL,Dir} | Paths]) -> +find_application_paths([{URL, Dir} | Paths]) -> Sub1 = "doc/html/index.html", %% Sub2 = "doc/index.html", - case file:list_dir(Dir) of - {ok, Dirs} -> - AppDirs = - lists:filter( - fun(E) -> - is_match(E, "^[A-Za-z0-9_]+-[0-9\\.]+") - end, Dirs), - AppPaths = - lists:map( - fun(AppDir) -> - {ok,[App,Ver]} = regexp:split(AppDir, "-"), - DirPath = filename:join(Dir,AppDir), - AppURL = URL ++ AppDir, - {App,Ver,DirPath,AppURL ++ "/" ++ Sub1} -%% case file:read_file_info( -%% filename:join(DirPath, Sub1)) of -%% {ok, _} -> -%% {App,Ver,DirPath,AppURL ++ "/" ++ Sub1}; -%% _ -> -%% {App,Ver,DirPath,AppURL ++ "/" ++ Sub2} -%% end - end, AppDirs), - AppPaths ++ find_application_paths(Paths) - end. + AppDirs = get_app_dirs(Dir), + + AppPaths = + lists:map( + fun({App, AppPath}) -> + VsnFile = filename:join(AppPath, "vsn.mk"), + VsnStr = + case file:read_file(VsnFile) of + {ok, Bin} -> + case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of + {match, [V]} -> + V; + nomatch -> + exit(io_lib:format("No VSN variable found in ~s\n", + [VsnFile])) + end; + {error, Reason} -> + exit(io_lib:format("~p : ~s\n", [Reason, VsnFile])) + end, + AppURL = URL ++ App ++ "-" ++ VsnStr, + {App, VsnStr, AppPath, AppURL ++ "/" ++ Sub1} + end, AppDirs), + AppPaths ++ find_application_paths(Paths). + +get_app_dirs(Dir) -> + {ok, Files} = file:list_dir(Dir), + AFiles = + lists:map(fun(File) -> {File, filename:join([Dir, File])} end, Files), + lists:zf(fun is_app_with_doc/1, AFiles). + +is_app_with_doc({ADir, APath}) -> + case file:read_file_info(filename:join([APath, "info"])) of + {ok, _FileInfo} -> + {true, {ADir, APath}}; + _ -> + false + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Find info for one application. @@ -281,20 +232,20 @@ find_application_paths([{URL,Dir} | Paths]) -> find_application_infos([]) -> []; -find_application_infos([{App,Ver,AppPath,IndexURL} | Paths]) -> +find_application_infos([{App, Vsn, AppPath, IndexURL} | Paths]) -> case read_info(filename:join(AppPath,"info")) of {error,_Reason} -> warning("No info for app ~p", [AppPath]), find_application_infos(Paths); Db -> - {Group,Heading} = + {Group,_Heading} = case lists:keysearch("group", 1, Db) of {value, {_, G0}} -> % This value may be in two parts, % tag and desciption - case string:str(G0," ") of + case string:str(G0, " ") of 0 -> - {list_to_atom(G0),""}; + {list_to_atom(G0), ""}; N -> {list_to_atom(string:substr(G0,1,N-1)), string:substr(G0,N+1)} @@ -309,7 +260,8 @@ find_application_infos([{App,Ver,AppPath,IndexURL} | Paths]) -> false -> "" end, - [{Group,Heading,{App,{Ver,AppPath,IndexURL,Text}}} +%% [{Group, Heading, {App, {Vsn, AppPath, IndexURL, Text}}} + [{Group, "", {App, {Vsn, AppPath, IndexURL, Text}}} | find_application_infos(Paths)] end. @@ -439,17 +391,17 @@ search_appname(App, [{_Group,_,Apps} | Groups]) -> search_appname(App, Groups) end; search_appname(_App, []) -> - {error,noapp}. + {error, noapp}. subst_applinks(Info, Group) -> subst_applinks_1(group_order(), Info, Group). -subst_applinks_1([G|Gs], Info0, Group) -> +subst_applinks_1([{G, Heading}|Gs], Info0, Group) -> case lists:keysearch(G, 1, Info0) of - {value,{G,Heading,Apps}} -> + {value,{G,_Heading,Apps}} -> Info = lists:keydelete(G, 1, Info0), - ["\n
  • ",Heading,"\n
      \n", - html_applinks(Apps),"\n
  • \n"| + ["\n
  • ",Heading, "\n
      \n", + html_applinks(Apps), "\n
  • \n"| subst_applinks_1(Gs, Info, Group)]; false -> warning("No applications in group ~w\n", [G]), @@ -457,7 +409,7 @@ subst_applinks_1([G|Gs], Info0, Group) -> end; subst_applinks_1([], [], _) -> []; subst_applinks_1([], Info, _) -> - error("Info left:\n", [Info]), + error("Info left: ~p\n", [Info]), []. html_applinks([{Name,[{_,_,URL,_}|_]}|AppNames]) -> @@ -482,9 +434,9 @@ subst_groups(Info0) -> subst_known_groups([], Info, Text) -> {Text,Info}; -subst_known_groups([Group | Groups], Info0, Text0) -> +subst_known_groups([{Group, Heading} | Groups], Info0, Text0) -> case lists:keysearch(Group, 1, Info0) of - {value,{_,Heading,Apps}} -> + {value,{_,_Heading,Apps}} -> Text = group_table(Heading,Apps), Info = lists:keydelete(Group, 1, Info0), subst_known_groups(Groups, Info, Text0 ++ Text); @@ -634,34 +586,36 @@ combine_key_value([]) -> lines_to_key_value([]) -> []; lines_to_key_value([Line | Lines]) -> - case regexp:first_match(Line, "^[a-zA-Z_\\-]+:") of + case re:run(Line, "^[a-zA-Z_\\-]+:") of nomatch -> - case regexp:first_match(Line, "[\041-\377]") of + case re:run(Line, "[\041-\377]") of nomatch -> lines_to_key_value(Lines); _ -> warning("skipping line \"~s\"",[Line]), lines_to_key_value(Lines) end; - {match, _, Length} -> + {match, [{0, Length} |_]} -> Value0 = lists:sublist(Line, Length+1, length(Line) - Length), - {ok, Value1, _} = regexp:sub(Value0, "^[ \t]*", ""), - {ok, Value, _} = regexp:sub(Value1, "[ \t]*$", ""), + Value1 = re:replace(Value0, "^[ \t]*", "", + [{return, list}]), + Value = re:replace(Value1, "[ \t]*$", "", + [{return, list}]), Key = lists:sublist(Line, Length-1), - [{Key,Value} | lines_to_key_value(Lines)] + [{Key, Value} | lines_to_key_value(Lines)] end. - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Extensions to the 'regexp' module. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -is_match(Ex, Re) -> - case regexp:first_match(Ex, Re) of - {match, _, _} -> - true; - nomatch -> - false - end. +%% is_match(Ex, Re) -> +%% case regexp:first_match(Ex, Re) of +%% {match, _, _} -> +%% true; +%% nomatch -> +%% false +%% end. %% -type gsub(String, RegExp, Fun, Acc) -> subres(). %% Substitute every match of the regular expression RegExp with the @@ -669,25 +623,27 @@ is_match(Ex, Re) -> %% regular expressions. Acc is an argument to the Fun. The Fun should return %% a tuple {Replacement, NewAcc}. -gsub(String, RegExp, Fun, Acc) when list(RegExp) -> - case regexp:parse(RegExp) of - {ok,RE} -> gsub(String, RE, Fun, Acc); - {error,E} -> {error,E} +gsub(String, RegExp, Fun, Acc) when is_list(RegExp) -> + case re:compile(RegExp) of + {ok, RE} -> + gsub(String, RE, Fun, Acc); + {error, E} -> + {error, E} end; gsub(String, RE, Fun, Acc) -> - {match,Ss} = regexp:matches(String, RE), - {NewString, NewAcc} = sub_repl(Ss, Fun, Acc, String, 1), - {ok,NewString,NewAcc}. + {match, Ss} = re:run(String, RE, [global]), + {NewString, NewAcc} = sub_repl(Ss, Fun, Acc, String, 0), + {ok, NewString, NewAcc}. % New code that uses fun for finding the replacement. Also uses accumulator % to pass argument between the calls to the fun. -sub_repl([{St,L}|Ss], Fun, Acc0, S, Pos) -> - Match = string:substr(S, St, L), +sub_repl([[{St, L}] |Ss], Fun, Acc0, S, Pos) -> + Match = string:substr(S, St+1, L), {Rep, Acc} = Fun(Match, Acc0), {Rs, NewAcc} = sub_repl(Ss, Fun, Acc, S, St+L), - {string:substr(S, Pos, St-Pos) ++ Rep ++ Rs, NewAcc}; -sub_repl([], _Fun, Acc, S, Pos) -> {string:substr(S, Pos), Acc}. + {string:substr(S, Pos+1, St-Pos) ++ Rep ++ Rs, NewAcc}; +sub_repl([], _Fun, Acc, S, Pos) -> {string:substr(S, Pos+1), Acc}. @@ -725,3 +681,4 @@ uc([H | T], Acc) when is_integer(H), [97] =< H, H =< $z -> uc(T, [H - 32 | Acc]); uc([H | T], Acc) -> uc(T, [H | Acc]). + diff --git a/system/doc/top/src/erlresolvelinks.erl b/system/doc/top/src/erlresolvelinks.erl index a891b67421..004d0d8626 100644 --- a/system/doc/top/src/erlresolvelinks.erl +++ b/system/doc/top/src/erlresolvelinks.erl @@ -1,42 +1,60 @@ --module(erlresolvelinks). - -%% ------ VERY IMPORTANT ------ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2010. 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/. %% -%% Original location for this file: -%% /clearcase/otp/internal_tools/integration/scripts/resolve_links/ -%% When updating this file, copy the source to -%% /usr/local/otp/patch/share/program/ -%% and place .beam files (compiled with correct release) in all -%% /usr/local/otp/patch/share/program/ -%% for releases >= R10B +%% 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% +%% +%%----------------------------------------------------------------- +%% File: erlresolvelinks.erl +%% +%% Description: +%% This file generates the javascript that resolves documentation links. +%% +%%----------------------------------------------------------------- +-module(erlresolvelinks). --export([make/1, do_make/1, do_make/2, do_make/3]). +-export([make/0, make/1]). -include_lib("kernel/include/file.hrl"). -define(JAVASCRIPT_NAME, "erlresolvelinks.js"). -make([RootDir]) -> - do_make(RootDir); +make() -> + case os:getenv("ERL_TOP") of + false -> + io:format("Variable ERL_TOP is required\n",[]); + Value -> + make_from_src(Value, ".") + end. + make([RootDir, DestDir]) -> do_make(RootDir, DestDir); -make([RootDir, DestDir, Name]) -> - do_make(RootDir, DestDir, Name). - -do_make(RootDir) -> +make(RootDir) when is_atom(RootDir) -> DestDir = filename:join(RootDir, "doc"), do_make(RootDir, DestDir). -do_make(RootDir, DestDir) -> - do_make(RootDir, DestDir, ?JAVASCRIPT_NAME). +do_make(_RootDir, _DestDir) -> + ok. -do_make(RootDir, DestDir, Name) -> +make_from_src(RootDir, DestDir) -> %% doc/Dir %% erts-Vsn %% lib/App-Vsn - DocDirs0 = get_dirs(filename:join([RootDir, "doc"])), - DocDirs = lists:map(fun(Dir) -> + Name = ?JAVASCRIPT_NAME, + DocDirs0 = get_dirs(filename:join([RootDir, "system/doc"])), + DocDirs = lists:map(fun({Dir, _DirPath}) -> D = filename:join(["doc", Dir]), {D, D} end, DocDirs0), @@ -68,7 +86,10 @@ do_make(RootDir, DestDir, Name) -> io:fwrite(Fd, "}\n", []), file:close(Fd), ok. - + + + + get_dirs(Dir) -> {ok, Files} = file:list_dir(Dir), AFiles = @@ -79,7 +100,7 @@ is_dir({File, AFile}) -> {ok, FileInfo} = file:read_file_info(AFile), case FileInfo#file_info.type of directory -> - {true, File}; + {true, {File, AFile}}; _ -> false end. @@ -88,47 +109,66 @@ latest_app_dirs(RootDir, Dir) -> ADir = filename:join(RootDir, Dir), RDirs0 = get_dirs(ADir), RDirs1 = lists:filter(fun is_app_dir/1, RDirs0), - %% Build a list of {{App, VsnNumList}, AppVsn} + SDirs0 = - lists:map(fun(AppVsn) -> - [App, VsnStr] = string:tokens(AppVsn, "-"), - VsnNumList = vsnstr_to_numlist(VsnStr), - {{App, VsnNumList}, AppVsn} end, + lists:map(fun({App, Dir1}) -> + File = filename:join(Dir1, "vsn.mk"), + case file:read_file(File) of + {ok, Bin} -> + case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of + {match, [VsnStr]} -> + VsnNumList = vsnstr_to_numlist(VsnStr), + {{App, VsnNumList}, App++"-"++VsnStr}; + nomatch -> + io:format("No VSN variable found in ~s\n", [File]), + error + end; + {error, Reason} -> + io:format("~p : ~s\n", [Reason, File]), + error + end + end, RDirs1), - SDirs1 = lists:keysort(1, SDirs0), - App2Dirs = lists:foldr(fun({{App, _VsnNumList}, AppVsn}, Acc) -> - case lists:keymember(App, 1, Acc) of - true -> - Acc; - false -> - [{App, AppVsn}| Acc] - end - end, [], SDirs1), + SDirs1 = lists:keysort(1, SDirs0), + App2Dirs = lists:foldr(fun({{App, _VsnNumList}, AppVsn}, Acc) -> + case lists:keymember(App, 1, Acc) of + true -> + Acc; + false -> + [{App, AppVsn}| Acc] + end + end, [], SDirs1), lists:map(fun({App, AppVsn}) -> {App, filename:join([Dir, AppVsn])} end, - App2Dirs). - -is_app_dir(Dir) -> - case string:tokens(Dir, "-") of - [_Name, Rest] -> - is_vsnstr(Rest); - _ -> + App2Dirs). + +is_app_dir({_Dir, DirPath}) -> + case file:read_file_info(filename:join(DirPath, "vsn.mk")) of + {ok, FileInfo} -> + case FileInfo#file_info.type of + regular -> + true; + _ -> + false + end; + {error, _Reason} -> false end. -is_vsnstr(Str) -> - case string:tokens(Str, ".") of - [_] -> - false; - Toks -> - lists:all(fun is_numstr/1, Toks) - end. -is_numstr(Cs) -> - lists:all(fun(C) when $0 =< C, C =< $9 -> - true; - (_) -> - false - end, Cs). +%% is_vsnstr(Str) -> +%% case string:tokens(Str, ".") of +%% [_] -> +%% false; +%% Toks -> +%% lists:all(fun is_numstr/1, Toks) +%% end. + +%% is_numstr(Cs) -> +%% lists:all(fun(C) when $0 =< C, C =< $9 -> +%% true; +%% (_) -> +%% false +%% end, Cs). %% We know: diff --git a/system/doc/top/src/otp_man_index.erl b/system/doc/top/src/otp_man_index.erl new file mode 100644 index 0000000000..78ecd8b954 --- /dev/null +++ b/system/doc/top/src/otp_man_index.erl @@ -0,0 +1,197 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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% +%% +%%----------------------------------------------------------------- +%% File: otp_man_index.erl +%% +%% Description: +%% This file generates the module overview in the documentation. +%% +%%----------------------------------------------------------------- + +-module(otp_man_index). + +-export([gen/1]). +-include_lib("kernel/include/file.hrl"). + + +gen([RootDir, OutFile]) when is_atom(RootDir), is_atom(OutFile)-> + Bases = [{"../lib/", filename:join(RootDir, "lib")}, + {"../", RootDir}], + Apps = find_application_paths(Bases), + RefPages = find_ref_files(Apps), + gen_html(RefPages, atom_to_list(OutFile)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Find Reference files +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +find_ref_files(Apps) -> + find_ref_files(Apps, []). + +find_ref_files([], Acc) -> + Acc; +find_ref_files([{App, Vsn, AppPath, RelPath} |Apps], Acc) -> + case filelib:wildcard(filename:join(AppPath, "*.html")) of + [] -> + find_ref_files(Apps, Acc); + Result -> + + Refs1 = lists:filter(fun(Ref) -> + case file:read_file(Ref) of + {ok, Bin} -> + case re:run(Bin, ".*.*",[]) of + {match, _} -> + true; + nomatch -> + false + end; + {error, Reason} -> + exit(io_lib:format("~p : ~s\n", [Reason, Ref])) + end + end, + Result), + + Refs2 = lists:map(fun(Ref) -> + Module = filename:basename(Ref, ".html"), + {string:to_lower(Module), + Module, + App ++ "-" ++ Vsn, + RelPath, + filename:join(RelPath, filename:basename(Ref))} + end, + Refs1), + find_ref_files(Apps, Refs2 ++ Acc) + end. + +find_application_paths([]) -> + []; +find_application_paths([{URL, Dir} | Paths]) -> + Sub1 = "doc/html", + + AppDirs = get_app_dirs(Dir), + + AppPaths = + lists:map( + fun({App, AppPath}) -> + VsnFile = filename:join(AppPath, "vsn.mk"), + VsnStr = + case file:read_file(VsnFile) of + {ok, Bin} -> + case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of + {match, [V]} -> + V; + nomatch -> + exit(io_lib:format("No VSN variable found in ~s\n", + [VsnFile])) + end; + {error, Reason} -> + exit(io_lib:format("~p : ~s\n", [Reason, VsnFile])) + end, + AppURL = URL ++ App ++ "-" ++ VsnStr, + {App, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1} + end, AppDirs), + AppPaths ++ find_application_paths(Paths). + + +get_app_dirs(Dir) -> + {ok, Files} = file:list_dir(Dir), + AFiles = + lists:map(fun(File) -> {File, filename:join([Dir, File])} end, Files), + lists:zf(fun is_app_with_doc/1, AFiles). + +is_app_with_doc({ADir, APath}) -> + case file:read_file_info(filename:join([APath, "info"])) of + {ok, _FileInfo} -> + {true, {ADir, APath}}; + _ -> + false + end. + + + + +gen_html(RefPages, OutFile)-> + case file:open(OutFile, [write]) of + {ok, Out} -> + io:fwrite(Out, "~s\n", [html_header()]), + + SortedPages = lists:sort(RefPages), + + lists:foreach(fun({_,Module, App, AppDocDir, RefPagePath}) -> + io:fwrite(Out, "
    \n",[]), + io:fwrite(Out, " \n", + [RefPagePath, Module]), + io:fwrite(Out, " \n", + [filename:join(AppDocDir, "index.html"), + App]), + io:fwrite(Out, " \n",[]) + end, + SortedPages), + + {Year, _, _} = date(), + io:fwrite(Out, "~s\n", [html_footer(integer_to_list(Year))]); + {error, Reason} -> + exit("~p: ~s\n",[Reason, OutFile]) + end. + + + +html_header() -> + "\n" + "\n" + "\n" + "\n" + " \n" + " Erlang/OTP Manual Page Index\n" + "\n" + "\n" + "
    \n" + "\n" + "\n" + "[Up | Erlang]\n" + "
    \n" + "

    OTP Reference Page Index
    \n" + "

    \n" + "
    \n" + "

    \n" + "

    Manual PageApplication
    ~s~s
    \n" + "\n" + " \n" + "\n". + + + +html_footer(Year) -> + "
    Manual PageApplication
    \n" + "

    \n" + "

    \n" + "

    \n" + "
    \n" + "\n" + "Copyright © 1991-" ++ Year ++ "\n" + "\n" + "Ericsson AB\n" + "\n" + "
    \n" + "\n" + "\n". diff --git a/system/doc/top/templates/applications.html.src b/system/doc/top/templates/applications.html.src index 0251d39b28..285bbced71 100644 --- a/system/doc/top/templates/applications.html.src +++ b/system/doc/top/templates/applications.html.src @@ -1,7 +1,26 @@ + + - Erlang/OTP #version# + Erlang/OTP #version# Applications