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. --- lib/common_test/info | 2 +- lib/docbuilder/info | 2 +- lib/edoc/info | 2 +- lib/erl_docgen/priv/xsl/db_man.xsl | 28 ++- lib/eunit/info | 2 +- lib/hipe/Makefile | 2 +- lib/hipe/doc/Makefile | 17 +- lib/hipe/doc/src/Makefile | 21 +- lib/hipe/doc/src/book.xml | 9 +- lib/hipe/doc/src/hipe_app.xml | 58 +++++ lib/hipe/doc/src/ref_man.xml | 35 +++ lib/hipe/info | 2 +- lib/test_server/info | 2 +- 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 +- 22 files changed, 629 insertions(+), 410 deletions(-) create mode 100644 lib/hipe/doc/src/hipe_app.xml create mode 100644 lib/hipe/doc/src/ref_man.xml 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 diff --git a/lib/common_test/info b/lib/common_test/info index 1819ca2aad..6b2778f3e6 100644 --- a/lib/common_test/info +++ b/lib/common_test/info @@ -1,2 +1,2 @@ -group: tools +group: test short: A portable framework for automatic testing diff --git a/lib/docbuilder/info b/lib/docbuilder/info index 33ce19fb4b..60daa212c8 100644 --- a/lib/docbuilder/info +++ b/lib/docbuilder/info @@ -1,2 +1,2 @@ -group: tools +group: doc short: Tool for generating HTML documentation for applications. diff --git a/lib/edoc/info b/lib/edoc/info index cb25c1e519..bc52caa78b 100644 --- a/lib/edoc/info +++ b/lib/edoc/info @@ -1,3 +1,3 @@ -group: tools +group: doc Documentation Applications short: A utility used to generate documentation out of tags in source files. diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl index a9a2781a8a..a2b1e755e2 100644 --- a/lib/erl_docgen/priv/xsl/db_man.xsl +++ b/lib/erl_docgen/priv/xsl/db_man.xsl @@ -176,10 +176,12 @@ - - + + Ericsson AB + + .TH 3 " " "" "Erlang Module Definition" .SH NAME \- @@ -190,11 +192,12 @@ - - + + Ericsson AB + - .TH 1 " " "" "User Commands" + .TH 1 " " "" "User Commands" .SH NAME \- @@ -204,8 +207,9 @@ - - + + Ericsson AB + .TH 3 " " "" "C Library Functions" @@ -218,8 +222,9 @@ - - + + Ericsson AB + .TH 5 " " "" "Files" @@ -232,8 +237,9 @@ - - + + Ericsson AB + .TH 7 " " "" "Erlang Application Definition" diff --git a/lib/eunit/info b/lib/eunit/info index 138f4dc040..e7e6265940 100644 --- a/lib/eunit/info +++ b/lib/eunit/info @@ -1,2 +1,2 @@ -group: tools +group: test short: Support for unit testing. diff --git a/lib/hipe/Makefile b/lib/hipe/Makefile index 10bf82b2d7..54efd7fcaf 100644 --- a/lib/hipe/Makefile +++ b/lib/hipe/Makefile @@ -27,7 +27,7 @@ else HIPE_SUBDIRS = endif -ALWAYS_SUBDIRS = misc main cerl icode flow util +ALWAYS_SUBDIRS = misc main cerl icode flow util doc/src ifdef HIPE_ENABLED # "rtl" below must be the first directory so that file rtl/hipe_literals.hrl diff --git a/lib/hipe/doc/Makefile b/lib/hipe/doc/Makefile index 340f909aa6..cdf9c9c798 100644 --- a/lib/hipe/doc/Makefile +++ b/lib/hipe/doc/Makefile @@ -1,21 +1,28 @@ -# ``The contents of this file are subject to the Erlang Public License, +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2006-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. -# +# +# %CopyrightEnd% +# SHELL=/bin/sh include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk clean: - -rm -f *.html edoc-info stylesheet.css + -rm -f *.html edoc-info stylesheet.css erlang.png # ---------------------------------------------------- # Special Build Targets diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile index 3b63e57549..d440178e4c 100644 --- a/lib/hipe/doc/src/Makefile +++ b/lib/hipe/doc/src/Makefile @@ -1,19 +1,20 @@ -# ``The contents of this file are subject to the Erlang Public License, +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2006-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.'' -# -# $Id$ +# +# %CopyrightEnd% # include $(ERL_TOP)/make/target.mk include $(ERL_TOP)/make/$(TARGET)/otp.mk @@ -33,7 +34,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # ---------------------------------------------------- # Target Specs # ---------------------------------------------------- -XML_APPLICATION_FILES = +XML_APPLICATION_FILES = ref_man.xml XML_REF3_FILES = XML_PART_FILES = part_notes.xml diff --git a/lib/hipe/doc/src/book.xml b/lib/hipe/doc/src/book.xml index 236dfc69a1..9c95e3a827 100644 --- a/lib/hipe/doc/src/book.xml +++ b/lib/hipe/doc/src/book.xml @@ -4,7 +4,7 @@
- 20062009 + 20062010 Ericsson AB. All Rights Reserved. @@ -13,12 +13,12 @@ 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. - + HiPE @@ -31,6 +31,9 @@ HiPE + + + diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml new file mode 100644 index 0000000000..56729d4cc4 --- /dev/null +++ b/lib/hipe/doc/src/hipe_app.xml @@ -0,0 +1,58 @@ + + + + +
+ + 19972010 + Ericsson AB. 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. + + + + snmp + + + + + + + + hipe.xml +
+ HiPE + The HiPE Application + +

+ The normal way to native-compile an Erlang module using HiPE is to include the atom native + in the Erlang compiler options, as in: + + 1> c(my_module, [native]). + Options to the HiPE compiler are then passed as follows: + + 1> c(my_module, [native,{hipe,Options}]). + For on-line help in the Erlang shell, call hipe:help(). + Details on HiPE compiler options are given by hipe:help_options(). +

+
+
+ SEE ALSO +

+ c(3), + compile(3) +

+
+ +
+ diff --git a/lib/hipe/doc/src/ref_man.xml b/lib/hipe/doc/src/ref_man.xml new file mode 100644 index 0000000000..09d10147ee --- /dev/null +++ b/lib/hipe/doc/src/ref_man.xml @@ -0,0 +1,35 @@ + + + + +
+ + 19962009 + Ericsson AB. 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. + + + + HiPE + + + 1997-06-04 + 1.3.1 + ref_man.xml +
+ + + +
+ diff --git a/lib/hipe/info b/lib/hipe/info index 51b5dfb979..fe08fc8990 100644 --- a/lib/hipe/info +++ b/lib/hipe/info @@ -1,2 +1,2 @@ -group: basic +group: misc Miscellaneous Applications short: High Performance Erlang \ No newline at end of file diff --git a/lib/test_server/info b/lib/test_server/info index 79ccc202d7..7a9ed6c700 100644 --- a/lib/test_server/info +++ b/lib/test_server/info @@ -1,2 +1,2 @@ -group: tools +group: test Test Applications short: The OTP Test Server 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