diff options
Diffstat (limited to 'lib/tools/doc/src')
32 files changed, 7731 insertions, 0 deletions
diff --git a/lib/tools/doc/src/Makefile b/lib/tools/doc/src/Makefile new file mode 100644 index 0000000000..bab607c4bd --- /dev/null +++ b/lib/tools/doc/src/Makefile @@ -0,0 +1,132 @@ +# +# %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% +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(TOOLS_VSN) +APPLICATION=tools + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +XML_APPLICATION_FILES = ref_man.xml + +XML_REF3_FILES = \ + cover.xml \ + eprof.xml \ + fprof.xml \ + cprof.xml \ + instrument.xml \ + make.xml \ + tags.xml \ + xref.xml \ + erlang_mode.xml + +XML_PART_FILES = part.xml part_notes.xml part_notes_history.xml + +XML_CHAPTER_FILES = \ + cover_chapter.xml \ + fprof_chapter.xml \ + cprof_chapter.xml \ + erlang_mode_chapter.xml \ + xref_chapter.xml \ + notes.xml \ + notes_history.xml + + +BOOK_FILES = book.xml + +XML_FILES = \ + $(BOOK_FILES) $(XML_CHAPTER_FILES) \ + $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES) + +GIF_FILES = \ + venn1.gif \ + venn2.gif + +# ---------------------------------------------------- + +HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) + +INFO_FILE = ../../info + +MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) + +HTML_REF_MAN_FILE = $(HTMLDIR)/index.html + +TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +XML_FLAGS += + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +$(HTMLDIR)/%.gif: %.gif + $(INSTALL_DATA) $< $@ + +docs: pdf html man + +$(TOP_PDF_FILE): $(XML_FILES) + +pdf: $(TOP_PDF_FILE) + +html: gifs $(HTML_REF_MAN_FILE) + +man: $(MAN3_FILES) + +gifs: $(GIF_FILES:%=$(HTMLDIR)/%) + +debug opt: + +clean clean_docs: + rm -rf $(HTMLDIR)/* + rm -f $(MAN3DIR)/* + rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f errs core *~ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_docs_spec: docs + $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf + $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf + $(INSTALL_DIR) $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(HTMLDIR)/* \ + $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR) + $(INSTALL_DIR) $(RELEASE_PATH)/man/man3 + $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3 + +release_spec: + diff --git a/lib/tools/doc/src/book.xml b/lib/tools/doc/src/book.xml new file mode 100644 index 0000000000..96f6c426c3 --- /dev/null +++ b/lib/tools/doc/src/book.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE book SYSTEM "book.dtd"> + +<book xmlns:xi="http://www.w3.org/2001/XInclude"> + <header titlestyle="normal"> + <copyright> + <year>1997</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Tools</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <insidecover> + </insidecover> + <pagetext>Tools</pagetext> + <preamble> + </preamble> + <parts lift="no"> + <xi:include href="part.xml"/> + </parts> + <applications> + <xi:include href="ref_man.xml"/> + </applications> + <releasenotes> + <xi:include href="notes.xml"/> + </releasenotes> + <listofterms></listofterms> + <index></index> +</book> + diff --git a/lib/tools/doc/src/cover.xml b/lib/tools/doc/src/cover.xml new file mode 100644 index 0000000000..323bd0dda8 --- /dev/null +++ b/lib/tools/doc/src/cover.xml @@ -0,0 +1,458 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2001</year> + <year>2007</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>cover</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>cover</module> + <modulesummary>A Coverage Analysis Tool for Erlang</modulesummary> + <description> + <p>The module <c>cover</c> provides a set of functions for coverage + analysis of Erlang programs, counting how many times each + <em>executable line</em> of code is executed when a program is run. <br></br> + + An executable line contains an Erlang expression such as a matching + or a function call. A blank line or a line containing a comment, + function head or pattern in a <c>case</c>- or <c>receive</c> statement + is not executable.</p> + <p>Coverage analysis can be used to verify test cases, making sure all + relevant code is covered, and may also be helpful when looking for + bottlenecks in the code.</p> + <p>Before any analysis can take place, the involved modules must be + <em>Cover compiled</em>. This means that some extra information is + added to the module before it is compiled into a binary which then + is loaded. The source file of the module is not affected and no + <c>.beam</c> file is created.</p> + <p>Each time a function in a Cover compiled module is called, + information about the call is added to an internal database of Cover. + The coverage analysis is performed by examining the contents of + the Cover database. The output <c>Answer</c> is determined by two + parameters, <c>Level</c> and <c>Analysis</c>.</p> + <list type="bulleted"> + <item> + <p><c>Level = module</c></p> + <p><c>Answer = {Module,Value}</c>, where <c>Module</c> is the module + name.</p> + </item> + <item> + <p><c>Level = function</c></p> + <p><c>Answer = [{Function,Value}]</c>, one tuple for each function in + the module. A function is specified by its module name <c>M</c>, + function name <c>F</c> and arity <c>A</c> as a tuple + <c>{M,F,A}</c>.</p> + </item> + <item> + <p><c>Level = clause</c></p> + <p><c>Answer = [{Clause,Value}]</c>, one tuple for each clause in + the module. A clause is specified by its module name <c>M</c>, + function name <c>F</c>, arity <c>A</c> and position in the function + definition <c>C</c> as a tuple <c>{M,F,A,C}</c>.</p> + </item> + <item> + <p><c>Level = line</c></p> + <p><c>Answer = [{Line,Value}]</c>, one tuple for each executable + line in the module. A line is specified by its module name <c>M</c> + and line number in the source file <c>N</c> as a tuple + <c>{M,N}</c>.</p> + </item> + <item> + <p><c>Analysis = coverage</c></p> + <p><c>Value = {Cov,NotCov}</c> where <c>Cov</c> is the number of + executable lines in the module, function, clause or line that have + been executed at least once and <c>NotCov</c> is the number of + executable lines that have not been executed.</p> + </item> + <item> + <p><c>Analysis = calls</c></p> + <p><c>Value = Calls</c> which is the number of times the module, + function, or clause has been called. In the case of line level + analysis, <c>Calls</c> is the number of times the line has been + executed.</p> + </item> + </list> + <p><em>Distribution</em></p> + <p>Cover can be used in a distributed Erlang system. One of the + nodes in the system must then be selected as the <em>main node</em>, and all Cover commands must be executed from this + node. The error reason <c>not_main_node</c> is returned if an + interface function is called on one of the remote nodes.</p> + <p>Use <c>cover:start/1</c> and <c>cover:stop/1</c> to add or + remove nodes. The same Cover compiled code will be loaded on each + node, and analysis will collect and sum up coverage data results + from all nodes.</p> + </description> + <funcs> + <func> + <name>start() -> {ok,Pid} | {error,Reason}</name> + <fsummary>Start Cover.</fsummary> + <type> + <v>Pid = pid()</v> + <v>Reason = {already_started,Pid}</v> + </type> + <desc> + <p>Starts the Cover server which owns the Cover internal database. + This function is called automatically by the other functions in + the module.</p> + </desc> + </func> + <func> + <name>start(Nodes) -> {ok,StartedNodes} | {error,not_main_node}</name> + <fsummary>Start Cover on remote nodes.</fsummary> + <type> + <v>Nodes = StartedNodes = [atom()]</v> + </type> + <desc> + <p>Starts a Cover server on the each of given nodes, and loads + all cover compiled modules.</p> + </desc> + </func> + <func> + <name>compile(ModFile) -> Result</name> + <name>compile(ModFile, Options) -> Result</name> + <name>compile_module(ModFile) -> Result</name> + <name>compile_module(ModFile, Options) -> Result</name> + <fsummary>Compile a module for Cover analysis.</fsummary> + <type> + <v>ModFile = Module | File</v> + <v> Module = atom()</v> + <v> File = string()</v> + <v>Options = [Option]</v> + <v> Option = {i,Dir} | {d,Macro} | {d,Macro,Value}</v> + <d>See <c>compile:file/2.</c></d> + <v>Result = {ok,Module} | {error,File} | {error,not_main_node}</v> + </type> + <desc> + <p>Compiles a module for Cover analysis. The module is given by its + module name <c>Module</c> or by its file name <c>File</c>. + The <c>.erl</c> extension may be omitted. If the module is + located in another directory, the path has to be specified.</p> + <p><c>Options</c> is a list of compiler options which defaults to + <c>[]</c>. Only options defining include file directories and + macros are passed to <c>compile:file/2</c>, everything else is + ignored.</p> + <p>If the module is successfully Cover compiled, the function + returns <c>{ok,Module}</c>. Otherwise the function returns + <c>{error,File}</c>. Errors and warnings are printed as they + occur.</p> + <p>Note that the internal database is (re-)initiated during + the compilation, meaning any previously collected coverage data + for the module will be lost.</p> + </desc> + </func> + <func> + <name>compile_directory() -> [Result] | {error,Reason}</name> + <name>compile_directory(Dir) -> [Result] | {error,Reason}</name> + <name>compile_directory(Dir, Options) -> [Result] | {error,Reason}</name> + <fsummary>Compile all modules in a directory for Cover analysis.</fsummary> + <type> + <v>Dir = string()</v> + <v>Options = [Option]</v> + <d>See <c>compile_module/1,2</c></d> + <v>Result = {ok,Module} | {error,File} | {error,not_main_node}</v> + <d>See <c>compile_module/1,2</c></d> + <v>Reason = eacces | enoent</v> + </type> + <desc> + <p>Compiles all modules (<c>.erl</c> files) in a directory + <c>Dir</c> for Cover analysis the same way as + <c>compile_module/1,2</c> and returns a list with the return + values.</p> + <p><c>Dir</c> defaults to the current working directory.</p> + <p>The function returns <c>{error,eacces}</c> if the directory is not + readable or <c>{error,enoent}</c> if the directory does not exist.</p> + </desc> + </func> + <func> + <name>compile_beam(ModFile) -> Result</name> + <fsummary>Compile a module for Cover analysis, using an existing beam.</fsummary> + <type> + <v>ModFile = Module | BeamFile</v> + <v> Module = atom()</v> + <v> BeamFile = string()</v> + <v>Result = {ok,Module} | {error,BeamFile} | {error,Reason}</v> + <v> Reason = non_existing | {no_abstract_code,BeamFile} | {encrypted_abstract_code,BeamFile} | {already_cover_compiled,no_beam_found,Module} | not_main_node</v> + </type> + <desc> + <p>Does the same as <c>compile/1,2</c>, but uses an existing + <c>.beam</c> file as base, i.e. the module is not compiled + from source. Thus <c>compile_beam/1</c> is faster than + <c>compile/1,2</c>.</p> + <p>Note that the existing <c>.beam</c> file must contain + <em>abstract code</em>, i.e. it must have been compiled with + the <c>debug_info</c> option. If not, the error reason + <c>{no_abstract_code,BeamFile}</c> is returned. + If the abstract code is encrypted, and no key is available + for decrypting it, the error reason + <c><![CDATA[{encrypted_abstract_code,BeamFile} is returned. <p>If only the module name (i.e. not the full name of the <c>.beam]]></c> file) is given to this function, the + <c>.beam</c> file is found by calling + <c>code:which(Module)</c>. If no <c>.beam</c> file is found, + the error reason <c>non_existing</c> is returned. If the + module is already cover compiled with <c>compile_beam/1</c>, + the <c>.beam</c> file will be picked from the same location + as the first time it was compiled. If the module is already + cover compiled with <c>compile/1,2</c>, there is no way to + find the correct <c>.beam</c> file, so the error reason + <c>{already_cover_compiled,no_beam_found,Module}</c> is + returned.</p> + <p><c>{error,BeamFile}</c> is returned if the compiled code + can not be loaded on the node.</p> + </desc> + </func> + <func> + <name>compile_beam_directory() -> [Result] | {error,Reason}</name> + <name>compile_beam_directory(Dir) -> [Result] | {error,Reason}</name> + <fsummary>Compile all .beam files in a directory for Cover analysis.</fsummary> + <type> + <v>Dir = string()</v> + <v>Result = See compile_beam/1</v> + <v>Reason = eacces | enoent</v> + </type> + <desc> + <p>Compiles all modules (<c>.beam</c> files) in a directory + <c>Dir</c> for Cover analysis the same way as + <c>compile_beam/1</c> and returns a list with the return + values.</p> + <p><c>Dir</c> defaults to the current working directory.</p> + <p>The function returns <c>{error,eacces}</c> if the directory is not + readable or <c>{error,enoent}</c> if the directory does not exist.</p> + </desc> + </func> + <func> + <name>analyse(Module) -> {ok,Answer} | {error,Error}</name> + <name>analyse(Module, Analysis) -> {ok,Answer} | {error,Error}</name> + <name>analyse(Module, Level) -> {ok,Answer} | {error,Error}</name> + <name>analyse(Module, Analysis, Level) -> {ok,Answer} | {error,Error}</name> + <fsummary>Analyse a Cover compiled module.</fsummary> + <type> + <v>Module = atom()</v> + <v>Analysis = coverage | calls</v> + <v>Level = line | clause | function | module</v> + <v>Answer = {Module,Value} | [{Item,Value}]</v> + <v> Item = Line | Clause | Function</v> + <v> Line = {M,N}</v> + <v> Clause = {M,F,A,C}</v> + <v> Function = {M,F,A}</v> + <v> M = F = atom()</v> + <v> N = A = C = integer()</v> + <v> Value = {Cov,NotCov} | Calls</v> + <v> Cov = NotCov = Calls = integer()</v> + <v>Error = {not_cover_compiled,Module} | not_main_node</v> + </type> + <desc> + <p>Performs analysis of a Cover compiled module <c>Module</c>, as + specified by <c>Analysis</c> and <c>Level</c> (see above), by + examining the contents of the internal database.</p> + <p><c>Analysis</c> defaults to <c>coverage</c> and <c>Level</c> + defaults to <c>function</c>.</p> + <p>If <c>Module</c> is not Cover compiled, the function returns + <c>{error,{not_cover_compiled,Module}}</c>.</p> + </desc> + </func> + <func> + <name>analyse_to_file(Module) -> </name> + <name>analyse_to_file(Module,Options) -> </name> + <name>analyse_to_file(Module, OutFile) -> </name> + <name>analyse_to_file(Module, OutFile, Options) -> {ok,OutFile} | {error,Error}</name> + <fsummary>Detailed coverage analysis of a Cover compiled module.</fsummary> + <type> + <v>Module = atom()</v> + <v>OutFile = string()</v> + <v>Options = [Option]</v> + <v>Option = html</v> + <v>Error = {not_cover_compiled,Module} | {file,File,Reason} | no_source_code_found | not_main_node</v> + <v> File = string()</v> + <v> Reason = term()</v> + </type> + <desc> + <p>Makes a copy <c>OutFile</c> of the source file for a module + <c>Module</c>, where it for each executable line is specified + how many times it has been executed.</p> + <p>The output file <c>OutFile</c> defaults to + <c>Module.COVER.out</c>, or <c>Module.COVER.html</c> if the + option <c>html</c> was used.</p> + <p>If <c>Module</c> is not Cover compiled, the function returns + <c>{error,{not_cover_compiled,Module}}</c>.</p> + <p>If the source file and/or the output file cannot be opened using + <c>file:open/2</c>, the function returns + <c>{error,{file,File,Reason}}</c> where <c>File</c> is the file + name and <c>Reason</c> is the error reason.</p> + <p>If the module was cover compiled from the <c>.beam</c> + file, i.e. using <c>compile_beam/1</c> or + <c>compile_beam_directory/0,1</c>, it is assumed that the + source code can be found in the same directory as the + <c>.beam</c> file, or in <c>../src</c> relative to that + directory. If no source code is found, + <c>,{error,no_source_code_found}</c> is returned.</p> + </desc> + </func> + <func> + <name>modules() -> [Module] | {error,not_main_node}</name> + <fsummary>Return all Cover compiled modules.</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns a list with all modules that are currently Cover + compiled.</p> + </desc> + </func> + <func> + <name>imported_modules() -> [Module] | {error,not_main_node}</name> + <fsummary>Return all modules for which there are imported data.</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns a list with all modules for which there are + imported data.</p> + </desc> + </func> + <func> + <name>imported() -> [File] | {error,not_main_node}</name> + <fsummary>Return all imported files.</fsummary> + <type> + <v>File = string()</v> + </type> + <desc> + <p>Returns a list with all imported files.</p> + </desc> + </func> + <func> + <name>which_nodes() -> [Node] | {error,not_main_node}</name> + <fsummary>Return all nodes that are part of the coverage analysis.</fsummary> + <type> + <v>Node = atom()</v> + </type> + <desc> + <p>Returns a list with all nodes that are part of the coverage + analysis. Note that the current node is not returned. This + node is always part of the analysis.</p> + </desc> + </func> + <func> + <name>is_compiled(Module) -> {file,File} | false | {error,not_main_node}</name> + <fsummary>Check if a module is Cover compiled.</fsummary> + <type> + <v>Module = atom()</v> + <v>Beam = string()</v> + </type> + <desc> + <p>Returns <c>{file,File}</c> if the module <c>Module</c> is + Cover compiled, or <c>false</c> otherwise. <c>File</c> is + the <c>.erl</c> file used by <c>cover:compile_module/1,2</c> + or the <c>.beam</c> file used by <c>compile_beam/1</c>.</p> + </desc> + </func> + <func> + <name>reset(Module) -></name> + <name>reset() -> ok | {error,not_main_node}</name> + <fsummary>Reset coverage data for Cover compiled modules.</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Resets all coverage data for a Cover compiled module + <c>Module</c> in the Cover database on all nodes. If the + argument is omitted, the coverage data will be reset for all + modules known by Cover.</p> + <p>If <c>Module</c> is not Cover compiled, the function returns + <c>{error,{not_cover_compiled,Module}}</c>.</p> + </desc> + </func> + <func> + <name>export(ExportFile)</name> + <name>export(ExportFile,Module) -> ok | {error,Reason}</name> + <fsummary>Reset coverage data for Cover compiled modules.</fsummary> + <type> + <v>ExportFile = string()</v> + <v>Module = atom()</v> + <v>Reason = {not_cover_compiled,Module} | {cant_open_file,ExportFile,Reason} | not_main_node</v> + </type> + <desc> + <p>Exports the current coverage data for <c>Module</c> to the + file <c>ExportFile</c>. It is recommended to name the + <c>ExportFile</c> with the extension <c>.coverdata</c>, since + other filenames can not be read by the web based interface to + cover.</p> + <p>If <c>Module</c> is not given, data for all Cover compiled + or earlier imported modules is exported.</p> + <p>This function is useful if coverage data from different + systems is to be merged.</p> + <p>See also <c>cover:import/1</c></p> + </desc> + </func> + <func> + <name>import(ExportFile) -> ok | {error,Reason}</name> + <fsummary>Reset coverage data for Cover compiled modules.</fsummary> + <type> + <v>ExportFile = string()</v> + <v>Reason = {cant_open_file,ExportFile,Reason} | not_main_node</v> + </type> + <desc> + <p>Imports coverage data from the file <c>ExportFile</c> + created with <c>cover:export/1,2</c>. Any analysis performed + after this will include the imported data.</p> + <p>Note that when compiling a module <em>all existing coverage data is removed</em>, including imported data. If a module is + already compiled when data is imported, the imported data is + <em>added</em> to the existing coverage data.</p> + <p>Coverage data from several export files can be imported + into one system. The coverage data is then added up when + analysing.</p> + <p>Coverage data for a module can not be imported from the + same file twice unless the module is first reset or + compiled. The check is based on the filename, so you can + easily fool the system by renaming your export file.</p> + <p>See also <c>cover:export/1,2</c></p> + </desc> + </func> + <func> + <name>stop() -> ok | {error,not_main_node}</name> + <fsummary>Stop Cover.</fsummary> + <desc> + <p>Stops the Cover server and unloads all Cover compiled code.</p> + </desc> + </func> + <func> + <name>stop(Nodes) -> ok | {error,not_main_node}</name> + <fsummary>Stop Cover on remote nodes.</fsummary> + <type> + <v>Nodes = [atom()]</v> + </type> + <desc> + <p>Stops the Cover server and unloads all Cover compiled code + on the given nodes. Data stored in the Cover database on the + remote nodes is fetched and stored on the main node.</p> + </desc> + </func> + </funcs> + + <section> + <title>SEE ALSO</title> + <p>code(3), compile(3)</p> + </section> +</erlref> + diff --git a/lib/tools/doc/src/cover_chapter.xml b/lib/tools/doc/src/cover_chapter.xml new file mode 100644 index 0000000000..b4f7919183 --- /dev/null +++ b/lib/tools/doc/src/cover_chapter.xml @@ -0,0 +1,490 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2001</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>cover</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>cover_chapter.xml</file> + </header> + + <section> + <title>Introduction</title> + <p>The module <c>cover</c> provides a set of functions for coverage + analysis of Erlang programs, counting how many times each + <seealso marker="#lines">executable line</seealso> is executed.</p> + <p>Coverage analysis can be used to verify test cases, making sure all + relevant code is covered, and may be helpful when looking for + bottlenecks in the code.</p> + </section> + + <section> + <title>Getting Started With Cover</title> + + <section> + <title>Example</title> + <p>Assume that a test case for the following program should be + verified:</p> + <code type="none"> +-module(channel). +-behaviour(gen_server). + +-export([start_link/0,stop/0]). +-export([alloc/0,free/1]). % client interface +-export([init/1,handle_call/3,terminate/2]). % callback functions + +start_link() -> + gen_server:start_link({local,channel},channel,[],[]). + +stop() -> + gen_server:call(channel,stop). + +%%%-Client interface functions------------------------------------------- + +alloc() -> + gen_server:call(channel,alloc). + +free(Channel) -> + gen_server:call(channel,{free,Channel}). + +%%%-gen_server callback functions---------------------------------------- + +init(_Arg) -> + {ok,channels()}. + +handle_call(stop,Client,Channels) -> + {stop,normal,ok,Channels}; + +handle_call(alloc,Client,Channels) -> + {Ch,Channels2} = alloc(Channels), + {reply,{ok,Ch},Channels2}; + +handle_call({free,Channel},Client,Channels) -> + Channels2 = free(Channel,Channels), + {reply,ok,Channels2}. + +terminate(_Reason,Channels) -> + ok. + +%%%-Internal functions--------------------------------------------------- + +channels() -> + [ch1,ch2,ch3]. + +alloc([Channel|Channels]) -> + {Channel,Channels}; +alloc([]) -> + false. + +free(Channel,Channels) -> + [Channel|Channels].</code> + <p>The test case is implemented as follows:</p> + <code type="none"> +-module(test). +-export([s/0]). + +s() -> + {ok,Pid} = channel:start_link(), + {ok,Ch1} = channel:alloc(), + ok = channel:free(Ch1), + ok = channel:stop().</code> + </section> + + <section> + <title>Preparation</title> + <p>First of all, Cover must be started. This spawns a process which + owns the Cover database where all coverage data will be stored.</p> + <pre> +1> <input>cover:start().</input> +{ok,<0.30.0>}</pre> + <p>To include other nodes in the coverage analysis, use + <c>start/1</c>. All cover compiled modules will then be loaded + on all nodes, and data from all nodes will be summed up when + analysing. For simplicity this example only involves the + current node.</p> + <p>Before any analysis can take place, the involved modules must be + <em>Cover compiled</em>. This means that some extra information is + added to the module before it is compiled into a binary which then + is <seealso marker="#loading">loaded</seealso>. The source file of + the module is not affected and no <c>.beam</c> file is created.</p> + <pre> +2> <input>cover:compile_module(channel).</input> +{ok,channel}</pre> + <p>Each time a function in the Cover compiled module <c>channel</c> + is called, information about the call will be added to the Cover + database. Run the test case:</p> + <pre> +3> <input>test:s().</input> +ok</pre> + <p>Cover analysis is performed by examining the contents of the Cover + database. The output is determined by two parameters, <c>Level</c> + and <c>Analysis</c>. <c>Analysis</c> is either <c>coverage</c> or + <c>calls</c> and determines the type of the analysis. <c>Level</c> + is either <c>module</c>, <c>function</c>, <c>clause</c>, or + <c>line</c> and determines the level of the analysis.</p> + </section> + + <section> + <title>Coverage Analysis</title> + <p>Analysis of type <c>coverage</c> is used to find out how much of + the code has been executed and how much has not been executed. + Coverage is represented by a tuple <c>{Cov,NotCov}</c>, where + <c>Cov</c> is the number of executable lines that have been executed + at least once and <c>NotCov</c> is the number of executable lines + that have not been executed.</p> + <p>If the analysis is made on module level, the result is given for + the entire module as a tuple <c>{Module,{Cov,NotCov}}</c>:</p> + <pre> +4> <input>cover:analyse(channel,coverage,module).</input> +{ok,{channel,{14,1}}}</pre> + <p>For <c>channel</c>, the result shows that 14 lines in the module + are covered but one line is not covered.</p> + <p>If the analysis is made on function level, the result is given as + a list of tuples <c>{Function,{Cov,NotCov}}</c>, one for each + function in the module. A function is specified by its module name, + function name and arity:</p> + <pre> +5> <input>cover:analyse(channel,coverage,function).</input> +{ok,[{{channel,start_link,0},{1,0}}, + {{channel,stop,0},{1,0}}, + {{channel,alloc,0},{1,0}}, + {{channel,free,1},{1,0}}, + {{channel,init,1},{1,0}}, + {{channel,handle_call,3},{5,0}}, + {{channel,terminate,2},{1,0}}, + {{channel,channels,0},{1,0}}, + {{channel,alloc,1},{1,1}}, + {{channel,free,2},{1,0}}]}</pre> + <p>For <c>channel</c>, the result shows that the uncovered line is in + the function <c>channel:alloc/1</c>.</p> + <p>If the analysis is made on clause level, the result is given as + a list of tuples <c>{Clause,{Cov,NotCov}}</c>, one for each + function clause in the module. A clause is specified by its module + name, function name, arity and position within the function + definition:</p> + <pre> +6> <input>cover:analyse(channel,coverage,clause).</input> +{ok,[{{channel,start_link,0,1},{1,0}}, + {{channel,stop,0,1},{1,0}}, + {{channel,alloc,0,1},{1,0}}, + {{channel,free,1,1},{1,0}}, + {{channel,init,1,1},{1,0}}, + {{channel,handle_call,3,1},{1,0}}, + {{channel,handle_call,3,2},{2,0}}, + {{channel,handle_call,3,3},{2,0}}, + {{channel,terminate,2,1},{1,0}}, + {{channel,channels,0,1},{1,0}}, + {{channel,alloc,1,1},{1,0}}, + {{channel,alloc,1,2},{0,1}}, + {{channel,free,2,1},{1,0}}]}</pre> + <p>For <c>channel</c>, the result shows that the uncovered line is in + the second clause of <c>channel:alloc/1</c>.</p> + <p>Finally, if the analysis is made on line level, the result is given + as a list of tuples <c>{Line,{Cov,NotCov}}</c>, one for each + executable line in the source code. A line is specified by its + module name and line number.</p> + <pre> +7> <input>cover:analyse(channel,coverage,line).</input> +{ok,[{{channel,9},{1,0}}, + {{channel,12},{1,0}}, + {{channel,17},{1,0}}, + {{channel,20},{1,0}}, + {{channel,25},{1,0}}, + {{channel,28},{1,0}}, + {{channel,31},{1,0}}, + {{channel,32},{1,0}}, + {{channel,35},{1,0}}, + {{channel,36},{1,0}}, + {{channel,39},{1,0}}, + {{channel,44},{1,0}}, + {{channel,47},{1,0}}, + {{channel,49},{0,1}}, + {{channel,52},{1,0}}]}</pre> + <p>For <c>channel</c>, the result shows that the uncovered line is + line number 49.</p> + </section> + + <section> + <title>Call Statistics</title> + <p>Analysis of type <c>calls</c> is used to find out how many times + something has been called and is represented by an integer + <c>Calls</c>.</p> + <p>If the analysis is made on module level, the result is given as a + tuple <c>{Module,Calls}</c>. Here <c>Calls</c> is the total number + of calls to functions in the module:</p> + <pre> +8> <input>cover:analyse(channel,calls,module).</input> +{ok,{channel,12}}</pre> + <p>For <c>channel</c>, the result shows that a total of twelve calls + have been made to functions in the module.</p> + <p>If the analysis is made on function level, the result is given as + a list of tuples <c>{Function,Calls}</c>. Here <c>Calls</c> is + the number of calls to each function:</p> + <pre> +9> <input>cover:analyse(channel,calls,function).</input> +{ok,[{{channel,start_link,0},1}, + {{channel,stop,0},1}, + {{channel,alloc,0},1}, + {{channel,free,1},1}, + {{channel,init,1},1}, + {{channel,handle_call,3},3}, + {{channel,terminate,2},1}, + {{channel,channels,0},1}, + {{channel,alloc,1},1}, + {{channel,free,2},1}]}</pre> + <p>For <c>channel</c>, the result shows that <c>handle_call/3</c> is + the most called function in the module (three calls). All other + functions have been called once.</p> + <p>If the analysis is made on clause level, the result is given as + a list of tuples <c>{Clause,Calls}</c>. Here <c>Calls</c> is + the number of calls to each function clause:</p> + <pre> +10> <input>cover:analyse(channel,calls,clause).</input> +{ok,[{{channel,start_link,0,1},1}, + {{channel,stop,0,1},1}, + {{channel,alloc,0,1},1}, + {{channel,free,1,1},1}, + {{channel,init,1,1},1}, + {{channel,handle_call,3,1},1}, + {{channel,handle_call,3,2},1}, + {{channel,handle_call,3,3},1}, + {{channel,terminate,2,1},1}, + {{channel,channels,0,1},1}, + {{channel,alloc,1,1},1}, + {{channel,alloc,1,2},0}, + {{channel,free,2,1},1}]}</pre> + <p>For <c>channel</c>, the result shows that all clauses have been + called once, except the second clause of <c>channel:alloc/1</c> + which has not been called at all.</p> + <p>Finally, if the analysis is made on line level, the result is given + as a list of tuples <c>{Line,Calls}</c>. Here <c>Calls</c> is + the number of times each line has been executed:</p> + <pre> +11> <input>cover:analyse(channel,calls,line).</input> +{ok,[{{channel,9},1}, + {{channel,12},1}, + {{channel,17},1}, + {{channel,20},1}, + {{channel,25},1}, + {{channel,28},1}, + {{channel,31},1}, + {{channel,32},1}, + {{channel,35},1}, + {{channel,36},1}, + {{channel,39},1}, + {{channel,44},1}, + {{channel,47},1}, + {{channel,49},0}, + {{channel,52},1}]}</pre> + <p>For <c>channel</c>, the result shows that all lines have been + executed once, except line number 49 which has not been executed at + all.</p> + </section> + + <section> + <title>Analysis to File</title> + <p>A line level calls analysis of <c>channel</c> can be written to + a file using <c>cover:analysis_to_file/1</c>:</p> + <pre> +12> <input>cover:analyse_to_file(channel).</input> +{ok,"channel.COVER.out"}</pre> + <p>The function creates a copy of <c>channel.erl</c> where it for + each executable line is specified how many times that line has been + executed. The output file is called <c>channel.COVER.out</c>.</p> + <pre> +File generated from channel.erl by COVER 2001-05-21 at 11:16:38 + +**************************************************************************** + + | -module(channel). + | -behaviour(gen_server). + | + | -export([start_link/0,stop/0]). + | -export([alloc/0,free/1]). % client interface + | -export([init/1,handle_call/3,terminate/2]). % callback functions + | + | start_link() -> + 1..| gen_server:start_link({local,channel},channel,[],[]). + | + | stop() -> + 1..| gen_server:call(channel,stop). + | + | %%%-Client interface functions------------------------------------ + | + | alloc() -> + 1..| gen_server:call(channel,alloc). + | + | free(Channel) -> + 1..| gen_server:call(channel,{free,Channel}). + | + | %%%-gen_server callback functions--------------------------------- + | + | init(_Arg) -> + 1..| {ok,channels()}. + | + | handle_call(stop,Client,Channels) -> + 1..| {stop,normal,ok,Channels}; + | + | handle_call(alloc,Client,Channels) -> + 1..| {Ch,Channels2} = alloc(Channels), + 1..| {reply,{ok,Ch},Channels2}; + | + | handle_call({free,Channel},Client,Channels) -> + 1..| Channels2 = free(Channel,Channels), + 1..| {reply,ok,Channels2}. + | + | terminate(_Reason,Channels) -> + 1..| ok. + | + | %%%-Internal functions-------------------------------------------- + | + | channels() -> + 1..| [ch1,ch2,ch3]. + | + | alloc([Channel|Channels]) -> + 1..| {Channel,Channels}; + | alloc([]) -> + 0..| false. + | + | free(Channel,Channels) -> + 1..| [Channel|Channels].</pre> + </section> + + <section> + <title>Conclusion</title> + <p>By looking at the results from the analyses, it can be deducted + that the test case does not cover the case when all channels are + allocated and <c>test.erl</c> should be extended accordingly. <br></br> + + Incidentally, when the test case is corrected a bug in <c>channel</c> + should indeed be discovered.</p> + <p>When the Cover analysis is ready, Cover is stopped and all Cover + compiled modules are <seealso marker="#loading">unloaded</seealso>. + The code for <c>channel</c> is now loaded as usual from a + <c>.beam</c> file in the current path.</p> + <pre> +13> <input>code:which(channel).</input> +cover_compiled +14> <input>cover:stop().</input> +ok +15> <input>code:which(channel).</input> +"./channel.beam"</pre> + </section> + </section> + + <section> + <title>Miscellaneous</title> + + <section> + <title>Performance</title> + <p>Execution of code in Cover compiled modules is slower and more + memory consuming than for regularly compiled modules. As the Cover + database contains information about each executable line in each + Cover compiled module, performance decreases proportionally to + the size and number of the Cover compiled modules.</p> + </section> + + <section> + <marker id="lines"></marker> + <title>Executable Lines</title> + <p>Cover uses the concept of <em>executable lines</em>, which is lines + of code containing an executable expression such as a matching or + a function call. A blank line or a line containing a comment, + function head or pattern in a <c>case</c>- or <c>receive</c> + statement is not executable.</p> + <p>In the example below, lines number 2,4,6,8 and 11 are executable + lines:</p> + <p></p> + <pre> +1: is_loaded(Module,Compiled) -> +2: case get_file(Module,Compiled) of +3: {ok,File} -> +4: case code:which(Module) of +5: ?TAG -> +6: {loaded,File}; +7: _ -> +8: unloaded +9: end; +10: false -> +11: false +12: end.</pre> + </section> + + <section> + <marker id="loading"></marker> + <title>Code Loading Mechanism</title> + <p>When a module is Cover compiled, it is also loaded using the normal + code loading mechanism of Erlang. This means that if a Cover + compiled module is re-loaded during a Cover session, for example + using <c>c(Module)</c>, it will no longer be Cover compiled.</p> + <p>Use <c>cover:is_compiled/1</c> or <c>code:which/1</c> to see if + a module is Cover compiled (and still loaded) or not.</p> + <p>When Cover is stopped, all Cover compiled modules are unloaded.</p> + </section> + </section> + + <section> + <title>Using the Web Based User Interface to Cover</title> + + <section> + <title>Introduction</title> + <p>To ease the use of Cover there is a web based user interface + to Cover called WebCover. WebCover is designed to be started + and used via WebTool. It is possible to Cover compile Erlang + modules and to generate printable Cover and Call analyses via + the web based user interface.</p> + </section> + + <section> + <title>Start the Web Based User Interface to Cover</title> + <p>To start WebCover you can either start WebTool, point a + browser to the start page of WebTool and start WebCover from + there, or you can use the <c>start_webtool</c> script to start + Webtool, WebCover and a browser. See WebTool documentation for + further information.</p> + <p>Currently WebCover is only compatible + with Internet Explorer and Netscape Navigator 4.0 and higher.</p> + </section> + + <section> + <title>Navigating WebCover</title> + <p>From the menu in the lefthand frame you can select the + <c>Nodes</c>, <c>Compile</c>, <c>Import</c> or <c>Result</c> + page.</p> + <p>From the <c>Nodes</c> page you can add remote nodes to + participate in the coverage analysis. Coverage data from all + involved nodes will then be merged during analysis.</p> + <p>From the <c>Compile</c> page you can Cover compile <c>.erl</c> + or <c>.beam</c> files.</p> + <p>From the <c>Import</c> page you can import coverage data from + a previous analysis. Imported data will then be merged with + the current coverage data. <em>Note</em> that it is only possible to + import files with the extension <c>.coverdata</c>.</p> + <p>From the <c>Result</c> page you can analyse, reset or export + coverage data.</p> + <p>Please follow the instructions on each page.</p> + </section> + </section> +</chapter> + diff --git a/lib/tools/doc/src/cprof.xml b/lib/tools/doc/src/cprof.xml new file mode 100644 index 0000000000..421ed7875a --- /dev/null +++ b/lib/tools/doc/src/cprof.xml @@ -0,0 +1,294 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2002</year> + <year>2007</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>cprof</title> + <prepared>Raimo Niskanen</prepared> + <responsible>nobody</responsible> + <docno></docno> + <approved>nobody</approved> + <checked></checked> + <date>2002-09-12</date> + <rev>PA1</rev> + <file>cprof.sgml</file> + </header> + <module>cprof</module> + <modulesummary>A simple Call Count Profiling Tool using breakpoints for minimal runtime performance impact.</modulesummary> + <description> + <p>The <c>cprof</c> module is used to profile a program + to find out how many times different functions are called. + Breakpoints similar to local call trace, but containing a + counter, are used to minimise runtime performance impact. + </p> + <p>Since breakpoints are used there is no need for special + compilation of any module to be profiled. For now these + breakpoints can only be set on BEAM code so <term id="BIF"></term>s + cannot be call count traced. + </p> + <p>The size of the call counters is the host machine word + size. One bit is used when pausing the counter, so the maximum + counter value for a 32-bit host is 2147483647. + </p> + <p>The profiling result is delivered as a term containing a + sorted list of entries, one per module. Each module entry + contains a sorted list of functions. The sorting order in both + cases is of decreasing call count. + </p> + <p>Call count tracing is very lightweight compared to other forms + of tracing since no trace message has to be generated. Some + measurements indicates performance degradation in the vicinity + of 10 percent. + <marker id="analyse"></marker> +</p> + </description> + <funcs> + <func> + <name>analyse() -> {AllCallCount, ModAnalysisList}</name> + <name>analyse(Limit) -> {AllCallCount, ModAnalysisList}</name> + <name>analyse(Mod) -> ModAnlysis</name> + <name>analyse(Mod, Limit) -> ModAnalysis</name> + <fsummary>Collect and analyse call counters.</fsummary> + <type> + <v>Limit = integer()</v> + <v>Mod = atom()</v> + <v>AllCallCount = integer()</v> + <v>ModAnalysisList = [ModAnalysis]</v> + <v>ModAnalysis = {Mod, ModCallCount, FuncAnalysisList}</v> + <v>ModCallCount = integer()</v> + <v>FuncAnalysisList = [{{Mod, Func, Arity}, FuncCallCount}]</v> + <v>Func = atom()</v> + <v>Arity = integer()</v> + <v>FuncCallCount = integer()</v> + </type> + <desc> + <p>Collects and analyses the call counters presently in the + node for either module <c>Mod</c>, or for all modules + (except <c>cprof</c> itself), and returns: </p> + <taglist> + <tag><c>FuncAnalysisList</c></tag> + <item>A list of tuples, one for each function in a module, in + decreasing <c>FuncCallCount</c> order.</item> + <tag><c>ModCallCount</c></tag> + <item>The sum of <c>FuncCallCount</c> values for all + functions in module <c>Mod</c>.</item> + <tag><c>AllCallCount</c></tag> + <item>The sum of <c>ModCallCount</c> values for all modules + concerned in <c>ModAnalysisList</c>.</item> + <tag><c>ModAnalysisList</c></tag> + <item>A list of tuples, one for each module except + <c>cprof</c>, in decreasing <c>ModCallCount</c> order.</item> + </taglist> + <p>If call counters are still running while + <c>analyse/0..2</c> is executing, you might get an + inconsistent result. This happens if the process executing + <c>analyse/0..2</c> gets scheduled out so some other process + can increment the counters that are being analysed, Calling + <c>pause()</c> before analysing takes care of the problem. + </p> + <p>If the <c>Mod</c> argument is given, the result contains a + <c>ModAnalysis</c> tuple for module <c>Mod</c> only, + otherwise the result contains one <c>ModAnalysis</c> tuple + for all modules returned from <c>code:all_loaded()</c> + except <c>cprof</c> itself. + </p> + <p>All functions with a <c>FuncCallCount</c> lower than + <c>Limit</c> are excluded from <c>FuncAnalysisList</c>. They + are still included in <c>ModCallCount</c>, though. + The default value for <c>Limit</c> is <c>1</c>. + <marker id="pause_0"></marker> +</p> + </desc> + </func> + <func> + <name>pause() -> integer()</name> + <fsummary>Pause running call count trace for all functions.</fsummary> + <desc> + <p>Pause call count tracing for all functions in all modules + and stop it for all functions in modules to be + loaded. This is the same as + <c>(pause({'_','_','_'})+stop({on_load}))</c>. + </p> + <p>See also + <seealso marker="#pause">pause/1..3</seealso> below. + <marker id="pause"></marker> +</p> + </desc> + </func> + <func> + <name>pause(FuncSpec) -> integer()</name> + <name>pause(Mod, Func) -> integer()</name> + <name>pause(Mod, Func, Arity) -> integer()</name> + <fsummary>Pause running call count trace for matching functions.</fsummary> + <type> + <v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v> + <v>Mod = atom()</v> + <v>Func = atom()</v> + <v>Arity = integer()</v> + <v>FS = term()</v> + </type> + <desc> + <p>Pause call counters for matching functions in matching + modules. The <c>FS</c> argument can be used to + specify the first argument to + <c>erlang:trace_pattern/3</c>. See erlang(3). + </p> + <p>The call counters for all matching functions that + has got call count breakpoints are paused at their current + count. + </p> + <p>Return the number of matching functions that can have + call count breakpoints, the same as + <c>start/0..3</c> with the same arguments would have + returned. + <marker id="restart"></marker> +</p> + </desc> + </func> + <func> + <name>restart() -> integer()</name> + <name>restart(FuncSpec) -> integer()</name> + <name>restart(Mod, Func) -> integer()</name> + <name>restart(Mod, Func, Arity) -> integer()</name> + <fsummary>Restart existing call counters for matching functions.</fsummary> + <type> + <v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v> + <v>Mod = atom()</v> + <v>Func = atom()</v> + <v>Arity = integer()</v> + <v>FS = term()</v> + </type> + <desc> + <p>Restart call counters for the matching functions in + matching modules that are call count traced. The <c>FS</c> + argument can be used to specify the first argument to + <c>erlang:trace_pattern/3</c>. See erlang(3). + </p> + <p>The call counters for all matching functions that has got + call count breakpoints are set to zero and running. + </p> + <p>Return the number of matching functions that can have + call count breakpoints, the same as + <c>start/0..3</c> with the same arguments would have + returned. + <marker id="start_0"></marker> +</p> + </desc> + </func> + <func> + <name>start() -> integer()</name> + <fsummary>Start call count tracing for all functions.</fsummary> + <desc> + <p>Start call count tracing for all functions in all modules, + and also for all functions in modules to be + loaded. This is the same as + <c>(start({'_','_','_'})+start({on_load}))</c>. + </p> + <p>See also + <seealso marker="#start">start/1..3</seealso> below. + <marker id="start"></marker> +</p> + </desc> + </func> + <func> + <name>start(FuncSpec) -> integer()</name> + <name>start(Mod, Func) -> integer()</name> + <name>start(Mod, Func, Arity) -> integer()</name> + <fsummary>Start call count tracing for matching functions.</fsummary> + <type> + <v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v> + <v>Mod = atom()</v> + <v>Func = atom()</v> + <v>Arity = integer()</v> + <v>FS = term()</v> + </type> + <desc> + <p>Start call count tracing for matching functions in matching + modules. The <c>FS</c> argument can be used to specify the + first argument to <c>erlang:trace_pattern/3</c>, for example + <c>on_load</c>. See erlang(3). + </p> + <p>Set call count breakpoints on the matching functions that + has no call count breakpoints. Call counters + are set to zero and running for all matching functions. + </p> + <p>Return the number of matching functions that has got + call count breakpoints. + <marker id="stop_0"></marker> +</p> + </desc> + </func> + <func> + <name>stop() -> integer()</name> + <fsummary>Stop call count tracing for all functions.</fsummary> + <desc> + <p>Stop call count tracing for all functions in all modules, + and also for all functions in modules to be + loaded. This is the same as + <c>(stop({'_','_','_'})+stop({on_load}))</c>. + </p> + <p>See also + <seealso marker="#stop">stop/1..3</seealso> below. + <marker id="stop"></marker> +</p> + </desc> + </func> + <func> + <name>stop(FuncSpec) -> integer()</name> + <name>stop(Mod, Func) -> integer()</name> + <name>stop(Mod, Func, Arity) -> integer()</name> + <fsummary>Stop call count tracing for matching functions.</fsummary> + <type> + <v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v> + <v>Mod = atom()</v> + <v>Func = atom()</v> + <v>Arity = integer()</v> + <v>FS = term()</v> + </type> + <desc> + <p>Stop call count tracing for matching functions in matching + modules. The <c>FS</c> argument can be used to specify the + first argument to <c>erlang:trace_pattern/3</c>, for example + <c>on_load</c>. See erlang(3). + </p> + <p>Remove call count breakpoints from the matching functions that + has call count breakpoints. + </p> + <p>Return the number of matching functions that can have + call count breakpoints, the same as + <c>start/0..3</c> with the same arguments would have + returned. + </p> + </desc> + </func> + </funcs> + + <section> + <title>See Also</title> + <p><seealso marker="eprof">eprof</seealso>(3), + <seealso marker="fprof">fprof</seealso>(3), + erlang(3), + <seealso marker="cprof_chapter">User's Guide</seealso></p> + </section> +</erlref> + diff --git a/lib/tools/doc/src/cprof_chapter.xml b/lib/tools/doc/src/cprof_chapter.xml new file mode 100644 index 0000000000..cf6a6f843a --- /dev/null +++ b/lib/tools/doc/src/cprof_chapter.xml @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2002</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>cprof - The Call Count Profiler</title> + <prepared>Raimo Niskanen</prepared> + <responsible>nobody</responsible> + <docno></docno> + <approved>nobody</approved> + <checked>no</checked> + <date>2002-09-11</date> + <rev>PA1</rev> + <file>cprof_chapter.xml</file> + </header> + <p><c>cprof</c> is a profiling tool that can be used to get a picture of + how often different functions in the system are called. + </p> + <p><c>cprof</c> uses breakpoints similar to local call trace, + but containing counters, to collect profiling + data. Therfore there is no need for special compilation of any + module to be profiled. + </p> + <p><c>cprof</c> presents all profiled modules in decreasing total + call count order, and for each module presents all profiled + functions also in decreasing call count order. A call count limit + can be specified to filter out all functions below the limit. + </p> + <p>Profiling is done in the following steps:</p> + <taglist> + <tag><c>cprof:start/0..3</c></tag> + <item>Starts profiling with zeroed call counters for specified + functions by setting call count breakpoints on them. </item> + <tag><c>Mod:Fun()</c></tag> + <item>Runs the code to be profiled.</item> + <tag><c>cprof:pause/0..3</c></tag> + <item>Pauses the call counters for specified functions. This minimises + the impact of code running in the background or in the shell + that disturbs the profiling. Call counters are automatically + paused when they "hit the ceiling" of the host machine word + size. For a 32 bit host the maximum counter value is + 2147483647.</item> + <tag><c>cprof:analyse/0..2</c></tag> + <item>Collects call counters and computes the result.</item> + <tag><c>cprof:restart/0..3</c></tag> + <item>Restarts the call counters from zero for specified + functions. Can be used to collect a new set of counters without + having to stop and start call count profiling.</item> + <tag><c>cprof:stop/0..3</c></tag> + <item>Stops profiling by removing call count breakpoints from + specified functions.</item> + </taglist> + <p>Functions can be specified as either all in the system, all in one + module, all arities of one function, one function, or all + functions in all modules not yet loaded. As for now, BIFs cannot + be call count traced. + </p> + <p>The analysis result can either be for all modules, or for one + module. In either case a call count limit can be given to filter + out the functions with a call count below the limit. The all + modules analysis does <em>not</em> contain the module <c>cprof</c> + itself, it can only be analysed by specifying it as a single + module to analyse. + </p> + <p>Call count tracing is very lightweight compared to other forms of + tracing since no trace message has to be generated. Some + measurements indicates performance degradations in the vicinity of + 10 percent. + </p> + <p>The following sections show some examples of profiling with + <c>cprof</c>. See also + <seealso marker="cprof">cprof(3)</seealso>. + </p> + + <section> + <title>Example: Background work</title> + <p>From the Erlang shell:</p> + <pre> +1> <input>cprof:start(), cprof:pause(). % Stop counters just after start</input> +3476 +2> <input>cprof:analyse().</input> +{30, + [{erl_eval,11, + [{{erl_eval,expr,3},3}, + {{erl_eval,'-merge_bindings/2-fun-0-',2},2}, + {{erl_eval,expand_module_name,2},1}, + {{erl_eval,merge_bindings,2},1}, + {{erl_eval,binding,2},1}, + {{erl_eval,expr_list,5},1}, + {{erl_eval,expr_list,3},1}, + {{erl_eval,exprs,4},1}]}, + {orddict,8, + [{{orddict,find,2},6}, + {{orddict,dict_to_list,1},1}, + {{orddict,to_list,1},1}]}, + {packages,7,[{{packages,is_segmented_1,1},6}, + {{packages,is_segmented,1},1}]}, + {lists,4,[{{lists,foldl,3},3},{{lists,reverse,1},1}]}]} +3> <input>cprof:analyse(cprof).</input> +{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]} +4> <input>cprof:stop().</input> +3476</pre> + <p>The example showed the background work that the shell performs + just to interpret the first command line. Most work is done by + <c>erl_eval</c> and <c>orddict</c>. + </p> + <p>What is captured in this example is the part of the work the + shell does while interpreting the command line that occurs + between the actual calls to <c>cprof:start()</c> and + <c>cprof:analyse()</c>. + </p> + </section> + + <section> + <title>Example: One module</title> + <p>From the Erlang shell:</p> + <pre> +1> <input>cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.</input> +1 +2> <input>cprof:analyse(calendar).</input> +{calendar,9, + [{{calendar,df,2},1}, + {{calendar,dm,1},1}, + {{calendar,dy,1},1}, + {{calendar,last_day_of_the_month1,2},1}, + {{calendar,last_day_of_the_month,2},1}, + {{calendar,is_leap_year1,1},1}, + {{calendar,is_leap_year,1},1}, + {{calendar,day_of_the_week,3},1}, + {{calendar,date_to_gregorian_days,3},1}]} +3> <input>cprof:stop().</input> +3271</pre> + <p>The example tells us that "Aktiebolaget LM Ericsson & Co" + was registered on a Monday (since the return value + of the first command is 1), and that the <c>calendar</c> module + needed 9 function calls to calculate that. + </p> + <p>Using <c>cprof:analyse()</c> in this example also shows + approximately the same background work as in the first example. + </p> + </section> + + <section> + <title>Example: In the code</title> + <p>Write a module:</p> + <pre> +-module(sort). + +-export([do/1]). + +do(N) -> + cprof:stop(), + cprof:start(), + do(N, []). + +do(0, L) -> + R = lists:sort(L), + cprof:pause(), + R; +do(N, L) -> + do(N-1, [random:uniform(256)-1 | L]).</pre> + <p>From the Erlang shell:</p> + <pre> +1> <input>c(sort).</input> +{ok,sort} +2> <input>l(random).</input> +{module,random} +3> <input>sort:do(1000).</input> +[0,0,1,1,1,1,1,1,2,2,2,3,3,3,3,3,4,4,4,5,5,5,5,6,6,6,6,6,6|...] +4> <input>cprof:analyse().</input> +{9050, + [{lists_sort,6047, + [{{lists_sort,merge3_2,6},923}, + {{lists_sort,merge3_1,6},879}, + {{lists_sort,split_2,5},661}, + {{lists_sort,rmerge3_1,6},580}, + {{lists_sort,rmerge3_2,6},543}, + {{lists_sort,merge3_12_3,6},531}, + {{lists_sort,merge3_21_3,6},383}, + {{lists_sort,split_2_1,6},338}, + {{lists_sort,rmerge3_21_3,6},299}, + {{lists_sort,rmerge3_12_3,6},205}, + {{lists_sort,rmerge2_2,4},180}, + {{lists_sort,rmerge2_1,4},171}, + {{lists_sort,merge2_1,4},127}, + {{lists_sort,merge2_2,4},121}, + {{lists_sort,mergel,2},79}, + {{lists_sort,rmergel,2},27}]}, + {random,2001, + [{{random,uniform,1},1000}, + {{random,uniform,0},1000}, + {{random,seed0,0},1}]}, + {sort,1001,[{{sort,do,2},1001}]}, + {lists,1,[{{lists,sort,1},1}]}]} +5> <input>cprof:stop().</input> +5369</pre> + <p>The example shows some details of how <c>lists:sort/1</c> + works. It used 6047 function calls in the module + <c>lists_sort</c> to complete the work. + </p> + <p>This time, since the shell was not involved, no other work was + done in the system during the profiling. If you retry the same + example with a freshly started Erlang emulator, but omit the + command <c>l(random)</c>, the analysis will show a lot more + function calls done by <c>code_server</c> and others to + automatically load the module <c>random</c>. + </p> + </section> +</chapter> + diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml new file mode 100644 index 0000000000..ae1033f2d0 --- /dev/null +++ b/lib/tools/doc/src/eprof.xml @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>eprof</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>eprof</module> + <modulesummary>A Time Profiling Tool for Erlang</modulesummary> + <description> + <p>The module <c>eprof</c> provides a set of functions for time + profiling of Erlang programs to find out how the execution time is + used. The profiling is done using the Erlang trace BIFs. Tracing of + local function calls for a specified set of processes is enabled when + profiling is begun, and disabled when profiling is stopped.</p> + <p>When using Eprof, expect a significant slowdown in program execution, + in most cases at least 100 percent.</p> + </description> + <funcs> + <func> + <name>start() -> {ok,Pid} | {error,Reason}</name> + <fsummary>Start Eprof.</fsummary> + <type> + <v>Pid = pid()</v> + <v>Reason = {already_started,Pid}</v> + </type> + <desc> + <p>Starts the Eprof server which owns the Eprof internal database.</p> + </desc> + </func> + <func> + <name>start_profiling(Rootset) -> profiling | error</name> + <name>profile(Rootset) -> profiling | error</name> + <fsummary>Start profiling.</fsummary> + <type> + <v>Rootset = [atom() | pid()]</v> + </type> + <desc> + <p>Starts profiling for the processes in <c>Rootset</c> (and any new + processes spawned from them). Information about activity in any + profiled process is stored in the Eprof database.</p> + <p><c>Rootset</c> is a list of pids and registered names.</p> + <p>The function returns <c>profiling</c> if tracing could be enabled + for all processes in <c>Rootset</c>, or <c>error</c> otherwise.</p> + </desc> + </func> + <func> + <name>stop_profiling() -> profiling_stopped | profiling_already_stopped</name> + <fsummary>Stop profiling.</fsummary> + <desc> + <p>Stops profiling started with <c>start_profiling/1</c> or + <c>profile/1</c>.</p> + </desc> + </func> + <func> + <name>profile(Rootset,Fun) -> {ok,Value} | {error,Reason} | error</name> + <name>profile(Rootset,Module,Function,Args) -> {ok,Value} | {error,Reason} | error</name> + <fsummary>Start profiling.</fsummary> + <type> + <v>Rootset = [atom() | pid()]</v> + <v>Fun = fun() -> term()</v> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + <v>Value = Reason = term()</v> + </type> + <desc> + <p>This function first spawns a process <c>P</c> which evaluates + <c>Fun()</c> or <c>apply(Module,Function,Args)</c>. Then, it + starts profiling for <c>P</c> and the processes in <c>Rootset</c> + (and any new processes spawned from them). Information about + activity in any profiled process is stored in the Eprof database.</p> + <p><c>Rootset</c> is a list of pids and registered names.</p> + <p>If tracing could be enabled for <c>P</c> and all processes in + <c>Rootset</c>, the function returns <c>{ok,Value}</c> when + <c>Fun()</c>/<c>apply</c> returns with the value <c>Value</c>, or + <c>{error,Reason}</c> if <c>Fun()</c>/<c>apply</c> fails with + exit reason <c>Reason</c>. Otherwise it returns <c>error</c> + immediately.</p> + <p>The programmer must ensure that the function given as argument + is truly synchronous and that no work continues after + the function has returned a value.</p> + </desc> + </func> + <func> + <name>analyse()</name> + <fsummary>Display profiling results per process.</fsummary> + <desc> + <p>Call this function when profiling has been stopped to display + the results per process, that is:</p> + <list type="bulleted"> + <item>how much time has been used by each process, and</item> + <item>in which function calls this time has been spent.</item> + </list> + <p>Time is shown as percentage of total time, not as absolute time.</p> + </desc> + </func> + <func> + <name>total_analyse()</name> + <fsummary>Display profiling results per function call.</fsummary> + <desc> + <p>Call this function when profiling has been stopped to display + the results per function call, that is in which function calls + the time has been spent.</p> + <p>Time is shown as percentage of total time, not as absolute time.</p> + </desc> + </func> + <func> + <name>log(File) -> ok</name> + <fsummary>Activate logging of <c>eprof</c>printouts.</fsummary> + <type> + <v>File = atom() | string()</v> + </type> + <desc> + <p>This function ensures that the results displayed by + <c>analyse/0</c> and <c>total_analyse/0</c> are printed both to + the file <c>File</c> and the screen.</p> + </desc> + </func> + <func> + <name>stop() -> stopped</name> + <fsummary>Stop Eprof.</fsummary> + <desc> + <p>Stops the Eprof server.</p> + </desc> + </func> + </funcs> +</erlref> + diff --git a/lib/tools/doc/src/erlang_mode.xml b/lib/tools/doc/src/erlang_mode.xml new file mode 100644 index 0000000000..72770898c2 --- /dev/null +++ b/lib/tools/doc/src/erlang_mode.xml @@ -0,0 +1,324 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2003</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Erlang mode for Emacs</title> + <prepared>Ingela Anderton</prepared> + <responsible></responsible> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>erlang.el</module> + <modulesummary>Erlang mode for Emacs </modulesummary> + <description> + <p>Possibly the most important feature of an editor designed for + programmers is the ability to indent a line of code in accordance + with the structure of the programming language. The Erlang mode + does, of course, provide this feature. The layout used is based + on the common use of the language. The mode also provides things as + syntax highlighting, electric commands, module name verification, + comment support including paragraph filling, skeletons, tags + support etc.</p> + <p>In the following descriptions the use of the word <em>Point</em> means: "Point can be seen as the position of the + cursor. More precisely, the point is the position between two + characters while the cursor is drawn over the character + following the point".</p> + </description> + + <section> + <title>Indent</title> + <p>The following command are directly available for indentation.</p> + <list type="bulleted"> + <item><em><c>TAB</c></em> (<c>erlang-indent-command</c>) - + Indents the current line of code. </item> + <item><em><c>M-C-\\</c></em> (<c>indent-region</c>) - Indents all + lines in the region. </item> + <item><em><c>M-l</c></em> (<c>indent-for-comment</c>) - Insert a + comment character to the right of the code on the line (if + any).</item> + </list> + <p>Lines containing comment are indented differently depending on + the number of %-characters used: </p> + <list type="bulleted"> + <item>Lines with one %-character is indented to the right of + the code. The column is specified by the variable + <c>comment-column</c>, by default column 48 is used.</item> + <item>Lines with two %-characters will be indented to the same + depth as code would have been in the same situation. </item> + <item>Lines with three of more %-characters are indented to the + left margin.</item> + <item><em><c>C-c C-q</c></em> (<c>erlang-indent-function</c>) - + Indents the current Erlang function. </item> + <item><em><c>M-x erlang-indent-clause RET</c></em> <br></br> + -Indent the + current Erlang clause.</item> + <item><em><c>M-x erlang-indent-current-buffer RET</c></em> - + Indent the entire buffer. </item> + </list> + </section> + + <section> + <title>Edit - Fill Comment </title> + <p>When editing normal text in text mode you can let Emacs reformat the + text by the <c>fill-paragraph</c> command. This command will not work + for comments since it will treat the comment characters as words.</p> + <p>The Erlang editing mode provides a command that knows about the + Erlang comment structure and can be used to fill text paragraphs + in comments. Ex:</p> + <code type="none"> + %% This is just a very simple test to show + %% how the Erlang fill + %% paragraph command works.</code> + <p>Clearly, the text is badly formatted. Instead of formatting this + paragraph line by line, let's try <c>erlang-fill-paragraph</c> by + pressing <em><c>M-q</c></em>. The result is:</p> + <code type="none"> + %% This is just a very simple test to show how the Erlang fill + %% paragraph command works.</code> + </section> + + <section> + <title>Edit - Comment/Uncomment Region </title> + <p><em><c>C-c C-c</c></em> will put comment characters at the + beginning of all lines in a marked region. If you want to have + two comment characters instead of one you can do <em><c>C-u 2 C-c C-c</c></em></p> + <p><em><c>C-c C-u</c></em> will undo a comment-region command. </p> + </section> + + <section> + <title>Edit - Moving the marker </title> + <list type="bulleted"> + <item><em><c>C-a M-a </c></em> + (<c>erlang-beginning-of-function</c>) - Move the point to the + beginning of the current or preceding Erlang function. With an + numeric argument (ex <em><c>C-u 2 C-a M-a</c></em>) the function + skips backwards over this many Erlang functions. Should the + argument be negative the point is moved to the beginning of a + function below the current function. </item> + <item><em><c>M-C-a </c></em> (<c>erlang-beginning-of-clause</c>) - As + above but move point to the beginning of the current or + preceding Erlang clause.</item> + <item><em><c>C-a M-e </c></em> (<c>erlang-end-of-function</c>) + - Move to the end of the current or following Erlang function. With + an numeric argument (ex <em><c>C-u 2 C-a M-e</c></em>) the function + skips backwards over this many Erlang functions. Should the argument + be negative the point is moved to the end of a function below + the current function.</item> + <item><em><c>M-C-e </c></em> (<c>erlang-end-of-clause</c>) - As above + but move point to the end of the current or following Erlang + clause.</item> + </list> + </section> + + <section> + <title>Edit - Marking </title> + <list type="bulleted"> + <item><em><c>C-c M-h</c></em> (<c>erlang-mark-function</c>) - Put the + region around the current Erlang function. The point is + placed in the beginning and the mark at the end of the + function.</item> + <item><em><c>M-C-h </c></em> (<c>erlang-mark-clause</c>) Put the region + around the current Erlang clause. The point is placed in the + beginning and the mark at the end of the function. </item> + </list> + </section> + + <section> + <title>Edit - Function Header Commands </title> + <list type="bulleted"> + <item><em><c>C-c C-j</c></em> (<c>erlang-generate-new-clause</c>) - + Create a new clause in the current Erlang function. The point is + placed between the parentheses of the argument list.</item> + <item><em><c>C-c C-y</c></em> (<c>erlang-clone-arguments</c>) - + Copy the function arguments of the preceding Erlang clause. This + command is useful when defining a new clause with almost the same + argument as the preceding.</item> + </list> + </section> + + <section> + <title>Edit - Arrows</title> + <list type="bulleted"> + <item> + <p><em><c>C-c C-a</c></em> (<c>erlang-align-arrows</c>) - + aligns arrows after clauses inside a region.</p> + <code type="none"> + Example: + + sum(L) -> sum(L, 0). + sum([H|T], Sum) -> sum(T, Sum + H); + sum([], Sum) -> Sum. + + becomes: + + sum(L) -> sum(L, 0). + sum([H|T], Sum) -> sum(T, Sum + H); + sum([], Sum) -> Sum."</code> + </item> + </list> + </section> + + <section> + <title>Syntax highlighting</title> + <p>The syntax highlighting can be activated from the Erlang menu. There + are four different alternatives:</p> + <list type="bulleted"> + <item>Off: Normal black and white display. + </item> + <item>Level 1: Function headers, reserved words, comments, + strings, quoted atoms, and character constants will be + colored. </item> + <item>Level 2: The above, attributes, Erlang bif:s, guards, and + words in comments enclosed in single quotes will be colored.</item> + <item>Level 3: The above, variables, records, and macros will + be colored. (This level is also known as the Christmas tree + level.) </item> + </list> + </section> + + <section> + <title>Tags</title> + <p>For the tag commands to work it requires that you have + generated a tag file. See <seealso marker="erlang_mode_chapter#tags">Erlang mode users guide</seealso></p> + <p></p> + <list type="bulleted"> + <item><em><c>M-. </c></em> (<c>find-tag</c>) - + Find a function definition. The default value is the function name + under the point. </item> + <item>Find Tag (<c>erlang-find-tag</c>) - Like the Elisp-function + `find-tag'. Capable of retrieving Erlang modules. Tags can be + given on the forms `tag', `module:', `module:tag'.</item> + <item><em><c>M-+</c></em> (<c>erlang-find-next-tag</c>) - Find the + next occurrence of tag.</item> + <item><em><c>M-TAB</c></em> (<c>erlang-complete-tag</c>) - + Perform completion on the tag entered in a tag search. + Completes to the set of names listed in the current tags table.</item> + <item>Tags aprops (<c>tags-apropos</c>) - Display list of all tags in + tags table REGEXP matches. </item> + <item><em><c>C-x t s</c></em> (<c>tags-search</c>) - Search + through all files listed in tags table for match for REGEXP. + Stops when a match is found.</item> + </list> + </section> + + <section> + <title>Skeletons</title> + <p>A skeleton is a piece of pre-written code that can be inserted into + the buffer. Erlang mode comes with a set of predefined skeletons. + The skeletons can be accessed either from the Erlang menu of + from commands named <c>tempo-template-erlang-*</c>, as the + skeletons is defined using the standard Emacs package "tempo". + Here follows a brief description of the available skeletons:</p> + <list type="bulleted"> + <item>Simple skeletons: If, Case, Receive, Receive After, + Receive Loop - Basic code constructs. + </item> + <item>Header elements: Module, Author - These commands insert + lines on the form <c>-module(</c>xxx<c>). </c> and + <c>-author('my@home').</c>. They can be used directly, but are + also used as part of the full headers described below.</item> + <item>Full Headers: Small (minimum requirement), Medium (with + fields for basic information about the module), and Large + Header (medium header with some extra layout structure).</item> + <item>Small Server - skeleton for a simple server not using + OTP.</item> + <item>Application - skeletons for the OTP application + behavior</item> + <item>Supervisor - skeleton for the OTP supervisor behavior</item> + <item>Supervisor Bridge - skeleton for the OTP supervisor bridge + behavior </item> + <item>gen_server - skeleton for the OTP gen_server + behavior</item> + <item>gen_event - skeleton for the OTP gen_event behavior</item> + <item>gen_fsm - skeleton for the OTP gen_fsm behavior</item> + <item>Library module - skeleton for a module that does not + implement a process.</item> + <item>Corba callback - skeleton for a Corba callback module.</item> + <item>Erlang test suite - skeleton for a callback module + for the erlang test server.</item> + </list> + </section> + + <section> + <title>Shell</title> + <list type="bulleted"> + <item>New shell (<c>erlang-shell</c>) - Starts a new Erlang shell.</item> + <item><em><c>C-c C-z,</c></em> (<c>erlang-shell-display </c>) - + Displays an Erlang shell, or starts a new one if there is no shell + started.</item> + </list> + </section> + + <section> + <title>Compile</title> + <list type="bulleted"> + <item><em><c>C-c C-k,</c></em> (<c>erlang-compile</c>) - + Compiles the Erlang module in the current buffer. + You can also use <em><c>C-u C-c C-k</c></em> + to debug compile the module with the debug options + <c>debug_info</c> and <c>export_all</c>.</item> + <item><em><c>C-c C-l,</c></em> (<c>erlang-compile-display</c>) - + Display compilation output.</item> + <item><em><c>C-u C-x`</c></em> Start parsing the compiler output from the + beginning. This command will place the point on the line where + the first error was found.</item> + <item><em><c>C-x`</c></em> (<c>erlang-next-error</c>) - Move the + point on to the next error. The buffer displaying the + compilation errors will be updated so that the current error + will be visible.</item> + </list> + </section> + + <section> + <title>Man</title> + <p>On unix you can view the manual pages in emacs. + In order to find the manual pages, the variable `erlang-root-dir' + should be bound to the name of the directory containing the Erlang + installation. The name should not include the final slash. + Practically, you should add a line on the following form to + your ~/.emacs,</p> + <code type="none"> + (setq erlang-root-dir "/the/erlang/root/dir/goes/here")</code> + </section> + + <section> + <title>Starting IMenu</title> + <list type="bulleted"> + <item><em><c>M-x imenu-add-to-menubar RET</c></em> - This + command will create the IMenu menu containing all the functions + in the current buffer.The command will ask you for a suitable + name for the menu. Not supported by Xemacs.</item> + </list> + </section> + + <section> + <title>Version</title> + <list type="bulleted"> + <item><em><c>M-x erlang-version RET</c></em> - + This command displays the version number of the Erlang editing mode. + Remember to always supply the version number when asking questions + about the Erlang mode.</item> + </list> + </section> +</erlref> + diff --git a/lib/tools/doc/src/erlang_mode_chapter.xml b/lib/tools/doc/src/erlang_mode_chapter.xml new file mode 100644 index 0000000000..cf043e3302 --- /dev/null +++ b/lib/tools/doc/src/erlang_mode_chapter.xml @@ -0,0 +1,251 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2003</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>The Erlang mode for Emacs</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>erlang_mode_chapter.xml</file> + </header> + + <section> + <title>Purpose</title> + <p>The purpose of this user guide is to introduce you to the + Erlang mode for Emacs and gives some relevant background + information of the functions and features. See also <seealso marker="erlang.el">Erlang mode reference manual</seealso> The + purpose of the Erlang mode itself is to facilitate the developing + process for the Erlang programmer.</p> + </section> + + <section> + <title>Pre-requisites</title> + <p>Basic knowledge of Emacs and Erlang/OTP. </p> + </section> + + <section> + <title>Elisp</title> + <p>There are two Elsip modules include in this tool package + for Emacs. There is erlang.el that defines the actual erlang mode + and there is erlang-start.el that makes some nice initializations.</p> + </section> + + <section> + <title>Setup on UNIX</title> + <p>To set up the Erlang Emacs mode on a UNIX systems, edit/create + the file <c>.emacs</c> in the your home directory.</p> + <p>Below is a complete example of what should be added to a user's + <c>.emacs</c> provided that OTP is installed in the directory + <c>/usr/local/otp </c>: </p> + <code type="none"><![CDATA[ + (setq load-path (cons "/usr/local/otp/lib/tools-<ToolsVer>/emacs" + load-path)) + (setq erlang-root-dir "/usr/local/otp") + (setq exec-path (cons "/usr/local/otp/bin" exec-path)) + (require 'erlang-start) + ]]></code> + </section> + + <section> + <title>Setup on Windows </title> + <p>To set up the Erlang Emacs mode on a Windows systems, + edit/create the file <c>.emacs</c>, the location of the file + depends on the configuration of the system. If the <em>HOME</em> + environment variable is set, Emacs will look for the + <c>.emacs</c> file in the directory indicated by the + <em>HOME</em> variable. If <em>HOME</em> is not set, Emacs + will look for the <c>.emacs</c> file in <c>C:\\ </c>.</p> + <p>Below is a complete example of what should be added to a user's + <c>.emacs</c> provided that OTP is installed in the directory + <c><![CDATA[C:\\Program Files\\erl<Ver>]]></c>: </p> + <code type="none"><![CDATA[ + (setq load-path (cons "C:/Program Files/erl<Ver>/lib/tools-<ToolsVer>/emacs" + load-path)) + (setq erlang-root-dir "C:/Program Files/erl<Ver>") + (setq exec-path (cons "C:/Program Files/erl<Ver>/bin" exec-path)) + (require 'erlang-start) + ]]></code> + <note> + <p>In .emacs, the slash character "/" can be used as path + separator. But if you decide to use the backslash character "\\", + please not that you must use double backslashes, since they are + treated as escape characters by Emacs.</p> + </note> + </section> + + <section> + <title>Indentation</title> + <p>The "Oxford Advanced Learners Dictionary of Current English" says the + following about the word "indent":</p> + <quote> + <p>"start (a line of print or writing) farther from + the margin than the others".</p> + </quote> + <p>The Erlang mode does, of course, provide this feature. The layout + used is based on the common use of the language.</p> + <p>It is strongly recommend to use this feature and avoid to indent lines + in a nonstandard way. Some motivations are:</p> + <list type="bulleted"> + <item>Code using the same layout is easy to read and maintain. </item> + <item>Since several features of Erlang mode is based on the + standard layout they might not work correctly if a nonstandard layout + is used. </item> + </list> + <p>The indentation features can be used to reindent large sections + of a file. If some lines use nonstandard indentation they will + be reindented.</p> + </section> + + <section> + <title>Editing</title> + <list type="bulleted"> + <item><em><c>M-x erlang-mode RET</c></em> - This command activates + the Erlang major mode for the current buffer. When this + mode is active the mode line contain the word "Erlang".</item> + </list> + <p>When the Erlang mode is correctly installed, it is + automatically activated when a file ending in <c>.erl</c> or + <c>.hrl</c> is opened in Emacs.</p> + <p>When a file is saved the name in the <c>-module().</c> line is + checked against the file name. Should they mismatch Emacs can + change the module specifier so that it matches the file name. + By default, the user is asked before the change is performed.</p> + <p>An "electric" command is a character that in addition to just + inserting the character performs some type of action. For + example the ";" character is typed in a situation where is ends + a function clause a new function header is generated. The electric + commands are as follows: </p> + <list type="bulleted"> + <item><em><c>erlang-electric-comma</c></em> - Insert a comma + character and possibly a new indented line. </item> + <item><em><c>erlang-electric-semicolon</c></em> - Insert a + semicolon character and possibly a prototype for the next line.</item> + <item><em><c>erlang-electric-gt</c></em> - "Insert a '>'-sign + and possible a new indented line.</item> + </list> + <p>To disable all electric commands set the variable + <c>erlang-electric-commands</c> to the empty list. In short, + place the following line in your <c>.emacs</c>-file:</p> + <code type="none"> + (setq erlang-electric-commands '())</code> + </section> + + <section> + <title>Syntax highlighting</title> + <p>It is possible for Emacs to use colors when displaying a buffer. By + "syntax highlighting", we mean that syntactic components, for example + keywords and function names, will be colored.</p> + <p>The basic idea of syntax highlighting is to make the structure of a + program clearer. For example, the highlighting will make it easier to + spot simple bugs. Have not you ever written a variable in lower-case + only? With syntax highlighting a variable will colored while atoms + will be shown with the normal text color.</p> + </section> + + <section> + <marker id="tags"></marker> + <title>Tags</title> + <p>Tags is a standard Emacs package used to record information + about source files in large development projects. In addition to + listing the files of a project, a tags file normally contains + information about all functions and variables that are defined. + By far, the most useful command of the tags system is its ability + to find the definition of functions in any file in the project. + However the Tags system is not limited to this feature, for + example, it is possible to do a text search in all files in a + project, or to perform a project-wide search and replace.</p> + <p>In order to use the Tags system a file named <c>TAGS</c> must be + created. The file can be seen as a database over all functions, + records, and macros in all files in the project. The + <c>TAGS</c> file can be created using two different methods for + Erlang. The first is the standard Emacs utility "etags", the + second is by using the Erlang module <c>tags</c>.</p> + </section> + + <section> + <title>Etags</title> + <p><c>etags</c> is a program that is part of the Emacs + distribution. It is normally executed from a command line, like + a unix shell or a DOS box.</p> + <p>The <c>etags</c> program of fairly modern versions of Emacs and XEmacs + has native support for Erlang. To check if your version does include + this support, issue the command <c>etags --help</c> at a the command + line prompt. At the end of the help text there is a list of supported + languages. Unless Erlang is a member of this list I suggest that you + should upgrade to a newer version of Emacs.</p> + <p>As seen in the help text -- unless you have not upgraded your + Emacs yet (well, what are you waiting around here for? Off you go and + upgrade!) -- <c>etags</c> associate the file extensions <c>.erl</c> + and <c>.hrl</c> with Erlang.</p> + <p>Basically, the <c>etags</c> utility is ran using the following form:</p> + <code type="none"> + etags file1.erl file2.erl</code> + <p>This will create a file named <c>TAGS</c> in the current directory.</p> + <p>The <c>etags</c> utility can also read a list of files from its + standard input by supplying a single dash in place of the file + names. This feature is useful when a project consists of a + large number of files. The standard UNIX command <c>find</c> + can be used to generate the list of files, e.g:</p> + <code type="none"> + find . -name "*.[he]rl" -print | etags -</code> + <p>The above line will create a <c>TAGS</c> file covering all the + Erlang source files in the current directory, and in the + subdirectories below.</p> + <p>Please see the GNU Emacs Manual and the etags man page for more + info.</p> + </section> + + <section> + <title>Shell</title> + <p>The look and feel on an Erlang shell inside Emacs should be the + same as in a normal Erlang shell. There is just one major + difference, the cursor keys will actually move the cursor around + just like in any normal Emacs buffer. The command line history + can be accessed by the following commands: </p> + <list type="bulleted"> + <item><em><c>C-up </c></em> or <em><c>M-p </c></em> + (<c>comint-previous-input</c>) - + Move to the previous line in the input history.</item> + <item><em><c>C-down </c></em> or <em><c>M-n </c></em> + (<c>comint-next-input</c>) - Move to the next line in the + input history.</item> + </list> + <p>If the Erlang shell buffer would be killed the command line + history is saved to a file. The command line history is + automatically retrieved when a new Erlang shell is started.</p> + </section> + + <section> + <title>Compilation</title> + <p>The classic edit-compile-bugfix cycle for Erlang is to edit the + source file in an editor, save it to a file and switch to an + Erlang shell. In the shell the compilation command is given. + Should the compilation fail you have to bring out the editor and + locate the correct line.</p> + <p>With the Erlang editing mode the entire edit-compile-bugfix cycle can + be performed without leaving Emacs. Emacs can order Erlang to compile + a file and it can parse the error messages to automatically place the + point on the erroneous lines.</p> + </section> +</chapter> + diff --git a/lib/tools/doc/src/fascicules.xml b/lib/tools/doc/src/fascicules.xml new file mode 100644 index 0000000000..0678195e07 --- /dev/null +++ b/lib/tools/doc/src/fascicules.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE fascicules SYSTEM "fascicules.dtd"> + +<fascicules> + <fascicule file="part" href="part_frame.html" entry="no"> + User's Guide + </fascicule> + <fascicule file="ref_man" href="ref_man_frame.html" entry="yes"> + Reference Manual + </fascicule> + <fascicule file="part_notes" href="part_notes_frame.html" entry="no"> + Release Notes + </fascicule> + <fascicule file="" href="../../../../doc/print.html" entry="no"> + Off-Print + </fascicule> +</fascicules> + diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml new file mode 100644 index 0000000000..8babf50033 --- /dev/null +++ b/lib/tools/doc/src/fprof.xml @@ -0,0 +1,911 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2001</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>fprof</title> + <prepared>Raimo Niskanen</prepared> + <responsible>nobody</responsible> + <docno></docno> + <approved>nobody</approved> + <checked></checked> + <date>2001-08-13</date> + <rev>PA1</rev> + <file>fprof.sgml</file> + </header> + <module>fprof</module> + <modulesummary>A Time Profiling Tool using trace to file for minimal runtime performance impact.</modulesummary> + <description> + <p>This module is used to profile a program + to find out how the execution time is used. + Trace to file is used to minimize + runtime performance impact. + </p> + <p>The <c>fprof</c> module uses tracing to collect profiling data, + hence there is no need for special compilation of any module to + be profiled. When it starts tracing, <c>fprof</c> will erase all + previous tracing in the node and set the necessary trace flags + on the profiling target processes as well as local call trace on + all functions in all loaded modules and all modules to be loaded. + <c>fprof</c> erases all tracing in the node when it stops tracing. + </p> + <p><c>fprof</c> presents both <em>own time</em> i.e how much time a + function has used for its own execution, and + <em>accumulated time</em> i.e including called functions. + All presented times are + collected using trace timestamps. <c>fprof</c> tries to collect + cpu time timestamps, if the host machine OS supports it. + Therefore the times may be wallclock times and OS scheduling will + randomly strike all called functions in a presumably fair way. + </p> + <p>If, however, the profiling time is short, and the host machine + OS does not support high resolution cpu time measurements, some + few OS schedulings may show up as ridiculously long execution + times for functions doing practically nothing. An example of a + function more or less just composing a tuple in about 100 times + the normal execution time has been seen, and when the tracing + was repeated, the execution time became normal. + </p> + <p>Profiling is essentially done in 3 steps:</p> + <taglist> + <tag><c>1</c></tag> + <item>Tracing; to file, as mentioned in the previous + paragraph. The trace contains entries for function calls, + returns to function, process scheduling, other process related + (spawn, etc) events, and garbage collection. All trace entries + are timestamped.</item> + <tag><c>2</c></tag> + <item>Profiling; the trace file is read, the execution call + stack is simulated, and raw profile data is calculated from + the simulated call stack and the trace timestamps. The profile + data is stored in the <c>fprof</c> server state. During this + step the trace data may be dumped in text format to file or + console. </item> + <tag><c>3</c></tag> + <item>Analysing; the raw profile data is sorted, filtered and + dumped in text format either to file or console. The text + format intended to be both readable for a human reader, as + well as parsable with the standard erlang parsing tools.</item> + </taglist> + <p>Since <c>fprof</c> uses trace to file, the runtime performance + degradation is minimized, but still far from negligible, + especially for programs that use the filesystem heavily by + themselves. Where you place the trace file is also important, + e.g on Solaris <c>/tmp</c> is usually a good choice since it is + essentially a RAM disk, while any NFS (network) mounted disk is + a bad idea. + </p> + <p><c>fprof</c> can also skip the file step and trace to a tracer + process that does the profiling in runtime. + <marker id="start"></marker> +</p> + </description> + <funcs> + <func> + <name>start() -> {ok, Pid} | {error, {already_started, Pid}}</name> + <fsummary>Starts the <c>fprof</c> server.</fsummary> + <type> + <v>Pid = pid()</v> + </type> + <desc> + <p>Starts the <c>fprof</c> server. + </p> + <p>Note that it seldom + needs to be started explicitly since it is automatically + started by the functions that need a running server. + <marker id="stop"></marker> +</p> + </desc> + </func> + <func> + <name>stop() -> ok</name> + <fsummary>Same as <c>stop(normal)</c>.</fsummary> + <desc> + <p>Same as <c>stop(normal)</c>.</p> + </desc> + </func> + <func> + <name>stop(Reason) -> ok</name> + <fsummary>Stops the <c>fprof</c> server.</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Stops the <c>fprof</c> server. + </p> + <p>The supplied <c>Reason</c> becomes the exit reason for the + server process. Default Any + <c>Reason</c> other than <c>kill</c> sends a request to the + server and waits for it to clean up, reply and exit. If + <c>Reason</c> is <c>kill</c>, the server is bluntly killed. + </p> + <p>If the <c>fprof</c> server is not running, this + function returns immediately with the same return value. + </p> + <note> + <p>When the <c>fprof</c> server is stopped the + collected raw profile data is lost.</p> + </note> + <marker id="apply"></marker> + </desc> + </func> + <func> + <name>apply(Func, Args) -> term()</name> + <fsummary>Same as <c>apply(Func, Args, [])</c>.</fsummary> + <type> + <v>Func = function() | {Module, Function}</v> + <v>Args = [term()]</v> + <v>Module = atom()</v> + <v>Function = atom()</v> + </type> + <desc> + <p>Same as <c>apply(Func, Args, [])</c>.</p> + </desc> + </func> + <func> + <name>apply(Module, Function, Args) -> term()</name> + <fsummary>Same as <c>apply({Module, Function}, Args, [])</c>.</fsummary> + <type> + <v>Args = [term()]</v> + <v>Module = atom()</v> + <v>Function = atom()</v> + </type> + <desc> + <p>Same as <c>apply({Module, Function}, Args, [])</c>.</p> + </desc> + </func> + <func> + <name>apply(Func, Args, OptionList) -> term()</name> + <fsummary>Calls <c>erlang:apply(Func, Args)</c>surrounded by<c>trace([start | OptionList])</c>and<c>trace(stop)</c>.</fsummary> + <type> + <v>Func = function() | {Module, Function}</v> + <v>Args = [term()]</v> + <v>OptionList = [Option]</v> + <v>Module = atom()</v> + <v>Function = atom()</v> + <v>Option = continue | start | {procs, PidList} | TraceStartOption</v> + </type> + <desc> + <p>Calls <c>erlang:apply(Func, Args)</c> surrounded by + <c>trace([start, ...])</c> and + <c>trace(stop)</c>. + </p> + <p>Some effort is made to keep the trace clean from unnecessary + trace messages; tracing is started and stopped from a spawned + process while the <c>erlang:apply/2</c> call is made in the + current process, only surrounded by <c>receive</c> and + <c>send</c> statements towards the trace starting + process. The trace starting process exits when not needed + any more. + </p> + <p>The <c>TraceStartOption</c> is any option allowed for + <c>trace/1</c>. The options + <c>[start, {procs, [self() | PidList]} | OptList]</c> + are given to <c>trace/1</c>, where <c>OptList</c> is + <c>OptionList</c> with <c>continue</c>, <c>start</c> + and <c>{procs, _}</c> options removed. + </p> + <p>The <c>continue</c> option inhibits the call to + <c>trace(stop)</c> and leaves it up to the caller to stop + tracing at a suitable time.</p> + </desc> + </func> + <func> + <name>apply(Module, Function, Args, OptionList) -> term()</name> + <fsummary>Same as <c>apply({Module, Function}, Args, OptionList)</c>.</fsummary> + <type> + <v>Module = atom()</v> + <v>Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Same as + <c>apply({Module, Function}, Args, OptionList)</c>. + </p> + <p><c>OptionList</c> is an option list allowed for + <c>apply/3</c>. + <marker id="trace"></marker> +</p> + </desc> + </func> + <func> + <name>trace(start, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>trace([start, {file, Filename}])</c>.</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>trace([start, {file, Filename}])</c>.</p> + </desc> + </func> + <func> + <name>trace(verbose, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>trace([start, verbose, {file, Filename}])</c>.</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>trace([start, verbose, {file, Filename}])</c>.</p> + </desc> + </func> + <func> + <name>trace(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>trace([{OptionName, OptionValue}])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>OptionValue = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>trace([{OptionName, OptionValue}])</c>.</p> + </desc> + </func> + <func> + <name>trace(verbose) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>trace([start, verbose])</c>.</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>trace([start, verbose])</c>.</p> + </desc> + </func> + <func> + <name>trace(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>trace([OptionName])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>trace([OptionName])</c>.</p> + </desc> + </func> + <func> + <name>trace({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>trace([{OptionName, OptionValue}])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>OptionValue = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>trace([{OptionName, OptionValue}])</c>.</p> + </desc> + </func> + <func> + <name>trace([Option]) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Starts or stops tracing.</fsummary> + <type> + <v>Option = start | stop | {procs, PidSpec} | {procs, [PidSpec]} | verbose | {verbose, bool()} | file | {file, Filename} | {tracer, Tracer}</v> + <v>PidSpec = pid() | atom()</v> + <v>Tracer = pid() | port()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Starts or stops tracing. + </p> + <p><c>PidSpec</c> and <c>Tracer</c> are used in calls to + <c>erlang:trace(PidSpec, true, [{tracer, Tracer} | Flags])</c>, and <c>Filename</c> is used to call + <c>dbg:trace_port(file, Filename)</c>. Please see the + appropriate documentation.</p> + <p>Option description:</p> + <taglist> + <tag><c>stop</c></tag> + <item>Stops a running <c>fprof</c> trace and clears all tracing + from the node. Either option <c>stop</c> or <c>start</c> must be + specified, but not both.</item> + <tag><c>start</c></tag> + <item>Clears all tracing from the node and starts a new + <c>fprof</c> trace. Either option <c>start</c> or + <c>stop</c> must be specified, but not both.</item> + <tag><c>verbose</c>| <c>{verbose, bool()}</c></tag> + <item>The options <c>verbose</c> or <c>{verbose, true}</c> + adds some trace flags that <c>fprof</c> does not need, but + that may be interesting for general debugging + purposes. This option is only + allowed with the <c>start</c> option.</item> + <tag><c>cpu_time</c>| <c>{cpu_time, bool()}</c></tag> + <item>The options <c>cpu_time</c> or <c>{cpu_time, true></c> + makes the timestamps in the trace be in CPU time instead + of wallclock time which is the default. This option is + only allowed with the <c>start</c> option.</item> + <tag><c>{procs, PidSpec}</c>| <c>{procs, [PidSpec]}</c></tag> + <item>Specifies which processes that shall be traced. If + this option is not given, the calling process is + traced. All processes spawned by the traced processes are + also traced. + This option is only allowed with the <c>start</c> option.</item> + <tag><c>file</c>| <c>{file, Filename}</c></tag> + <item>Specifies the filename of the trace. + If the option <c>file</c> is given, or none of these + options are given, the file <c>"fprof.trace"</c> is used. + This option is only allowed with the <c>start</c> option, + but not with the <c>{tracer, Tracer}</c> option.</item> + <tag><c>{tracer, Tracer}</c></tag> + <item>Specifies that trace to process or port shall be done + instead of trace to file. + This option is only allowed with the <c>start</c> option, + but not with the <c>{file, Filename}</c> option.</item> + </taglist> + <marker id="profile"></marker> + </desc> + </func> + <func> + <name>profile() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>profile([])</c>.</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>profile([])</c>.</p> + </desc> + </func> + <func> + <name>profile(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>profile([{OptionName, OptionValue}])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>OptionValue = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>profile([{OptionName, OptionValue}])</c>.</p> + </desc> + </func> + <func> + <name>profile(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>profile([OptionName])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>profile([OptionName])</c>.</p> + </desc> + </func> + <func> + <name>profile({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>profile([{OptionName, OptionValue}])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>OptionValue = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>profile([{OptionName, OptionValue}])</c>.</p> + </desc> + </func> + <func> + <name>profile([Option]) -> ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Compiles a trace into raw profile data held by the <c>fprof</c> server.</fsummary> + <type> + <v>Option = file | {file, Filename} | dump | {dump, Dump} | append | start | stop</v> + <v>Dump = pid() | Dumpfile | []</v> + <v>Tracer = pid()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Compiles a trace into raw profile data held by the + <c>fprof</c> server. + </p> + <p><c>Dumpfile</c> is used to call <c>file:open/2</c>, + and <c>Filename</c> is used to call + <c>dbg:trace_port(file, Filename)</c>. Please see the + appropriate documentation.</p> + <p>Option description:</p> + <taglist> + <tag><c>file</c>| <c>{file, Filename}</c></tag> + <item>Reads the file <c>Filename</c> and creates raw + profile data that is stored in RAM by the + <c>fprof</c> server. If the option <c>file</c> is + given, or none of these options are given, the file + <c>"fprof.trace"</c> is read. The call will return when + the whole trace has been + read with the return value <c>ok</c> if successful. + This option is not allowed with the <c>start</c> or + <c>stop</c> options.</item> + <tag><c>dump</c>| <c>{dump, Dump}</c></tag> + <item>Specifies the destination for the trace text dump. If + this option is not given, no dump is generated, if it is + <c>dump</c> the destination will be the + caller's group leader, otherwise the destination + <c>Dump</c> is either the pid of an I/O device or + a filename. And, finally, if the filename is <c>[]</c> - + <c>"fprof.dump"</c> is used instead. + This option is not allowed with the <c>stop</c> option.</item> + <tag><c>append</c></tag> + <item>Causes the trace text dump to be appended to the + destination file. + This option is only allowed with the + <c>{dump, Dumpfile}</c> option.</item> + <tag><c>start</c></tag> + <item>Starts a tracer process that profiles trace data in + runtime. The call will return immediately with the return + value <c>{ok, Tracer}</c> if successful. + This option is not allowed with the <c>stop</c>, + <c>file</c> or <c>{file, Filename}</c> options.</item> + <tag><c>stop</c></tag> + <item>Stops the tracer process that profiles trace data in + runtime. The return value will be value <c>ok</c> if successful. + This option is not allowed with the <c>start</c>, + <c>file</c> or <c>{file, Filename}</c> options.</item> + </taglist> + <marker id="analyse"></marker> + </desc> + </func> + <func> + <name>analyse() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>analyse([])</c>.</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>analyse([])</c>.</p> + </desc> + </func> + <func> + <name>analyse(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>analyse([{OptionName, OptionValue}])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>OptionValue = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>analyse([{OptionName, OptionValue}])</c>.</p> + </desc> + </func> + <func> + <name>analyse(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>analyse([OptionName])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as <c>analyse([OptionName])</c>.</p> + </desc> + </func> + <func> + <name>analyse({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Same as <c>analyse([{OptionName, OptionValue}])</c>.</fsummary> + <type> + <v>OptionName = atom()</v> + <v>OptionValue = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Same as + <c>analyse([{OptionName, OptionValue}])</c>.</p> + </desc> + </func> + <func> + <name>analyse([Option]) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name> + <fsummary>Analyses raw profile data in the <c>fprof</c> server.</fsummary> + <type> + <v>Option = dest | {dest, Dest} | append | {cols, Cols} | callers | {callers, bool()} | no_callers | {sort, SortSpec} | totals | {totals, bool()} | details | {details, bool()} | no_details</v> + <v>Dest = pid() | Destfile</v> + <v>Cols = integer() >= 80</v> + <v>SortSpec = acc | own</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Analyses raw profile data in the + <c>fprof</c> server. If called while there is no raw + profile data available, <c>{error, no_profile}</c> is + returned. + </p> + <p><c>Destfile</c> is used to call <c>file:open/2</c>. + Please see the appropriate documentation.</p> + <p>Option description:</p> + <taglist> + <tag><c>dest</c>| <c>{dest, Dest}</c></tag> + <item>Specifies the destination for the analysis. If + this option is not given or it is <c>dest</c>, + the destination will be the caller's group leader, + otherwise the destination <c>Dest</c> is either + the <c>pid()</c> of an I/O device or a filename. + And, finally, if the filename is <c>[]</c> - + <c>"fprof.analysis"</c> is used instead.</item> + <tag><c>append</c></tag> + <item>Causes the analysis to be appended to the + destination file. + This option is only allowed with the + <c>{dest, Destfile}</c> option.</item> + <tag><c>{cols, Cols}</c></tag> + <item>Specifies the number of columns in the analysis text. + If this option is not given the number of columns is set + to 80.</item> + <tag><c>callers</c>| <c>{callers, true}</c></tag> + <item>Prints callers and called information in the + analysis. This is the default.</item> + <tag><c>{callers, false}</c>| <c>no_callers</c></tag> + <item>Suppresses the printing of callers and called + information in the analysis.</item> + <tag><c>{sort, SortSpec}</c></tag> + <item>Specifies if the analysis should be sorted according + to the ACC column, which is the default, or the OWN + column. See + <seealso marker="#analysis">Analysis Format</seealso> below.</item> + <tag><c>totals</c>| <c>{totals, true}</c></tag> + <item>Includes a section containing call statistics + for all calls regardless of process, in the analysis.</item> + <tag><c>{totals, false}</c></tag> + <item>Supresses the totals section in the analysis, which is + the default.</item> + <tag><c>details</c>| <c>{details, true}</c></tag> + <item>Prints call statistics for each process in the + analysis. This is the default.</item> + <tag><c>{details, false}</c>| <c>no_details</c></tag> + <item>Suppresses the call statistics for each process from + the analysis.</item> + </taglist> + </desc> + </func> + </funcs> + + <section> + <marker id="analysis"></marker> + <title>Analysis format</title> + <p>This section describes the output format of the analyse + command. See <seealso marker="#analyse">analyse/0</seealso>. + </p> + <p>The format is parsable with the standard Erlang parsing tools + <c>erl_scan</c> and <c>erl_parse</c>, <c>file:consult/1</c> or + <c>io:read/2</c>. The parse format is not explained here - it + should be easy for the interested to try it out. Note that some + flags to <c>analyse/1</c> will affect the format. + </p> + <p>The following example was run on OTP/R8 on Solaris 8, all OTP + internals in this example are very version dependent. + </p> + <p>As an example, we will use the following function, that you may + recognise as a slightly modified benchmark function from the + manpage file(3):</p> + <code type="none"><![CDATA[ +-module(foo). +-export([create_file_slow/2]). + +create_file_slow(Name, N) when integer(N), N >= 0 -> + {ok, FD} = + file:open(Name, [raw, write, delayed_write, binary]), + if N > 256 -> + ok = file:write(FD, + lists:map(fun (X) -> <<X:32/unsigned>> end, + lists:seq(0, 255))), + ok = create_file_slow(FD, 256, N); + true -> + ok = create_file_slow(FD, 0, N) + end, + ok = file:close(FD). + +create_file_slow(FD, M, M) -> + ok; +create_file_slow(FD, M, N) -> + ok = file:write(FD, <<M:32/unsigned>>), + create_file_slow(FD, M+1, N).]]></code> + <p>Let us have a look at the printout after running:</p> + <pre> +1> <input>fprof:apply(foo, create_file_slow, [junk, 1024]).</input> +2> <input>fprof:profile().</input> +3> <input>fprof:analyse().</input></pre> + <p>The printout starts with:</p> + <pre> +%% Analysis results: +{ analysis_options, + [{callers, true}, + {sort, acc}, + {totals, false}, + {details, true}]}. + +% CNT ACC OWN +[{ totals, 9627, 1691.119, 1659.074}]. %%%</pre> + <p>The CNT column shows the total number of function calls that + was found in the trace. In the ACC column is the total time of + the trace from first timestamp to last. And in the OWN + column is the sum of the execution time in functions found in the + trace, not including called functions. In this case it is very + close to the ACC time since the emulator had practically nothing + else to do than to execute our test program. + </p> + <p>All time values in the printout are in milliseconds. + </p> + <p>The printout continues:</p> + <pre> +% CNT ACC OWN +[{ "<0.28.0>", 9627,undefined, 1659.074}]. %%</pre> + <p>This is the printout header of one process. The printout + contains only this one process since we did <c>fprof:apply/3</c> + which traces only the current process. Therefore the CNT and + OWN columns perfectly matches the totals above. The ACC column is + undefined since summing the ACC times of all calls in the process + makes no sense - you would get something like the ACC value from + totals above multiplied by the average depth of the call stack, + or something. + </p> + <p>All paragraphs up to the next process header only concerns + function calls within this process. + </p> + <p>Now we come to something more interesting:</p> + <pre> +{[{undefined, 0, 1691.076, 0.030}], + { {fprof,apply_start_stop,4}, 0, 1691.076, 0.030}, % + [{{foo,create_file_slow,2}, 1, 1691.046, 0.103}, + {suspend, 1, 0.000, 0.000}]}. + +{[{{fprof,apply_start_stop,4}, 1, 1691.046, 0.103}], + { {foo,create_file_slow,2}, 1, 1691.046, 0.103}, % + [{{file,close,1}, 1, 1398.873, 0.019}, + {{foo,create_file_slow,3}, 1, 249.678, 0.029}, + {{file,open,2}, 1, 20.778, 0.055}, + {{lists,map,2}, 1, 16.590, 0.043}, + {{lists,seq,2}, 1, 4.708, 0.017}, + {{file,write,2}, 1, 0.316, 0.021}]}. </pre> + <p>The printout consists of one paragraph per called function. The + function <em>marked</em> with '%' is the one the paragraph + concerns - <c>foo:create_file_slow/2</c>. Above the marked + function are the <em>calling</em> functions - those that has + called the marked, and below are those <em>called</em> by the + marked function. + </p> + <p>The paragraphs are per default sorted in decreasing order of + the ACC column for the marked function. The calling list and + called list within one paragraph are also per default sorted in + decreasing order of their ACC column. + </p> + <p>The columns are: CNT - the number of times the function + has been called, ACC - the time spent in the + function including called functions, and OWN - the + time spent in the function not including called + functions. + </p> + <p>The rows for the <em>calling</em> functions contain statistics + for the <em>marked</em> function with the constraint that only + the occasions when a call was made from the <em>row's</em> + function to the <em>marked</em> function are accounted for. + </p> + <p>The row for the <em>marked</em> function simply contains the + sum of all <em>calling</em> rows. + </p> + <p>The rows for the <em>called</em> functions contains statistics + for the <em>row's</em> function with the constraint that only the + occasions when a call was made from the <em>marked</em> to the + <em>row's</em> function are accounted for. + </p> + <p>So, we see that <c>foo:create_file_slow/2</c> used very little + time for its own execution. It spent most of its time in + <c>file:close/1</c>. The function <c>foo:create_file_slow/3</c> + that writes 3/4 of the file contents is the second biggest time + thief. + </p> + <p>We also see that the call to <c>file:write/2</c> that writes + 1/4 of the file contents takes very little time in itself. What + takes time is to build the data (<c>lists:seq/2</c> and + <c>lists:map/2</c>). + </p> + <p>The function 'undefined' that has called + <c>fprof:apply_start_stop/4</c> is an unknown function because that + call was not recorded in the trace. It was only recorded + that the execution returned from + <c>fprof:apply_start_stop/4</c> to some other function above in + the call stack, or that the process exited from there. + </p> + <p>Let us continue down the printout to find:</p> + <pre> +{[{{foo,create_file_slow,2}, 1, 249.678, 0.029}, + {{foo,create_file_slow,3}, 768, 0.000, 23.294}], + { {foo,create_file_slow,3}, 769, 249.678, 23.323}, % + [{{file,write,2}, 768, 220.314, 14.539}, + {suspend, 57, 6.041, 0.000}, + {{foo,create_file_slow,3}, 768, 0.000, 23.294}]}. </pre> + <p>If you compare with the code you will see there also that + <c>foo:create_file_slow/3</c> was called only from + <c>foo:create_file_slow/2</c> and itself, and called only + <c>file:write/2</c>, note the number of calls to + <c>file:write/2</c>. But here we see that <c>suspend</c> was + called a few times. This is a pseudo function that indicates + that the process was suspended while executing in + <c>foo:create_file_slow/3</c>, and since there is no + <c>receive</c> or <c>erlang:yield/0</c> in the code, it must be + Erlang scheduling suspensions, or the trace file driver + compensating for large file write operations (these are regarded + as a schedule out followed by a schedule in to the same process). + </p> + <p></p> + <p>Let us find the <c>suspend</c> entry:</p> + <pre> +{[{{file,write,2}, 53, 6.281, 0.000}, + {{foo,create_file_slow,3}, 57, 6.041, 0.000}, + {{prim_file,drv_command,4}, 50, 4.582, 0.000}, + {{prim_file,drv_get_response,1}, 34, 2.986, 0.000}, + {{lists,map,2}, 10, 2.104, 0.000}, + {{prim_file,write,2}, 17, 1.852, 0.000}, + {{erlang,port_command,2}, 15, 1.713, 0.000}, + {{prim_file,drv_command,2}, 22, 1.482, 0.000}, + {{prim_file,translate_response,2}, 11, 1.441, 0.000}, + {{prim_file,'-drv_command/2-fun-0-',1}, 15, 1.340, 0.000}, + {{lists,seq,4}, 3, 0.880, 0.000}, + {{foo,'-create_file_slow/2-fun-0-',1}, 5, 0.523, 0.000}, + {{erlang,bump_reductions,1}, 4, 0.503, 0.000}, + {{prim_file,open_int_setopts,3}, 1, 0.165, 0.000}, + {{prim_file,i32,4}, 1, 0.109, 0.000}, + {{fprof,apply_start_stop,4}, 1, 0.000, 0.000}], + { suspend, 299, 32.002, 0.000}, % + [ ]}.</pre> + <p>We find no particulary long suspend times, so no function seems + to have waited in a receive statement. Actually, + <c>prim_file:drv_command/4</c> contains a receive statement, but + in this test program, the message lies in the process receive + buffer when the receive statement is entered. We also see that + the total suspend time for the test run is small. + </p> + <p>The <c>suspend</c> pseudo function has got an OWN time of + zero. This is to prevent the process total OWN time from + including time in suspension. Whether suspend time is really ACC + or OWN time is more of a philosophical question. + </p> + <p>Now we look at another interesting pseudo function, + <c>garbage_collect</c>:</p> + <pre> +{[{{prim_file,drv_command,4}, 25, 0.873, 0.873}, + {{prim_file,write,2}, 16, 0.692, 0.692}, + {{lists,map,2}, 2, 0.195, 0.195}], + { garbage_collect, 43, 1.760, 1.760}, % + [ ]}.</pre> + <p>Here we see that no function distinguishes itself considerably, + which is very normal. + </p> + <p>The <c>garbage_collect</c> pseudo function has not got an OWN + time of zero like <c>suspend</c>, instead it is equal to the ACC + time. + </p> + <p>Garbage collect often occurs while a process is suspended, but + <c>fprof</c> hides this fact by pretending that the suspended + function was first unsuspended and then garbage + collected. Otherwise the printout would show + <c>garbage_collect</c> being called from <c>suspend</c> but not + not which function that might have caused the garbage + collection. + </p> + <p>Let us now get back to the test code:</p> + <pre> +{[{{foo,create_file_slow,3}, 768, 220.314, 14.539}, + {{foo,create_file_slow,2}, 1, 0.316, 0.021}], + { {file,write,2}, 769, 220.630, 14.560}, % + [{{prim_file,write,2}, 769, 199.789, 22.573}, + {suspend, 53, 6.281, 0.000}]}. </pre> + <p>Not unexpectedly, we see that <c>file:write/2</c> was called + from <c>foo:create_file_slow/3</c> and + <c>foo:create_file_slow/2</c>. The number of calls in each case as + well as the used time are also just confirms the previous results. + </p> + <p>We see that <c>file:write/2</c> only calls + <c>prim_file:write/2</c>, but let us refrain from digging into the + internals of the kernel application. + </p> + <p>But, if we nevertheless <em>do</em> dig down we find + the call to the linked in driver that does the file operations + towards the host operating system:</p> + <pre> +{[{{prim_file,drv_command,4}, 772, 1458.356, 1456.643}], + { {erlang,port_command,2}, 772, 1458.356, 1456.643}, % + [{suspend, 15, 1.713, 0.000}]}. </pre> + <p>This is 86 % of the total run time, and as we saw before it + is the close operation the absolutely biggest contributor. We + find a comparison ratio a little bit up in the call stack:</p> + <pre> +{[{{prim_file,close,1}, 1, 1398.748, 0.024}, + {{prim_file,write,2}, 769, 174.672, 12.810}, + {{prim_file,open_int,4}, 1, 19.755, 0.017}, + {{prim_file,open_int_setopts,3}, 1, 0.147, 0.016}], + { {prim_file,drv_command,2}, 772, 1593.322, 12.867}, % + [{{prim_file,drv_command,4}, 772, 1578.973, 27.265}, + {suspend, 22, 1.482, 0.000}]}. </pre> + <p>The time for file operations in the linked in driver + distributes itself as 1 % for open, 11 % for write and 87 % for + close. All data is probably buffered in the operating system + until the close. + </p> + <p>The unsleeping reader may notice that the ACC times for + <c>prim_file:drv_command/2</c> and + <c>prim_file:drv_command/4</c> is not equal between the + paragraphs above, even though it is easy to believe that + <c>prim_file:drv_command/2</c> is just a passthrough function. + </p> + <p>The missing time can be found in the paragraph + for <c>prim_file:drv_command/4</c> where it is evident that not + only <c>prim_file:drv_command/2</c> is called but also a fun: + </p> + <pre> +{[{{prim_file,drv_command,2}, 772, 1578.973, 27.265}], + { {prim_file,drv_command,4}, 772, 1578.973, 27.265}, % + [{{erlang,port_command,2}, 772, 1458.356, 1456.643}, + {{prim_file,'-drv_command/2-fun-0-',1}, 772, 87.897, 12.736}, + {suspend, 50, 4.582, 0.000}, + {garbage_collect, 25, 0.873, 0.873}]}. </pre> + <p>And some more missing time can be explained by the fact that + <c>prim_file:open_int/4</c> both calls + <c>prim_file:drv_command/2</c> directly as well as through + <c>prim_file:open_int_setopts/3</c>, which complicates the + picture. + </p> + <pre> +{[{{prim_file,open,2}, 1, 20.309, 0.029}, + {{prim_file,open_int,4}, 1, 0.000, 0.057}], + { {prim_file,open_int,4}, 2, 20.309, 0.086}, % + [{{prim_file,drv_command,2}, 1, 19.755, 0.017}, + {{prim_file,open_int_setopts,3}, 1, 0.360, 0.032}, + {{prim_file,drv_open,2}, 1, 0.071, 0.030}, + {{erlang,list_to_binary,1}, 1, 0.020, 0.020}, + {{prim_file,i32,1}, 1, 0.017, 0.017}, + {{prim_file,open_int,4}, 1, 0.000, 0.057}]}. +. +. +. +{[{{prim_file,open_int,4}, 1, 0.360, 0.032}, + {{prim_file,open_int_setopts,3}, 1, 0.000, 0.016}], + { {prim_file,open_int_setopts,3}, 2, 0.360, 0.048}, % + [{suspend, 1, 0.165, 0.000}, + {{prim_file,drv_command,2}, 1, 0.147, 0.016}, + {{prim_file,open_int_setopts,3}, 1, 0.000, 0.016}]}. </pre> + </section> + + <section> + <title>Notes</title> + <p>The actual supervision of execution times is in itself a + CPU intensive activity. A message is written on the trace file + for every function call that is made by the profiled code. + </p> + <p>The ACC time calculation is sometimes difficult to make + correct, since it is difficult to define. This happens + especially when a function occurs in several instances in the + call stack, for example by calling itself perhaps through other + functions and perhaps even non-tail recursively. + </p> + <p>To produce sensible results, <c>fprof</c> tries not to charge + any function more than once for ACC time. The instance highest + up (with longest duration) in the call stack is chosen. + </p> + <p>Sometimes a function may unexpectedly waste a lot (some 10 ms + or more depending on host machine OS) of OWN (and ACC) time, even + functions that does practically nothing at all. The problem may + be that the OS has chosen to schedule out the + Erlang runtime system process for a while, and if the OS does + not support high resolution cpu time measurements + <c>fprof</c> will use wallclock time for its calculations, and + it will appear as functions randomly burn virtual machine time.</p> + </section> + + <section> + <title>See Also</title> + <p>dbg(3), <seealso marker="eprof">eprof</seealso>(3), erlang(3), + io(3), + <seealso marker="fprof_chapter">Tools User's Guide</seealso></p> + </section> +</erlref> + diff --git a/lib/tools/doc/src/fprof_chapter.xml b/lib/tools/doc/src/fprof_chapter.xml new file mode 100644 index 0000000000..3f40d93f40 --- /dev/null +++ b/lib/tools/doc/src/fprof_chapter.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2001</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>fprof - The File Trace Profiler</title> + <prepared>Raimo Niskanen</prepared> + <responsible>nobody</responsible> + <docno></docno> + <approved>nobody</approved> + <checked>no</checked> + <date>2001-08-14</date> + <rev>PA1</rev> + <file>fprof_chapter.xml</file> + </header> + <p><c>fprof</c> is a profiling tool that can be used to get a picture of + how much processing time different functions consumes and in which + processes. + </p> + <p><c>fprof</c> uses tracing with timestamps to collect profiling + data. Therfore there is no need for special compilation of any + module to be profiled. + </p> + <p><c>fprof</c> presents wall clock times from the host machine OS, + with the assumption that OS scheduling will randomly load the + profiled functions in a fair way. Both <em>own time</em> i.e the + time used by a function for its own execution, and + <em>accumulated time</em> i.e execution time including called + functions. + </p> + <p>Profiling is essentially done in 3 steps:</p> + <taglist> + <tag><c>1</c></tag> + <item>Tracing; to file, as mentioned in the previous paragraph.</item> + <tag><c>2</c></tag> + <item>Profiling; the trace file is read and raw profile data is + collected into an internal RAM storage on the node. During + this step the trace data may be dumped in text format to file + or console.</item> + <tag><c>3</c></tag> + <item>Analysing; the raw profile data is sorted and dumped + in text format either to file or console.</item> + </taglist> + <p>Since <c>fprof</c> uses trace to file, the runtime performance + degradation is minimized, but still far from negligible, + especially not for programs that use the filesystem heavily + by themselves. Where you place the trace file is also important, + e.g on Solaris <c>/tmp</c> is usually a good choice, + while any NFS mounted disk is a lousy choice. + </p> + <p>Fprof can also skip the file step and trace to a tracer process + of its own that does the profiling in runtime. + </p> + <p>The following sections show some examples of how to profile with + Fprof. See also the reference manual + <seealso marker="fprof">fprof(3)</seealso>. + </p> + + <section> + <title>Profiling from the source code</title> + <p>If you can edit and recompile the source code, it is convenient + to insert <c>fprof:trace(start)</c> and + <c>fprof:trace(stop)</c> before and after the code to be + profiled. All spawned processes are also traced. If you want + some other filename than the default try + <c>fprof:trace(start, "my_fprof.trace")</c>. + </p> + <p>Then read the trace file and create the raw profile data with + <c>fprof:profile()</c>, or perhaps + <c>fprof:profile(file, "my_fprof.trace")</c> for non-default + filename. + </p> + <p>Finally create an informative table dumped on the console with + <c>fprof:analyse()</c>, or on file with + <c>fprof:analyse(dest, [])</c>, or perhaps even + <c>fprof:analyse([{dest, "my_fprof.analysis"}, {cols, 120}])</c> + for a wider listing on non-default filename. + </p> + <p>See the <seealso marker="fprof">fprof(3)</seealso> manual page + for more options and arguments to the functions + <seealso marker="fprof#trace">trace</seealso>, + <seealso marker="fprof#profile">profile</seealso> + and + <seealso marker="fprof#analyse">analyse</seealso>. + </p> + </section> + + <section> + <title>Profiling a function</title> + <p>If you have one function that does the task that you want to + profile, and the function returns when the profiling should + stop, it is convenient to use + <c>fprof:apply(Module, Function, Args)</c> and related for the + tracing step. + </p> + <p>If the tracing should continue after the function returns, for + example if it is a start function that spawns processes to be + profiled, you can use + <c>fprof:apply(M, F, Args, [continue | OtherOpts])</c>. + The tracing has to be stopped at a suitable later time using + <c>fprof:trace(stop)</c>. + </p> + </section> + + <section> + <title>Immediate profiling</title> + <p>It is also possible to trace immediately into the profiling + process that creates the raw profile data, that is to short + circuit the tracing and profiling steps so that the filesystem + is not used. + </p> + <p>Do something like this:</p> + <pre> +{ok, Tracer} = fprof:profile(start), +fprof:trace([start, {tracer, Tracer}]), +%% Code to profile +fprof:trace(stop);</pre> + <p>This puts less load on the filesystem, but much more on the + Erlang runtime system. + </p> + </section> +</chapter> + diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml new file mode 100644 index 0000000000..12877994de --- /dev/null +++ b/lib/tools/doc/src/instrument.xml @@ -0,0 +1,432 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1998</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>instrument</title> + <prepared>Arndt Jonasson</prepared> + <responsible>Torbjörn Johnsson</responsible> + <docno>1</docno> + <approved>Björn Gustavsson</approved> + <checked></checked> + <date>98-04-01</date> + <rev>PA1</rev> + <file>instrument.sgml</file> + </header> + <module>instrument</module> + <modulesummary>Analysis and Utility Functions for Instrumentation</modulesummary> + <description> + <p>The module <c>instrument</c> contains support for studying the resource + usage in an Erlang runtime system. Currently, only the allocation of memory can + be studied.</p> + <note> + <p>Note that this whole module is experimental, and the representations + used as well as the functionality is likely to change in the future.</p> + <p>The <c>instrument</c> module interface was slightly changed in + Erlang/OTP R9C.</p> + </note> + <p>To start an Erlang runtime system with instrumentation, use the + <c>+Mi*</c> set of command-line arguments to the <c>erl</c> command (see + the erts_alloc(3) and erl(1) man pages).</p> + <p>The basic object of study in the case of memory allocation is a memory + allocation map. A memory allocation map contains a list of descriptors + for each allocated memory block. Currently, a descriptor is a 4-tuple</p> + <pre> + {TypeNo, Address, Size, PidDesc} </pre> + <p>where <c>TypeNo</c> is the memory block type number, <c>Address</c> + is its place in memory, and <c>Size</c> is its size, in bytes. + <c>PidDesc</c> is either a tuple <c>{X,Y,Z}</c> identifying the + process which was executing when the block was allocated, or + <c>undefined</c> if no process was executing. The pid tuple + <c>{X,Y,Z}</c> can be transformed into a real pid by usage of the + <c>c:pid/3</c> function.</p> + <p>Various details about memory allocation:</p> + <p>Memory blocks are allocated both on the heap segment and on other memory + segments. This can cause the instrumentation functionality to report + very large holes. Currently the instrumentation functionality doesn't + provide any support for distinguishing between holes between memory + segments, and holes between allocated blocks inside memory segments. + The current size of the process cannot be obtained from within Erlang, + but can be seen with one of the system statistics tools, e.g., + <c>ps</c> or <c>top</c>. The Solaris utility <c>pmap</c> can be + useful. It reports currently mapped memory segments. </p> + <p>Overhead for instrumentation: When the emulator has been started with + the <seealso marker="erts:erts_alloc#Mim">"+Mim true"</seealso> + flag, each block is preceded by a 24 bytes large + header on a 32-bit machine and a 48 bytes large header on a 64-bit + machine. When the emulator has been started with the + <seealso marker="erts:erts_alloc#Mis">"+Mis true"</seealso> + flag, each block is preceded by an 8 bytes large header. These are the header + sizes used by the Erlang 5.3/OTP R9C emulator. Other versions of the + emulator may use other header sizes. The function + <seealso marker="#block_header_size/1">block_header_size/1</seealso> + can be used for retrieving the header size used for a specific memory + allocation map. The time overhead for managing the instrumentation + data is small.</p> + <p>Sizes presented by the instrumentation functionality are (by the + emulator) requested sizes, i.e. neither instrumentation headers nor + headers used by allocators are included.</p> + </description> + <funcs> + <func> + <name>allocator_descr(MemoryData, TypeNo) -> AllocDescr | invalid_type | "unknown"</name> + <fsummary>Returns a allocator description</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + <v>TypeNo = int()</v> + <v>AllocDescr = atom() | string()</v> + </type> + <desc> + <p>Returns the allocator description of the allocator that + manages memory blocks of type number <c>TypeNo</c> used in + <c>MemoryData</c>. + Valid <c>TypeNo</c>s are in the range returned by + <seealso marker="#type_no_range/1">type_no_range/1</seealso> on + this specific memory allocation map. If <c>TypeNo</c> is an + invalid integer, <c>invalid_type</c> is returned.</p> + </desc> + </func> + <func> + <name>block_header_size(MemoryData) -> int()</name> + <fsummary>Returns the memory block header size used by the emulator that generated the memory allocation map</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + </type> + <desc> + <marker id="block_header_size_1"></marker> + <p>Returns the memory block header size used by the + emulator that generated the memory allocation map. The block + header size may differ between different emulators.</p> + </desc> + </func> + <func> + <name>class_descr(MemoryData, TypeNo) -> ClassDescr | invalid_type | "unknown"</name> + <fsummary>Returns a allocator description</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + <v>TypeNo = int()</v> + <v>ClassDescr = atom() | string()</v> + </type> + <desc> + <p>Returns the class description of the class that + the type number <c>TypeNo</c> used in <c>MemoryData</c> belongs + to. + Valid <c>TypeNo</c>s are in the range returned by + <seealso marker="#type_no_range/1">type_no_range/1</seealso> on + this specific memory allocation map. If <c>TypeNo</c> is an + invalid integer, <c>invalid_type</c> is returned.</p> + </desc> + </func> + <func> + <name>descr(MemoryData) -> DescrMemoryData</name> + <fsummary>Replace type numbers in memory allocation map with type descriptions</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + <v>DescrMemoryData = {term(), DescrAllocList}</v> + <v>DescrAllocList = [DescrDesc]</v> + <v>DescrDesc = {TypeDescr, int(), int(), DescrPidDesc}</v> + <v>TypeDescr = atom() | string()</v> + <v>DescrPidDesc = pid() | undefined</v> + </type> + <desc> + <p>Returns a memory allocation map where the type numbers (first + element of <c>Desc</c>) have been replaced by type descriptions, + and pid tuples (fourth element of <c>Desc</c>) have been + replaced by real pids.</p> + </desc> + </func> + <func> + <name>holes(MemoryData) -> ok</name> + <fsummary>Print out the sizes of unused memory blocks</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + </type> + <desc> + <p>Prints out the size of each hole (i.e., the space between + allocated blocks) on the terminal. <em>NOTE:</em> Really large holes + are probably holes between memory segments. + The memory allocation map has to be sorted (see + <seealso marker="#sort/1">sort/1</seealso>).</p> + </desc> + </func> + <func> + <name>mem_limits(MemoryData) -> {Low, High}</name> + <fsummary>Return lowest and highest memory address used</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + <v>Low = High = int()</v> + </type> + <desc> + <p>Returns a tuple <c>{Low, High}</c> indicating + the lowest and highest address used. + The memory allocation map has to be sorted (see + <seealso marker="#sort/1">sort/1</seealso>).</p> + </desc> + </func> + <func> + <name>memory_data() -> MemoryData | false</name> + <fsummary>Return the current memory allocation map</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + </type> + <desc> + <p>Returns <c>MemoryData</c> (a the memory allocation map) + if the emulator has been started with the "<c>+Mim true</c>" + command-line argument; otherwise, <c>false</c>. <em>NOTE:</em><c>memory_data/0</c> blocks execution of other processes while + the data is collected. The time it takes to collect the data can + be substantial.</p> + </desc> + </func> + <func> + <name>memory_status(StatusType) -> [StatusInfo] | false</name> + <fsummary>Return current memory allocation status</fsummary> + <type> + <v>StatusType = total | allocators | classes | types</v> + <v>StatusInfo = {About, [Info]}</v> + <v>About = atom()</v> + <v>Info = {InfoName, Current, MaxSinceLast, MaxEver}</v> + <v>InfoName = sizes|blocks</v> + <v>Current = int()</v> + <v>MaxSinceLast = int()</v> + <v>MaxEver = int()</v> + </type> + <desc> + <p>Returns a list of <c>StatusInfo</c> if the emulator has been + started with the "<c>+Mis true</c>" or "<c>+Mim true</c>" + command-line argument; otherwise, <c>false</c>. </p> + <p>See the + <seealso marker="#read_memory_status/1">read_memory_status/1</seealso> + function for a description of the <c>StatusInfo</c> term.</p> + </desc> + </func> + <func> + <name>read_memory_data(File) -> MemoryData | {error, Reason}</name> + <fsummary>Read memory allocation map</fsummary> + <type> + <v>File = string()</v> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + </type> + <desc> + <marker id="read_memory_data_1"></marker> + <p>Reads a memory allocation map from the file <c>File</c> and + returns it. The file is assumed to have been created by + <c>store_memory_data/1</c>. The error codes are the same as for + <c>file:consult/1</c>.</p> + </desc> + </func> + <func> + <name>read_memory_status(File) -> MemoryStatus | {error, Reason}</name> + <fsummary>Read memory allocation status from a file</fsummary> + <type> + <v>File = string()</v> + <v>MemoryStatus = [{StatusType, [StatusInfo]}]</v> + <v>StatusType = total | allocators | classes | types</v> + <v>StatusInfo = {About, [Info]}</v> + <v>About = atom()</v> + <v>Info = {InfoName, Current, MaxSinceLast, MaxEver}</v> + <v>InfoName = sizes|blocks</v> + <v>Current = int()</v> + <v>MaxSinceLast = int()</v> + <v>MaxEver = int()</v> + </type> + <desc> + <marker id="read_memory_status_1"></marker> + <p>Reads memory allocation status from the file <c>File</c> and + returns it. The file is assumed to have been created by + <c>store_memory_status/1</c>. The error codes are the same as + for <c>file:consult/1</c>.</p> + <p>When <c>StatusType</c> is <c>allocators</c>, <c>About</c> is + the allocator that the information is about. When + <c>StatusType</c> is <c>types</c>, <c>About</c> is + the memory block type that the information is about. Memory + block types are not described other than by their name and may + vary between emulators. When <c>StatusType</c> is <c>classes</c>, + <c>About</c> is the memory block type class that information is + presented about. Memory block types are classified after their + use. Currently the following classes exist:</p> + <taglist> + <tag><c>process_data</c></tag> + <item>Erlang process specific data.</item> + <tag><c>binary_data</c></tag> + <item>Erlang binaries.</item> + <tag><c>atom_data</c></tag> + <item>Erlang atoms.</item> + <tag><c>code_data</c></tag> + <item>Erlang code.</item> + <tag><c>system_data</c></tag> + <item>Other data used by the system</item> + </taglist> + <p>When <c>InfoName</c> is <c>sizes</c>, <c>Current</c>, + <c>MaxSinceLast</c>, and <c>MaxEver</c> are, respectively, current + size, maximum size since last call to + <c>store_memory_status/1</c> or <c>memory_status/1</c> with the + specific <c>StatusType</c>, and maximum size since the emulator + was started. When <c>InfoName</c> is <c>blocks</c>, <c>Current</c>, + <c>MaxSinceLast</c>, and <c>MaxEver</c> are, respectively, current + number of blocks, maximum number of blocks since last call to + <c>store_memory_status/1</c> or <c>memory_status/1</c> with the + specific <c>StatusType</c>, and maximum number of blocks since the + emulator was started. </p> + <p><em>NOTE:</em>A memory block is accounted for at + "the first level" allocator. E.g. <c>fix_alloc</c> allocates its + memory pools via <c>ll_alloc</c>. When a <c>fix_alloc</c> block + is allocated, neither the block nor the pool in which it resides + are accounted for as memory allocated via <c>ll_alloc</c> even + though it is.</p> + </desc> + </func> + <func> + <name>sort(MemoryData) -> MemoryData</name> + <fsummary>Sort the memory allocation list</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + </type> + <desc> + <marker id="sort_1"></marker> + <p>Sorts a memory allocation map so that the addresses are in + ascending order.</p> + </desc> + </func> + <func> + <name>store_memory_data(File) -> true|false</name> + <fsummary>Store the current memory allocation map on a file</fsummary> + <type> + <v>File = string()</v> + </type> + <desc> + <p>Stores the current memory allocation map on the file + <c>File</c>. Returns <c>true</c> if the emulator has been + started with the "<c>+Mim true</c>" command-line argument, and + the map was successfuly stored; otherwise, <c>false</c>. The + contents of the file can later be read using + <seealso marker="#read_memory_data/1">read_memory_data/1</seealso>. + <em>NOTE:</em><c>store_memory_data/0</c> blocks execution of + other processes while the data is collected. The time it takes + to collect the data can be substantial.</p> + </desc> + </func> + <func> + <name>store_memory_status(File) -> true|false</name> + <fsummary>Store the current memory allocation status on a file</fsummary> + <type> + <v>File = string()</v> + </type> + <desc> + <p>Stores the current memory status on the file + <c>File</c>. Returns <c>true</c> if the emulator has been + started with the "<c>+Mis true</c>", or "<c>+Mim true</c>" + command-line arguments, and the data was successfuly stored; + otherwise, <c>false</c>. The contents of the file can later be + read using + <seealso marker="#read_memory_status/1">read_memory_status/1</seealso>.</p> + </desc> + </func> + <func> + <name>sum_blocks(MemoryData) -> int()</name> + <fsummary>Return the total amount of memory used</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + </type> + <desc> + <p>Returns the total size of the memory blocks in the list.</p> + </desc> + </func> + <func> + <name>type_descr(MemoryData, TypeNo) -> TypeDescr | invalid_type</name> + <fsummary>Returns a type description</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + <v>TypeNo = int()</v> + <v>TypeDescr = atom() | string()</v> + </type> + <desc> + <p>Returns the type description of a type number used in + <c>MemoryData</c>. + Valid <c>TypeNo</c>s are in the range returned by + <seealso marker="#type_no_range/1">type_no_range/1</seealso> on + this specific memory allocation map. If <c>TypeNo</c> is an + invalid integer, <c>invalid_type</c> is returned.</p> + </desc> + </func> + <func> + <name>type_no_range(MemoryData) -> {Min, Max}</name> + <fsummary>Returns the memory block type numbers</fsummary> + <type> + <v>MemoryData = {term(), AllocList}</v> + <v>AllocList = [Desc]</v> + <v>Desc = {int(), int(), int(), PidDesc}</v> + <v>PidDesc = {int(), int(), int()} | undefined</v> + <v>Min = int()</v> + <v>Max = int()</v> + </type> + <desc> + <marker id="type_no_range_1"></marker> + <p>Returns the memory block type number range used in + <c>MemoryData</c>. When the memory allocation map was generated + by an Erlang 5.3/OTP R9C or newer emulator, all integers <c>T</c> + that satisfy <c>Min</c> <= <c>T</c> <= <c>Max</c> are + valid type numbers. When the memory allocation map was generated + by a pre Erlang 5.3/OTP R9C emulator, all integers in the + range are <em>not</em> valid type numbers.</p> + </desc> + </func> + </funcs> + + <section> + <title>See Also</title> + <p><seealso marker="erts:erts_alloc">erts_alloc(3)</seealso>, + <seealso marker="erts:erl">erl(1)</seealso></p> + </section> +</erlref> + diff --git a/lib/tools/doc/src/make.dep b/lib/tools/doc/src/make.dep new file mode 100644 index 0000000000..11fa090d6f --- /dev/null +++ b/lib/tools/doc/src/make.dep @@ -0,0 +1,33 @@ +# ---------------------------------------------------- +# >>>> Do not edit this file <<<< +# This file was automaticly generated by +# /home/otp/bin/docdepend +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# TeX files that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: book.tex cover.tex cover_chapter.tex cprof.tex \ + cprof_chapter.tex eprof.tex erlang_mode.tex \ + erlang_mode_chapter.tex fprof.tex fprof_chapter.tex \ + instrument.tex make.tex part.tex ref_man.tex \ + tags.tex xref.tex xref_chapter.tex + +# ---------------------------------------------------- +# Source inlined when transforming from source to LaTeX +# ---------------------------------------------------- + +book.tex: ref_man.xml + +cprof.tex: ../../../../system/doc/definitions/term.defs + +xref.tex: ../../../../system/doc/definitions/term.defs + +# ---------------------------------------------------- +# Pictures that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: venn1.ps venn2.ps + diff --git a/lib/tools/doc/src/make.xml b/lib/tools/doc/src/make.xml new file mode 100644 index 0000000000..f13514d99f --- /dev/null +++ b/lib/tools/doc/src/make.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1996</year> + <year>2007</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>make</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>make</module> + <modulesummary>A Make Utility for Erlang</modulesummary> + <description> + <p>The module <c>make</c> provides a set of functions similar to + the UNIX type <c>Make</c> functions.</p> + </description> + <funcs> + <func> + <name>all() -> up_to_date | error</name> + <name>all(Options) -> up_to_date | error</name> + <fsummary>Compile a set of modules.</fsummary> + <type> + <v>Options = [Option]</v> + <v> Option = noexec | load | netload | <compiler option></v> + </type> + <desc> + <p>This function first looks in the current working directory + for a file named <c>Emakefile</c> (see below) specifying the + set of modules to compile and the compile options to use. If + no such file is found, the set of modules to compile + defaults to all modules in the current working + directory.</p> + <p>Traversing the set of modules, it then recompiles every module for + which at least one of the following conditions apply:</p> + <list type="bulleted"> + <item>there is no object file, or</item> + <item>the source file has been modified since it was last compiled, + or,</item> + <item>an include file has been modified since the source file was + last compiled.</item> + </list> + <p>As a side effect, the function prints the name of each module it + tries to compile. If compilation fails for a module, the make + procedure stops and <c>error</c> is returned.</p> + <p><c>Options</c> is a list of make- and compiler options. + The following make options exist:</p> + <list type="bulleted"> + <item><c>noexec</c> <br></br> + + No execution mode. Just prints the name of each module that needs + to be compiled.</item> + <item><c>load</c> <br></br> + + Load mode. Loads all recompiled modules.</item> + <item><c>netload</c> <br></br> + + Net load mode. Loads all recompiled modules an all known nodes.</item> + </list> + <p>All items in <c>Options</c> that are not make options are assumed + to be compiler options and are passed as-is to + <c>compile:file/2</c>. <c>Options</c> defaults to <c>[]</c>.</p> + </desc> + </func> + <func> + <name>files(ModFiles) -> up_to_date | error</name> + <name>files(ModFiles, Options) -> up_to_date | error</name> + <fsummary>Compile a set of modules.</fsummary> + <type> + <v>ModFiles = [Module | File]</v> + <v> Module = atom()</v> + <v> File = string()</v> + <v>Options = [Option]</v> + <v> Option = noexec | load | netload | <compiler option></v> + </type> + <desc> + <p><c>files/1,2</c> does exactly the same thing as <c>all/0,1</c> but + for the specified <c>ModFiles</c>, which is a list of module or + file names. The file extension <c>.erl</c> may be omitted.</p> + <p>The <c>Emakefile</c> (if it exists) in the current + directory is searched for compiler options for each module. If + a given module does not exist in <c>Emakefile</c> or if + <c>Emakefile</c> does not exist, the module is still compiled.</p> + </desc> + </func> + </funcs> + + <section> + <title>Emakefile</title> + <p><c>make:all/0,1</c> and <c>make:files/1,2</c> looks in the + current working directory for a file named <c>Emakefile</c>. If + it exists, <c>Emakefile</c> should contain elements like this:</p> + <code type="none"> +Modules. +{Modules,Options}. </code> + <p><c>Modules</c> is an atom or a list of atoms. It can be + </p> + <list type="bulleted"> + <item>a module name, e.g. <c>file1</c></item> + <item>a module name in another directory, + e.g. <c>../foo/file3</c></item> + <item>a set of modules specified with a wildcards, + e.g. <c>'file*'</c></item> + <item>a wildcard indicating all modules in current directory, + i.e. <c>'*'</c></item> + <item>a list of any of the above, + e.g. <c>['file*','../foo/file3','File4']</c></item> + </list> + <p><c>Options</c> is a list of compiler options. + </p> + <p><c>Emakefile</c> is read from top to bottom. If a module + matches more than one entry, the first match is valid. For + example, the following <c>Emakefile</c> means that <c>file1</c> + shall be compiled with the options + <c>[debug_info,{i,"../foo"}]</c>, while all other files in the + current directory shall be compiled with only the + <c>debug_info</c> flag.</p> + <code type="none"> +{'file1',[debug_info,{i,"../foo"}]}. +{'*',[debug_info]}. </code> + <p></p> + </section> +</erlref> + diff --git a/lib/tools/doc/src/note.gif b/lib/tools/doc/src/note.gif Binary files differnew file mode 100644 index 0000000000..6fffe30419 --- /dev/null +++ b/lib/tools/doc/src/note.gif diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml new file mode 100644 index 0000000000..59f600145e --- /dev/null +++ b/lib/tools/doc/src/notes.xml @@ -0,0 +1,475 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2004</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Tools Release Notes</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>notes.xml</file> + </header> + <p>This document describes the changes made to the Tools application.</p> + +<section><title>Tools 2.6.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The coverage analysis tool <c>cover</c> has been + improved when it comes to handling list and bit string + comprehensions (a counter for each qualifier), bit syntax + expressions (the Value and Size expressions), and try + expressions (the body called <c>Exprs</c> in the Reference + Manual). A few (not all) situations where several + expressions are put on the same line are also handled + better than before.</p> + <p>Own Id: OTP-8188 Aux Id: seq11397</p> + </item> + <item> + <p>When loading Cover compiled code on remote nodes + running code in the loaded module, a <c>badarg</c> + failure was sometimes the result. This bug has been fixed.</p> + <p>Own Id: OTP-8270 Aux Id: seq11423</p> + </item> + <item> + <p>The short-circuit operators <c>andalso</c> and + <c>orelse</c> are now handled correctly by the coverage + analysis tool <c>cover</c> (it is no longer checked + that the second argument returns a Boolean value.)</p> + <p>Own Id: OTP-8273</p> + </item> + </list> + </section> + +</section> + +<section><title>Tools 2.6.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p><c>cover</c> now properly escapes greater-than and + less-than characters in comments in HTML reports. (Thanks + to Magnus Henoch.)</p> + <p> + Own Id: OTP-7939</p> + </item> + </list> + </section> + +</section> + +<section><title>Tools 2.6.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + xref:start/1 does now allow anonymous XREF processes to + be started</p> + <p> + Own Id: OTP-7831</p> + </item> + </list> + </section> + +</section> + +<section><title>Tools 2.6.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>A bug in the Xref scanner has been fixed.</p> + <p> + Own Id: OTP-7423</p> + </item> + <item> + <p>A bug in Fprof where the function 'undefined' appeared + to call 'undefined' has been corrected.</p> + <p> + Own Id: OTP-7509</p> + </item> + </list> + </section> + +</section> + +<section><title>Tools 2.6.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The documentation has been updated so as to reflect + the last updates of the Erlang shell as well as the minor + modifications of the control sequence <c>p</c> of the + <c>io_lib</c> module.</p> <p>Superfluous empty lines have + been removed from code examples and from Erlang shell + examples.</p> + <p> + Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911 </p> + </item> + <item> + <p><c>tuple_size/1</c> and <c>byte_size/1</c> have been + substituted for <c>size/1</c>.</p> + <p> + Own Id: OTP-7009</p> + </item> + <item> + <p>The coverage analysis tool <c>cover</c> now handles + the short-circuit Boolean expressions <c>andalso/2</c> + and <c>orelse/2</c> properly.</p> + <p> + Own Id: OTP-7095</p> + </item> + </list> + </section> + +</section> + +<section><title>Tools 2.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The <c>cover</c> tool could use huge amounts of memory + when used in a distributed system.</p> + <p> + Own Id: OTP-6758</p> + </item> + </list> + </section> + +</section> + + + <section> + <title>Tools 2.5.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Missing buffer-local declaration in erlang.el has been + added. Before this fix there could arise problems in + other emacs modes after visiting a buffer using the + erlang mode.</p> + <p>Own Id: OTP-6721</p> + </item> + <item> + <p>Key-map for 'backward-delete-char-untabif updated to work + properly with Xemacs.</p> + <p>Own Id: OTP-6723</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Minor updates of Xref.</p> + <p>Own Id: OTP-6586</p> + </item> + <item> + <p>Minor Makefile changes.</p> + <p>Own Id: OTP-6689 Aux Id: OTP-6742 </p> + </item> + <item> + <p>"C-u C-c C-k" now does a compile with both "debug_info" + and "export_all".</p> + <p>Own Id: OTP-6741</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.5.4.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Changes due to internal interface changes in the erts + application which are needed at compile-time. No + functionality has been changed.</p> + <p>Own Id: OTP-6611 Aux Id: OTP-6580 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.5.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Made change to support the function erlang-find-tag for + xemacs and emacs-21.</p> + <p>Own Id: OTP-6512</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Minor updates of xref for future compatibility.</p> + <p>Own Id: OTP-6513</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.5.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c>eprof</c> did not work reliably in the SMP emulator, + because the trace receiver process could not process the + trace messages fast enough. Therefore, <c>eprof</c> now + blocks the other schedulers while profiling.</p> + <p>Own Id: OTP-6373</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.5.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Fprof traces could become truncated for the SMP emulator. + This bug has now been corrected.</p> + <p>Own Id: OTP-6246</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.5.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>eprof now works somewhat better in the SMP emulator.</p> + <p>Own Id: OTP-6152</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Fixed some bugs in <c>make</c>:</p> + <p><c>make:files/1,2</c> can now handle a file in another + directory as argument, similar to <c>make:all/0,1</c>.</p> + <p>When specifying a file name including the <c>.erl</c> + extension in <c>Emakefile</c>, <c>make:all/0,1</c> looked + for the object code in the wrong place.</p> + <p>When specifying a file name including the <c>.erl</c> + extension in <c>Emakefile</c> and some compile options + for the file, <c>make:files/0,1</c> did not use the + options as it should do.</p> + <p>Own Id: OTP-6057 Aux Id: seq10299</p> + </item> + <item> + <p><c>cover</c>: When <c>cover:stop()</c> was called, + the cover compiled code was not unloaded (as stated in + the documentation) but simply marked as 'old'. This + meant that processes lingering in (or with funs + referencing to) the cover compiled code would survive + even when the cover server and its ETS tables was + terminated.</p> + <p>Now the cover compiled code is unloaded, meaning that + processes lingering in/with references to it will be + killed when <c>cover:stop</c> is called, instead of + later crashing with <c>badarg</c> when trying to bump + counters in ETS tables no longer existing.</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Replaced call to deprecated function + <c>file:file_info/1</c> with call to + <c>filelib:is_dir/1</c> and <c>filelib:is_regular/1</c> + in <c>tags.erl</c>.</p> + <p>Own Id: OTP-6079</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.7</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>A bug in <c>fprof</c> profiling causing erroneous + inconsistent trace failure has been corrected.</p> + <p>Own Id: OTP-5922 Aux Id: seq10203 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.6</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Emacs: <c>erlang-man-function</c> and + <c>erlang-man-module</c> used a pattern matching to find + the requested module that sometimes yielded unexpected + results. For example, <c>erlang-man-module file</c> would + display the man page for <c>CosFileTransfer_File</c>.</p> + <p>Own Id: OTP-5746 Aux Id: seq10096</p> + </item> + <item> + <p>Some compiler warnings and Dialyzer warnings were + eliminated in the Tools application.</p> + <p>When tracing to a port (which <c>fprof</c> does), + there could be fake schedule out/schedule in messages + sent for a process that had exited.</p> + <p>Own Id: OTP-5757</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The cross reference tool <c>xref</c> did not handle the new + <c>fun M:F/A</c> construct properly. This problem has been + fixed.</p> + <p>Own Id: OTP-5653</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The <c>cover</c> tool did not escape '<' and '>' not + being part of HTML tags in HTML log files.</p> + <p>Own Id: OTP-5588</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.3</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>It is now possible to encrypt the debug information in + beam files, to help keep the source code secret. See + <c>compile(3)</c> for how to provide the key for encrypting, + and <c>beam_lib(3)</c> for how to provide the key for + decryption so that tools such as Debugger, <c>xref</c>, or + <c>cover</c> can be used.</p> + <p>The <c>beam_lib:chunks/2</c> functions now accepts an + additional chunk type '<c>compile_info</c>' to retrieve + the compilation information directly as a term. (Thanks + to Tobias Lindahl.)</p> + <p>Own Id: OTP-5460 Aux Id: seq9787</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The <c>cover</c> tool could not analyze empty modules on + module level.</p> + <p>Own Id: OTP-5418</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.4.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The <c>xref</c> analysis <c>locals_not_used</c> could + return too many functions. This problem has been fixed.</p> + <p>Own Id: OTP-5071</p> + </item> + <item> + <p>The <c>cover</c> tool could not always compile parse + transformed modules. This problem has been fixed.</p> + <p>Own Id: OTP-5305</p> + </item> + </list> + </section> + </section> +</chapter> + diff --git a/lib/tools/doc/src/notes_history.xml b/lib/tools/doc/src/notes_history.xml new file mode 100644 index 0000000000..ef5ce1c03d --- /dev/null +++ b/lib/tools/doc/src/notes_history.xml @@ -0,0 +1,243 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2006</year> + <year>2007</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>Tools Release Notes</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + + <section> + <title>Tools 2.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The Erlang Emacs mode now properly handles strings that + have $ or ^ as the last character.</p> + <p>Own Id: OTP-4697</p> + </item> + <item> + <p><c>xref</c>: The unresolved arity (-1) is now recognized + in analyses and queries.</p> + <p>Own Id: OTP-4778</p> + </item> + <item> + <p><c>cover</c> does no longer hang if an interface function + is called on a remote node - it returns + <c>{error,not_main_node}</c>.</p> + <p>Own Id: OTP-5031</p> + </item> + <item> + <p><c>fprof</c>: Time spent in the last function in a chain, + i.e. a function which did not call another function, and + the time when a process was scheduled out, was charged on + the above function. This resulted in own time in many + cases being bigger than acc time since the time a process + was scheduled out was charged on the function from which + the process was scheduled out. This is now corrected.</p> + <p>Own Id: OTP-5073</p> + </item> + <item> + <p>Previous patch from open source messed up \\M-q so part of + that patch was backed out.</p> + <p>Own Id: OTP-5074</p> + </item> + <item> + <p><c>cover</c>: Added "Exclude Included Functions". If + "real code" is included in a modules which is cover + compiled, there will be no bumps for lines in the + included file. Earlier this would cause faulty bumps for + lines in the module, i.e. if the code was on line 4 in + the included file it would produce a bump for line 4 in + the module. Lines in included files are now just + disregarded.</p> + <p>Own Id: OTP-5122</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Added support for try-catch to the Erlang mode for Emacs. + However there are still some known problems with some of + the more advanced variants especially including separate + of-clauses.</p> + <p>Own Id: OTP-4594</p> + </item> + <item> + <p>Improvments for support of Emacs 21 contributed by Dave + Love. The bulk of the changes are actually cosmetic + commentary/doc fixes. The significant ones make it play + better with Emacs 21 with up-to-date facilities. In + particular, support for compilation error messages from + an inferior erl (as opposed to batch compilation) works + in the released Emacs 21, and currently with the + development Emacs.</p> + <p>Own Id: OTP-5019</p> + </item> + <item> + <p>Added a skeletons for an Erlang test-suite for both the + ts-frontend and the ct-frontend (this frontend is + Ericsson internal). Also altered some of the old + skeletons to get a uniform look and feel.</p> + <p>Own Id: OTP-5058</p> + </item> + <item> + <p>The Erlang mode for Emacs now supports the new guard + <c>is_boolean</c>.</p> + <p>Own Id: OTP-5059</p> + </item> + <item> + <p><c>cover</c>: Adjustments to handle new syntax of + try-catch.</p> + <p>Own Id: OTP-5154</p> + </item> + </list> + </section> + </section> + + <section> + <title>Tools 2.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Totally rewritten the interface for WebCover. Can now + compile both <c>.erl</c> and <c>.beam</c> files and + export/import cover data.</p> + <p>Own Id: OTP-4706</p> + </item> + <item> + <p><c>cover</c> does no longer report coverage on lines which + are not executed.</p> + <p>Own Id: OTP-4734</p> + </item> + <item> + <p>Erlang mode for Emacs: Fixed so that the generation of new + function clauses works also for guarded functions.</p> + <p>Own Id: OTP-3697</p> + </item> + <item> + <p>Erlang mode for Emacs: Fixed so that you do not get + the error message "unbalanced parenthesis" when indenting + correct code including bit syntax.</p> + <p>Own Id: OTP-4526</p> + </item> + <item> + <p>Erlang mode for Emacs: The guard <c>function</c> is now + colored.</p> + <p>Own Id: OTP-4533</p> + </item> + <item> + <p>Erlang mode for Emacs: Indentation of macros is handled + correctly in all cases.</p> + <p>Own Id: OTP-4561, OTP-4687</p> + </item> + <item> + <p><c>is_*</c> guards are now colored.</p> + <p>Own Id: OTP-4562</p> + </item> + <item> + <p>Erlang mode for Emacs: Now handles the fact that a function + argument may be a guard expression. (That is useful when + writing test case code.)</p> + <p>Own Id: OTP-4579</p> + </item> + <item> + <p>Erlang mode for Emacs: Keywords <c>andalso</c> and + <c>orelse</c> are now colored.</p> + <p>Own Id: OTP-4580</p> + </item> + <item> + <p>Erlang mode for Emacs: Fixed bug in function that calculates + the arity of an Erlang function.</p> + <p>Own Id: OTP-4581</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Added functions <c>cover:start(Nodes)</c> and + <c>cover:stop(Nodes)</c>. Cover compiled modules will be + loaded on all nodes added with <c>cover:start(Nodes)</c>. + <c>cover:stop(Nodes)</c> will collect coverage data from + the stopped nodes and merge it with data collected on + the main (controller) node.</p> + <p><c>cover:analyse/1,2,3</c> and + <c>cover:analyse_to_file/1,2,3</c> will also collect data + from all nodes before analysing.</p> + <p>Own Id: OTP-4177</p> + </item> + <item> + <p>The module attribute tag <c>deprecated</c> is used by + <c>xref</c> to find calls to deprecated functions. + The <c>m/1</c>, <c>d/1</c>, and <c>analyze/2,3</c> functions + have been updated to return calls to deprecated functions. + See also <c>xref(3)</c> for more details.</p> + <p>Own Id: OTP-4695</p> + </item> + <item> + <p>Added functions <c>cover:compile_beam/1</c> and + <c>cover:compile_beam_directory/0,1</c>. These functions use + abstract code from existing beam files when cover compiling.</p> + <p>Added option <c>html</c> to + <c>cover:analyse_to_file/1,2,3</c>. Instead of plain text, + a HTML file is generated with all uncovered lines colored + red.</p> + <p>Added functions <c>cover:export/1,2</c> and + <c>cover:import/1</c>. These functions can be used to export + current coverage data to a file, and then import the data + in a later session. Data can be exported for one single + module or for all currently cover compiled modules.</p> + <p>Own Id: OTP-4702</p> + </item> + <item> + <p>Erlang mode for Emacs: Added function + <c>erlang-align-arrows</c>.</p> + <p>Own Id: OTP-4737</p> + </item> + <item> + <p>The interface for the <c>instrument</c> module has been + slightly changed. Also some new functionality has been + added. See <c>instrument(3)</c> for more information.</p> + <p>(*** POTENTIAL INCOMPATIBILITY ***)</p> + <p>Own Id: OTP-4761 <br></br> + + Aux Id: OTP-4534</p> + </item> + </list> + </section> + </section> +</chapter> + diff --git a/lib/tools/doc/src/part.xml b/lib/tools/doc/src/part.xml new file mode 100644 index 0000000000..3e02086b80 --- /dev/null +++ b/lib/tools/doc/src/part.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Tools User's Guide</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <description> + <p>The <em>Tools</em> application contains a number of stand-alone + tools, which are useful when developing Erlang programs.</p> + <taglist> + <tag><em>cover</em></tag> + <item>A coverage analysis tool for Erlang.</item> + <tag><em>cprof</em></tag> + <item>A profiling tool that shows how many + times each function is called. Uses a kind of local call trace + breakpoints containing counters to achieve very low runtime + performance degradation.</item> + <tag><em>emacs - (erlang.el and erlang-start.el)</em></tag> + <item>This package provides support + for the programming language Erlang in Emacs. The package provides an + editing mode with lots of bells and whistles, compilation + support, and it makes it possible for the user to start Erlang + shells that run inside Emacs.</item> + <tag><em>eprof</em></tag> + <item>A time profiling tool; measure how time is used in Erlang + programs. Erlang programs. Predecessor of <em>fprof</em> (see below).</item> + <tag><em>fprof</em></tag> + <item>Another Erlang profiler; measure how time is used in your + Erlang programs. Uses trace to file to minimize runtime + performance impact, and displays time for calling and called + functions.</item> + <tag><em>instrument</em></tag> + <item>Utility functions for obtaining and analysing resource usage + in an instrumented Erlang runtime system.</item> + <tag><em>make</em></tag> + <item>A make utility for Erlang similar to UNIX make.</item> + <tag><em>tags</em></tag> + <item>A tool for generating Emacs TAGS files from Erlang source + files.</item> + <tag><em>xref</em></tag> + <item>A cross reference tool. Can be used to check dependencies + between functions, modules, applications and releases.</item> + </taglist> + </description> + <xi:include href="cover_chapter.xml"/> + <xi:include href="cprof_chapter.xml"/> + <xi:include href="erlang_mode_chapter.xml"/> + <xi:include href="fprof_chapter.xml"/> + <xi:include href="xref_chapter.xml"/> +</part> + diff --git a/lib/tools/doc/src/part_notes.xml b/lib/tools/doc/src/part_notes.xml new file mode 100644 index 0000000000..b8b67889c2 --- /dev/null +++ b/lib/tools/doc/src/part_notes.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2004</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Tools Release Notes</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <description> + <p>The <em>Tools</em> application contains a number of stand-alone + tools, which are useful when developing Erlang programs.</p> + <p>For information about older versions, see + <url href="part_notes_history_frame.html">Release Notes History</url>.</p> + </description> + <xi:include href="notes.xml"/> +</part> + diff --git a/lib/tools/doc/src/part_notes_history.xml b/lib/tools/doc/src/part_notes_history.xml new file mode 100644 index 0000000000..b40b530c02 --- /dev/null +++ b/lib/tools/doc/src/part_notes_history.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part> + <header> + <copyright> + <year>2006</year> + <year>2007</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>Tools Release Notes History</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <description> + <p>The <em>Tools</em> application contains a number of stand-alone + tools, which are useful when developing Erlang programs.</p> + </description> + <include file="notes_history"></include> +</part> + diff --git a/lib/tools/doc/src/ref_man.xml b/lib/tools/doc/src/ref_man.xml new file mode 100644 index 0000000000..aea74e3746 --- /dev/null +++ b/lib/tools/doc/src/ref_man.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE application SYSTEM "application.dtd"> + +<application xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1996</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Tools Reference Manual</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <description> + <p>The <em>Tools</em> application contains a number of stand-alone + tools, which are useful when developing Erlang programs.</p> + <taglist> + <tag><em>cover</em></tag> + <item>A coverage analysis tool for Erlang.</item> + <tag><em>cprof</em></tag> + <item>A profiling tool that shows how many + times each function is called. Uses a kind of local call trace + breakpoints containing counters to achieve very low runtime + performance degradation.</item> + <tag><em>erlang.el</em>- Erlang mode for Emacs</tag> + <item>Editing support such as indentation, syntax highlighting, + electric commands, module name verification, comment support + including paragraph filling, skeletons, tags support and more + for erlang source code. </item> + <tag><em>eprof</em></tag> + <item>A time profiling tool; measure how time is used in Erlang + programs. Predecessor of <em>fprof</em> (see below).</item> + <tag><em>fprof</em></tag> + <item>Another Erlang profiler; measure how time is used in your + Erlang programs. Uses trace to file to minimize runtime + performance impact, and displays time for calling and called + functions.</item> + <tag><em>instrument</em></tag> + <item>Utility functions for obtaining and analysing resource usage + in an instrumented Erlang runtime system.</item> + <tag><em>make</em></tag> + <item>A make utility for Erlang similar to UNIX make.</item> + <tag><em>tags</em></tag> + <item>A tool for generating Emacs TAGS files from Erlang source + files.</item> + <tag><em>xref</em></tag> + <item>A cross reference tool. Can be used to check dependencies + between functions, modules, applications and releases.</item> + </taglist> + </description> + <xi:include href="cover.xml"/> + <xi:include href="cprof.xml"/> + <xi:include href="eprof.xml"/> + <xi:include href="erlang_mode.xml"/> + <xi:include href="fprof.xml"/> + <xi:include href="instrument.xml"/> + <xi:include href="make.xml"/> + <xi:include href="tags.xml"/> + <xi:include href="xref.xml"/> +</application> + diff --git a/lib/tools/doc/src/tags.xml b/lib/tools/doc/src/tags.xml new file mode 100644 index 0000000000..5e1da25acf --- /dev/null +++ b/lib/tools/doc/src/tags.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1998</year> + <year>2007</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>tags</title> + <prepared>Anders Lindgren</prepared> + <responsible></responsible> + <docno>1</docno> + <date>98-03-11</date> + <rev>A</rev> + <file>tags.sgml</file> + </header> + <module>tags</module> + <modulesummary>Generate Emacs TAGS file from Erlang source files</modulesummary> + <description> + <p>A <c>TAGS</c> file is used by Emacs to find function and variable + definitions in any source file in large projects. This module can + generate a <c>TAGS</c> file from Erlang source files. It recognises + functions, records, and macro definitions.</p> + </description> + <funcs> + <func> + <name>file(File [, Options])</name> + <fsummary>Create a <c>TAGS</c>file for the file <c>File</c>.</fsummary> + <desc> + <p>Create a <c>TAGS</c> file for the file <c>File</c>.</p> + </desc> + </func> + <func> + <name>files(FileList [, Options])</name> + <fsummary>Create a TAGS file for the files in the list<c>FileList</c>.</fsummary> + <desc> + <p>Create a TAGS file for the files in the list + <c>FileList</c>.</p> + </desc> + </func> + <func> + <name>dir(Dir [, Options])</name> + <fsummary>Create a TAGS file for all files in directory<c>Dir</c>.</fsummary> + <desc> + <p>Create a TAGS file for all files in directory + <c>Dir</c>.</p> + </desc> + </func> + <func> + <name>dirs(DirList [, Options])</name> + <fsummary>Create a TAGS file for all files in any directory in<c>DirList</c>.</fsummary> + <desc> + <p>Create a TAGS file for all files in any directory in + <c>DirList</c>.</p> + </desc> + </func> + <func> + <name>subdir(Dir [, Options])</name> + <fsummary>Descend recursively down the directory <c>Dir</c>and create a <c>TAGS</c>file based on all files found.</fsummary> + <desc> + <p>Descend recursively down the directory <c>Dir</c> and + create a <c>TAGS</c> file based on all files found.</p> + </desc> + </func> + <func> + <name>subdirs(DirList [, Options])</name> + <fsummary>Descend recursively down all the directories in<c>DirList</c>and create a <c>TAGS</c>file based on all files found.</fsummary> + <desc> + <p>Descend recursively down all the directories in + <c>DirList</c> and create a <c>TAGS</c> file based on all + files found.</p> + </desc> + </func> + <func> + <name>root([Options])</name> + <fsummary>Create a <c>TAGS</c>file covering all files in the Erlang distribution.</fsummary> + <desc> + <p>Create a <c>TAGS</c> file covering all files in + the Erlang distribution.</p> + </desc> + </func> + </funcs> + + <section> + <title>OPTIONS</title> + <p>The functions above have an optional argument, <c>Options</c>. It is a + list which can contain the following elements:</p> + <list type="bulleted"> + <item><c>{outfile, NameOfTAGSFile}</c> Create a <c>TAGS</c> file named + <c>NameOfTAGSFile</c>. + </item> + <item><c>{outdir, NameOfDirectory}</c> Create a file named + <c>TAGS</c> in the directory <c>NameOfDirectory</c>.</item> + </list> + <p>The default behaviour is to create a file named <c>TAGS</c> in the current + directory.</p> + </section> + + <section> + <title>Examples</title> + <list type="bulleted"> + <item> + <p><c>tags:root([{outfile, "root.TAGS"}]).</c> <br></br> +</p> + <p>This command will create a file named <c>root.TAGS</c> in the current + directory. The file will contain references to all Erlang source + files in the Erlang distribution.</p> + </item> + <item> + <p><c>tags:files(["foo.erl", "bar.erl", "baz.erl"], [{outdir, "../projectdir"}]). </c> <br></br> +</p> + <p>Here we create file named <c>TAGS</c> placed it in the directory + <c>../projectdir</c>. The file contains information about the + functions, records, and macro definitions of the three files.</p> + </item> + </list> + </section> + + <section> + <title>SEE ALSO</title> + <list type="bulleted"> + <item>Richard M. Stallman. GNU Emacs Manual, chapter "Editing Programs", + section "Tag Tables". Free Software Foundation, 1995. + </item> + <item>Anders Lindgren. The Erlang editing mode for Emacs. Ericsson, + 1998.</item> + </list> + </section> +</erlref> + diff --git a/lib/tools/doc/src/venn1.fig b/lib/tools/doc/src/venn1.fig new file mode 100644 index 0000000000..a826756047 --- /dev/null +++ b/lib/tools/doc/src/venn1.fig @@ -0,0 +1,63 @@ +#FIG 3.2 +Portrait +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 4368 1485 7027 4139 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 3177.742 2812.000 4570 2137 4725 2812 4570 3487 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 9043.057 2812.000 5400 4112 5175 2812 5400 1512 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2307.694 2812.000 6003 1512 6225 2812 6003 4112 +1 3 0 1 -1 7 0 0 -1 0.000 1 0.0000 5700 2812 1327 1327 5700 2812 4800 1837 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1 + 6681 3706 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 6675 1912 6675 3712 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2 + 4368 2806 6675 2806 +2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2 + 6675 3149 6985 3149 +-6 +6 1275 3075 3000 4800 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 563.250 3905.000 1434 3485 1530 3905 1434 4325 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 23.692 3905.000 2326 3096 2464 3905 2326 4714 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 4217.432 3905.000 1950 4714 1810 3905 1950 3096 +6 1275 3675 2775 4200 +6 2026 3679 2251 4129 +6 2026 3679 2251 4129 +4 0 0 100 0 0 8 0.0000 4 75 180 2078 3794 XU\001 +4 0 0 100 0 0 8 0.0000 4 75 165 2071 3944 and\001 +4 0 0 100 0 0 8 0.0000 4 75 165 2078 4093 LU\001 +-6 +-6 +4 0 0 100 0 0 8 0.0000 4 75 165 1594 3934 LU\001 +4 0 0 100 0 0 8 0.0000 4 75 180 2634 3934 XU\001 +4 0 0 100 0 0 8 0.0000 4 75 180 1337 3934 UU\001 +-6 +1 3 0 1 -1 7 0 0 -1 0.000 1 0.0000 2137 3905 826 826 2137 3905 1577 3298 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1 + 2747 4461 +-6 +6 1275 825 3000 2850 +6 2760 1516 2820 2006 +4 0 0 100 0 0 8 0.0000 4 75 90 2760 1576 U\001 +4 0 0 100 0 0 8 0.0000 4 75 75 2760 2006 B\001 +-6 +1 3 0 1 -1 7 0 0 -1 0.000 1 0.0000 2115 1665 826 826 2115 1665 1555 1058 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1 + 2725 2221 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 2722 1105 2722 2225 +2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2 + 2722 1875 2917 1875 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2 + 1286 1665 2722 1665 +4 0 0 100 0 0 11 0.0000 4 105 645 1830 2785 Definition\001 +4 0 0 100 0 0 8 0.0000 4 75 90 2022 1338 X\001 +4 0 0 100 0 0 8 0.0000 4 75 75 2022 2085 L\001 +-6 +4 0 0 100 0 0 11 0.0000 4 105 240 2025 5025 Use\001 +4 0 0 101 0 0 11 0.0000 4 105 1155 5127 4544 Definition and Use\001 diff --git a/lib/tools/doc/src/venn1.gif b/lib/tools/doc/src/venn1.gif Binary files differnew file mode 100644 index 0000000000..e40bcfb8ab --- /dev/null +++ b/lib/tools/doc/src/venn1.gif diff --git a/lib/tools/doc/src/venn1.ps b/lib/tools/doc/src/venn1.ps new file mode 100644 index 0000000000..9c12048728 --- /dev/null +++ b/lib/tools/doc/src/venn1.ps @@ -0,0 +1,205 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: venn1.ps +%%Creator: fig2dev Version 3.2 Patchlevel 1 +%%CreationDate: Tue Sep 19 19:28:28 2000 +%%For: hasse@helios (Hans Bolinder) +%%Orientation: Portrait +%%BoundingBox: 0 0 347 253 +%%Pages: 0 +%%BeginSetup +%%EndSetup +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +-76.0 302.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def +%%EndProlog + +$F2psBegin +10 setmiterlimit +n -1000 6025 m -1000 -1000 l 8035 -1000 l 8035 6025 l cp clip + 0.06000 0.06000 sc +/Times-Roman ff 165.00 scf sf +5127 4544 m +gs 1 -1 sc (Definition and Use) col0 sh gr +% Polyline +7.500 slw +n 6675 3149 m 6985 3149 l gs 0.95 setgray ef gr gs col0 s gr +/Times-Roman ff 120.00 scf sf +2078 3794 m +gs 1 -1 sc (XU) col0 sh gr +/Times-Roman ff 120.00 scf sf +2071 3944 m +gs 1 -1 sc (and) col0 sh gr +/Times-Roman ff 120.00 scf sf +2078 4093 m +gs 1 -1 sc (LU) col0 sh gr +/Times-Roman ff 120.00 scf sf +1594 3934 m +gs 1 -1 sc (LU) col0 sh gr +/Times-Roman ff 120.00 scf sf +2634 3934 m +gs 1 -1 sc (XU) col0 sh gr +/Times-Roman ff 120.00 scf sf +1337 3934 m +gs 1 -1 sc (UU) col0 sh gr +/Times-Roman ff 120.00 scf sf +2760 1576 m +gs 1 -1 sc (U) col0 sh gr +/Times-Roman ff 120.00 scf sf +2760 2006 m +gs 1 -1 sc (B) col0 sh gr +% Polyline +n 2722 1875 m 2917 1875 l gs 0.95 setgray ef gr gs col0 s gr +/Times-Roman ff 165.00 scf sf +1830 2785 m +gs 1 -1 sc (Definition) col0 sh gr +/Times-Roman ff 120.00 scf sf +2022 1338 m +gs 1 -1 sc (X) col0 sh gr +/Times-Roman ff 120.00 scf sf +2022 2085 m +gs 1 -1 sc (L) col0 sh gr +/Times-Roman ff 165.00 scf sf +2025 5025 m +gs 1 -1 sc (Use) col0 sh gr +% Arc +gs n 3177.7 2812.0 1547.3 -25.9 25.9 arc +gs col-1 s gr + gr + +% Arc +gs n 9043.1 2812.0 3868.1 160.4 -160.4 arc +gs col-1 s gr + gr + +% Arc +gs n 2307.7 2812.0 3917.3 -19.4 19.4 arc +gs col-1 s gr + gr + +% Ellipse +n 5700 2812 1327 1327 0 360 DrawEllipse gs col-1 s gr + +% Polyline +n 6677 3706 m 6685 3706 l gs col-1 s gr +% Polyline +n 6675 1912 m 6675 3712 l gs col-1 s gr +% Polyline +n 4368 2806 m 6675 2806 l gs col-1 s gr +% Arc +gs n 563.2 3905.0 966.8 -25.8 25.8 arc +gs col-1 s gr + gr + +% Arc +gs n 23.7 3905.0 2440.3 -19.4 19.4 arc +gs col-1 s gr + gr + +% Arc +gs n 4217.4 3905.0 2407.4 160.4 -160.4 arc +gs col-1 s gr + gr + +% Ellipse +n 2137 3905 826 826 0 360 DrawEllipse gs col-1 s gr + +% Polyline +n 2743 4461 m 2751 4461 l gs col-1 s gr +% Ellipse +n 2115 1665 826 826 0 360 DrawEllipse gs col-1 s gr + +% Polyline +n 2721 2221 m 2729 2221 l gs col-1 s gr +% Polyline +n 2722 1105 m 2722 2225 l gs col-1 s gr +% Polyline +n 1286 1665 m 2722 1665 l gs col-1 s gr +$F2psEnd +rs diff --git a/lib/tools/doc/src/venn2.fig b/lib/tools/doc/src/venn2.fig new file mode 100644 index 0000000000..3694c12f0c --- /dev/null +++ b/lib/tools/doc/src/venn2.fig @@ -0,0 +1,97 @@ +#FIG 3.2 +Portrait +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 3392 953 5034 3329 +6 3392 953 5034 2595 +6 3392 953 5034 2595 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2652.489 1773.500 3518 1357 3613 1774 3518 2190 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 6306.956 1773.000 4028 2575 3891 1774 4028 971 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2105.283 1773.000 4402 971 4538 1774 4402 2575 +1 1 0 1 -1 7 0 0 -1 0.000 1 0.0000 4214 1774 820 821 4214 1774 3659 1171 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1 + 4821 2325 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 4816 1217 4816 2329 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2 + 3392 1769 4816 1769 +2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2 + 4816 1982 5008 1982 +-6 +2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 36 + 4026 977 4011 1025 3996 1072 3981 1120 3966 1177 3954 1225 + 3944 1272 3929 1327 3919 1412 3909 1477 3899 1540 3894 1592 + 3894 1642 3891 1697 3889 1742 3889 1770 3394 1767 3396 1717 + 3399 1665 3409 1610 3424 1555 3439 1502 3464 1440 3489 1390 + 3516 1340 3551 1292 3584 1250 3631 1200 3679 1150 3731 1110 + 3801 1065 3869 1030 3931 1005 3986 982 4009 980 4026 977 +-6 +4 0 0 101 0 0 11 0.0000 4 105 525 3965 3044 X - XU\001 +4 0 0 101 0 0 11 0.0000 4 150 1110 3688 3299 exports_not_used\001 +-6 +6 5850 938 7560 3329 +6 5884 938 7526 2580 +6 5884 938 7526 2580 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 5144.489 1758.500 6010 1342 6105 1759 6010 2175 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 8798.956 1758.000 6520 2560 6383 1759 6520 956 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 4597.283 1758.000 6894 956 7030 1759 6894 2560 +1 1 0 1 -1 7 0 0 -1 0.000 1 0.0000 6706 1759 820 821 6706 1759 6151 1156 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1 + 7313 2310 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 7308 1202 7308 2314 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2 + 5884 1754 7308 1754 +2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2 + 7308 1967 7500 1967 +-6 +2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 22 + 6107 1757 6104 1802 6099 1855 6094 1902 6084 1960 6072 2010 + 6062 2052 6049 2092 6032 2122 6019 2160 6007 2180 5984 2140 + 5962 2095 5944 2057 5929 2007 5909 1947 5899 1892 5892 1835 + 5889 1800 5889 1775 5889 1755 6107 1757 +2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 32 + 7309 1757 7309 2315 7287 2340 7259 2365 7234 2390 7199 2412 + 7164 2440 7124 2465 7092 2482 7054 2502 7014 2520 6974 2535 + 6934 2547 6897 2557 6909 2510 6924 2457 6942 2407 6954 2357 + 6967 2297 6979 2247 6992 2192 6999 2142 7009 2095 7012 2045 + 7019 1990 7022 1945 7027 1900 7029 1855 7029 1805 7032 1765 + 7029 1752 7309 1757 +-6 +4 0 0 101 0 0 11 0.0000 4 135 1470 6000 3014 L * (UU + (XU - LU))\001 +4 0 0 101 0 0 11 0.0000 4 150 1800 5850 3299 locals_not_used (simplified)\001 +-6 +6 900 900 2550 3600 +6 900 900 2550 2625 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 160.489 1780.500 1026 1364 1121 1781 1026 2197 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 3814.956 1780.000 1536 2582 1399 1781 1536 978 +5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 -386.717 1780.000 1910 978 2046 1781 1910 2582 +1 1 0 1 -1 7 0 0 -1 0.000 1 0.0000 1722 1781 820 821 1722 1781 1167 1178 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1 + 2329 2332 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 2324 1224 2324 2336 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2 + 900 1776 2324 1776 +2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2 + 2324 1989 2516 1989 +-6 +2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 27 + 1395 1777 1400 1857 1405 1935 1407 2010 1417 2070 1425 2137 + 1440 2215 1455 2297 1470 2365 1490 2437 1510 2495 1527 2547 + 1535 2580 1600 2595 1672 2605 1772 2602 1865 2595 1947 2572 + 2005 2555 2075 2525 2150 2482 2207 2442 2260 2400 2295 2367 + 2325 2332 2325 1775 1395 1777 +2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 16 + 2330 1222 2365 1265 2402 1317 2437 1382 2477 1455 2500 1517 + 2520 1585 2532 1645 2540 1712 2542 1780 2540 1842 2535 1907 + 2527 1957 2517 1990 2325 1987 2330 1222 +4 0 0 101 0 0 11 0.0000 4 105 780 1331 3044 XU - X - B\001 +4 0 0 101 0 0 11 0.0000 4 150 1260 1113 3314 undefined_functions\001 +4 0 0 100 0 0 10 0.0000 4 135 1005 1275 3525 (modules mode)\001 +-6 diff --git a/lib/tools/doc/src/venn2.gif b/lib/tools/doc/src/venn2.gif Binary files differnew file mode 100644 index 0000000000..4cfea24646 --- /dev/null +++ b/lib/tools/doc/src/venn2.gif diff --git a/lib/tools/doc/src/venn2.ps b/lib/tools/doc/src/venn2.ps new file mode 100644 index 0000000000..198ccf285c --- /dev/null +++ b/lib/tools/doc/src/venn2.ps @@ -0,0 +1,284 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: venn2b.eps +%%Creator: fig2dev Version 3.2.3 Patchlevel +%%CreationDate: Tue Oct 9 11:12:20 2001 +%%For: hasse@ulmo2 (Hans Bolinder) +%%BoundingBox: 0 0 409 157 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 157 moveto 0 0 lineto 409 0 lineto 409 157 lineto closepath clip newpath +% Fill background color +0 0 moveto 409 0 lineto 409 157 lineto 0 157 lineto +closepath 1.00 1.00 1.00 setrgbcolor fill + +-53.0 212.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/reencdict 12 dict def /ReEncode { reencdict begin +/newcodesandnames exch def /newfontname exch def /basefontname exch def +/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def +basefontdict { exch dup /FID ne { dup /Encoding eq +{ exch dup length array copy newfont 3 1 roll put } +{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall +newfont /FontName newfontname put newcodesandnames aload pop +128 1 255 { newfont /Encoding get exch /.notdef put } for +newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat +newfontname newfont definefont pop end } def +/isovec [ +8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde +8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis +8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron +8#220 /dotlessi 8#230 /oe 8#231 /OE +8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling +8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis +8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot +8#255 /hypen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus +8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph +8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine +8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf +8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute +8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring +8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute +8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute +8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve +8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply +8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex +8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave +8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring +8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute +8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute +8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve +8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide +8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex +8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def +/Times-Roman /Times-Roman-iso isovec ReEncode + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.06000 0.06000 sc +% Polyline +n 4026 977 m 4011 1025 l 3996 1072 l 3981 1120 l 3966 1177 l 3954 1225 l + 3944 1272 l 3929 1327 l 3919 1412 l 3909 1477 l 3899 1540 l + 3894 1592 l 3894 1642 l 3891 1697 l 3889 1742 l 3889 1770 l + 3394 1767 l 3396 1717 l 3399 1665 l 3409 1610 l 3424 1555 l + 3439 1502 l 3464 1440 l 3489 1390 l 3516 1340 l 3551 1292 l + 3584 1250 l 3631 1200 l 3679 1150 l 3731 1110 l 3801 1065 l + 3869 1030 l 3931 1005 l 3986 982 l 4009 980 l + cp gs 0.75 setgray ef gr +/Times-Roman-iso ff 165.00 scf sf +3965 3044 m +gs 1 -1 sc (X - XU) col0 sh gr +/Times-Roman-iso ff 165.00 scf sf +3688 3299 m +gs 1 -1 sc (exports_not_used) col0 sh gr +% Polyline +n 6107 1757 m 6104 1802 l 6099 1855 l 6094 1902 l 6084 1960 l 6072 2010 l + 6062 2052 l 6049 2092 l 6032 2122 l 6019 2160 l 6007 2180 l + 5984 2140 l 5962 2095 l 5944 2057 l 5929 2007 l 5909 1947 l + 5899 1892 l 5892 1835 l 5889 1800 l 5889 1775 l 5889 1755 l + + cp gs 0.75 setgray ef gr +% Polyline +n 7309 1757 m 7309 2315 l 7287 2340 l 7259 2365 l 7234 2390 l 7199 2412 l + 7164 2440 l 7124 2465 l 7092 2482 l 7054 2502 l 7014 2520 l + 6974 2535 l 6934 2547 l 6897 2557 l 6909 2510 l 6924 2457 l + 6942 2407 l 6954 2357 l 6967 2297 l 6979 2247 l 6992 2192 l + 6999 2142 l 7009 2095 l 7012 2045 l 7019 1990 l 7022 1945 l + 7027 1900 l 7029 1855 l 7029 1805 l 7032 1765 l 7029 1752 l + + cp gs 0.75 setgray ef gr +/Times-Roman-iso ff 165.00 scf sf +6000 3014 m +gs 1 -1 sc (L * \(UU + \(XU - LU\)\)) col0 sh gr +/Times-Roman-iso ff 165.00 scf sf +5850 3299 m +gs 1 -1 sc (locals_not_used \(simplified\)) col0 sh gr +% Polyline +n 1395 1777 m 1400 1857 l 1405 1935 l 1407 2010 l 1417 2070 l 1425 2137 l + 1440 2215 l 1455 2297 l 1470 2365 l 1490 2437 l 1510 2495 l + 1527 2547 l 1535 2580 l 1600 2595 l 1672 2605 l 1772 2602 l + 1865 2595 l 1947 2572 l 2005 2555 l 2075 2525 l 2150 2482 l + 2207 2442 l 2260 2400 l 2295 2367 l 2325 2332 l 2325 1775 l + + cp gs 0.75 setgray ef gr +% Polyline +n 2330 1222 m 2365 1265 l 2402 1317 l 2437 1382 l 2477 1455 l 2500 1517 l + 2520 1585 l 2532 1645 l 2540 1712 l 2542 1780 l 2540 1842 l + 2535 1907 l 2527 1957 l 2517 1990 l 2325 1987 l + cp gs 0.75 setgray ef gr +/Times-Roman-iso ff 165.00 scf sf +1331 3044 m +gs 1 -1 sc (XU - X - B) col0 sh gr +/Times-Roman-iso ff 165.00 scf sf +1113 3314 m +gs 1 -1 sc (undefined_functions) col0 sh gr +% Polyline +7.500 slw +n 4816 1982 m + 5008 1982 l gs 0.95 setgray ef gr gs col0 s gr +% Polyline +n 7308 1967 m + 7500 1967 l gs 0.95 setgray ef gr gs col0 s gr +% Polyline +n 2324 1989 m + 2516 1989 l gs 0.95 setgray ef gr gs col0 s gr +/Times-Roman-iso ff 150.00 scf sf +1275 3525 m +gs 1 -1 sc (\(modules mode\)) col0 sh gr +% Arc +n 2652.5 1773.5 960.5 -25.7 25.7 arc +gs col-1 s gr + +% Arc +n 6307.0 1773.0 2416.0 160.6 -160.6 arc +gs col-1 s gr + +% Arc +n 2105.3 1773.0 2432.7 -19.2 19.2 arc +gs col-1 s gr + +% Ellipse +n 4214 1774 820 821 0 360 DrawEllipse gs col-1 s gr + +% Polyline +n 4817 2325 m 4825 2325 l gs col-1 s gr +% Polyline +n 4816 1217 m + 4816 2329 l gs col-1 s gr +% Polyline +n 3392 1769 m + 4816 1769 l gs col-1 s gr +% Arc +n 5144.5 1758.5 960.5 -25.7 25.7 arc +gs col-1 s gr + +% Arc +n 8799.0 1758.0 2416.0 160.6 -160.6 arc +gs col-1 s gr + +% Arc +n 4597.3 1758.0 2432.7 -19.2 19.2 arc +gs col-1 s gr + +% Ellipse +n 6706 1759 820 821 0 360 DrawEllipse gs col-1 s gr + +% Polyline +n 7309 2310 m 7317 2310 l gs col-1 s gr +% Polyline +n 7308 1202 m + 7308 2314 l gs col-1 s gr +% Polyline +n 5884 1754 m + 7308 1754 l gs col-1 s gr +% Arc +n 160.5 1780.5 960.5 -25.7 25.7 arc +gs col-1 s gr + +% Arc +n 3815.0 1780.0 2416.0 160.6 -160.6 arc +gs col-1 s gr + +% Arc +n -386.7 1780.0 2432.7 -19.2 19.2 arc +gs col-1 s gr + +% Ellipse +n 1722 1781 820 821 0 360 DrawEllipse gs col-1 s gr + +% Polyline +n 2325 2332 m 2333 2332 l gs col-1 s gr +% Polyline +n 2324 1224 m + 2324 2336 l gs col-1 s gr +% Polyline +n 900 1776 m + 2324 1776 l gs col-1 s gr +$F2psEnd +rs diff --git a/lib/tools/doc/src/warning.gif b/lib/tools/doc/src/warning.gif Binary files differnew file mode 100644 index 0000000000..96af52360e --- /dev/null +++ b/lib/tools/doc/src/warning.gif diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml new file mode 100644 index 0000000000..6fff68fe9f --- /dev/null +++ b/lib/tools/doc/src/xref.xml @@ -0,0 +1,1554 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2000</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>xref</title> + <prepared>Hans Bolinder</prepared> + <responsible>nobody</responsible> + <docno></docno> + <approved>nobody</approved> + <checked>no</checked> + <date>2000-08-15</date> + <rev>PA1</rev> + <file>xref.sgml</file> + </header> + <module>xref</module> + <modulesummary>A Cross Reference Tool for analyzing dependencies between functions, modules, applications and releases.</modulesummary> + <description> + <p>Xref is a cross reference tool that can be used for finding + dependencies between functions, modules, applications and + releases. + </p> + <p>Calls between functions are either <marker id="local_call"></marker> +<em>local calls</em> like <c>f()</c>, or <marker id="external_call"></marker> +<em>external calls</em> like + <c>m:f()</c>. <marker id="module_data"></marker> +<em>Module data</em>, + which are extracted from BEAM files, include local functions, + exported functions, local calls and external calls. By default, + calls to built-in functions (<term id="BIF"></term>) are ignored, but + if the option <c>builtins</c>, accepted by some of this + module's functions, is set to <c>true</c>, calls to BIFs + are included as well. It is the analyzing OTP version that + decides what functions are BIFs. Functional objects are assumed + to be called where they are created (and nowhere else). <marker id="unresolved_call"></marker> +<em>Unresolved calls</em> are calls to + <c>apply</c> or <c>spawn</c> with variable module, variable + function, or variable arguments. Examples are <c>M:F(a)</c>, + <c>apply(M, f, [a])</c>, and + <c>spawn(m, f(), Args)</c>. Unresolved calls are + represented by calls where variable modules have been replaced + with the atom <c>'$M_EXPR'</c>, variable functions have been + replaced with the atom <c>'$F_EXPR'</c>, and variable number of + arguments have been replaced with the number <c>-1</c>. The + above mentioned examples are represented by calls to + <c>'$M_EXPR':'$F_EXPR'/1</c>, <c>'$M_EXPR':f/1</c>, and + <c>m:'$F_EXPR'/-1</c>. The unresolved calls are a subset of the + external calls. + </p> + <warning> + <p>Unresolved calls make module data incomplete, which + implies that the results of analyses may be invalid.</p> + </warning> + <p><em>Applications</em> are collections of modules. The + modules' BEAM files are located in the <c>ebin</c> + subdirectory of the application directory. The name of the + application directory determines the name and version of the + application. + <em>Releases</em> are collections of applications + located in the <c>lib</c> subdirectory of the release directory. + There is more to read about applications and releases in the + Design Principles book. + </p> + <p> <marker id="xref_server"></marker> +<em>Xref servers</em> are identified + by names, supplied when creating new servers. Each Xref server + holds a set of releases, a set of applications, and a set of + modules with module data. Xref servers are independent of each + other, and all analyses are evaluated in the context of one + single Xref server (exceptions are the functions <c>m/1</c> and + <c>d/1</c> which do not use servers at all). The <marker id="mode"></marker> +<em>mode</em> of an Xref server determines what module + data are extracted from BEAM files as modules are added to the + server. Starting with R7, BEAM files compiled with the option + <c>debug_info</c> contain so called <marker id="debug_info"></marker> +debug information, which is an abstract + representation of the code. In <c>functions</c> mode, which is + the default mode, function calls and line numbers are extracted + from debug information. In <c>modules</c> mode, debug + information is ignored if present, but dependencies between + modules are extracted from other parts of the BEAM files. The + <c>modules</c> mode is significantly less time and space + consuming than the <c>functions</c> mode, but the analyses that + can be done are limited. + </p> + <p>An <marker id="analyzed_module"></marker> +<em>analyzed module</em> is a + module that has been added to an Xref server together with its + module data. + A <marker id="library_module"></marker> +<em>library module</em> is a + module located in some directory mentioned in the <marker id="library_path"></marker> +<em>library path</em>. + A library module is said to be used if some of its exported + functions are used by some analyzed module. + An <marker id="unknown_module"></marker> +<em>unknown module</em> is a + module that is neither an analyzed module nor a library module, + but whose exported functions are used by some analyzed module. + An <marker id="unknown_function"></marker> +<em>unknown function</em> is a + used function that is neither local or exported by any + analyzed module nor exported by any library module. + An <marker id="undefined_function"></marker> +<em>undefined function</em> is an externally used function that + is not exported by any analyzed module or library module. With + this notion, a local function can be an undefined function, namely + if it is externally used from some module. All unknown functions + are also undefined functions; there is a <seealso marker="xref_chapter#venn2">figure</seealso> in the + User's Guide that illustrates this relationship. + </p> + <p>Starting with R9C, the module attribute tag <c>deprecated</c> + can be used to inform Xref about <marker id="deprecated_function"></marker> +<em>deprecated functions</em> and + optionally when functions are planned to be removed. A few + examples show the idea: + </p> + <taglist> + <tag>-deprecated({f,1}).</tag> + <item>The exported function <c>f/1</c> is deprecated. Nothing is + said whether <c>f/1</c> will be removed or not.</item> + <tag>-deprecated({f,'_'}).</tag> + <item>All exported functions <c>f/0</c>, <c>f/1</c> and so on are + deprecated.</item> + <tag>-deprecated(module).</tag> + <item>All exported functions in the module are deprecated. + Equivalent to <c>-deprecated({'_','_'}).</c>.</item> + <tag>-deprecated([{g,1,next_version}]).</tag> + <item>The function <c>g/1</c> is deprecated and will be + removed in next version.</item> + <tag>-deprecated([{g,2,next_major_release}]).</tag> + <item>The function <c>g/2</c> is deprecated and will be + removed in next major release.</item> + <tag>-deprecated([{g,3,eventually}]).</tag> + <item>The function <c>g/3</c> is deprecated and will + eventually be removed.</item> + <tag>-deprecated({'_','_',eventually}).</tag> + <item>All exported functions in the module are deprecated and + will eventually be removed.</item> + </taglist> + <p>Before any analysis can take place, module data must be <em>set up</em>. For instance, the cross reference and the unknown + functions are computed when all module data are known. The + functions that need complete data (<c>analyze</c>, <c>q</c>, + <c>variables</c>) take care of setting up data automatically. + Module data need to be set up (again) after calls to any of the + <c>add</c>, <c>replace</c>, <c>remove</c>, + <c>set_library_path</c> or <c>update</c> functions. + </p> + <p>The result of setting up module data is the <marker id="call_graph"></marker> +<em>Call Graph</em>. A (directed) graph + consists of a set of vertices and a set of (directed) edges. The + edges represent <marker id="call"></marker> +<em>calls</em> (From, To) + between functions, modules, applications or releases. From is + said to call To, and To is said to be used by From. The vertices + of the Call Graph are the functions of all module data: local + and exported functions of analyzed modules; used BIFs; used + exported functions of library modules; and unknown functions. + The functions <c>module_info/0,1</c> added by the compiler are + included among the exported functions, but only when called from + some module. The edges are the function calls of all module + data. A consequence of the edges being a set is that there is + only one edge if a function is locally or externally used + several times on one and the same line of code. + </p> + <p>The Call Graph is <marker id="representation"></marker> +represented by + Erlang terms (the sets are lists), which is suitable for many + analyses. But for analyses that look at chains of calls, a list + representation is much too + slow. Instead the representation offered by the <c>digraph</c> + module is used. The translation of the list representation of + the Call Graph - or a subgraph thereof - to the <c>digraph</c> + representation does not + come for free, so the language used for expressing queries to be + described below has a special operator for this task and a + possibility to save the <c>digraph</c> representation for + subsequent analyses. + </p> + <p>In addition to the Call Graph there is a graph called the + <marker id="inter_call_graph"></marker> +<em>Inter Call Graph</em>. This is + a graph of calls (From, To) such that there is a chain of + calls from From to To in the Call Graph, and every From and To + is an exported function or an unused local function. + The vertices are the same as for the Call Graph. + </p> + <p>Calls between modules, applications and releases are also + directed graphs. The <marker id="type"></marker> +<em>types</em> + of the vertices and edges of these graphs are (ranging from the + most special to the most general): + <c>Fun</c> for functions; <c>Mod</c> for modules; + <c>App</c> for applications; and <c>Rel</c> for releases. + The following paragraphs will describe the different constructs + of the language used for selecting and analyzing parts of the + graphs, beginning with the <marker id="constants"></marker> +<em>constants</em>: + </p> + <list type="bulleted"> + <item>Expression ::= Constants</item> + <item>Constants ::= Consts | Consts <c>:</c> Type | RegExpr</item> + <item>Consts ::= Constant | <c>[</c>Constant<c>,</c> ...<c>]</c> + | <c>{</c>Constant<c>,</c> ...<c>}</c></item> + <item>Constant ::= Call | Const</item> + <item>Call ::= FunSpec <c>-></c> FunSpec + | <c>{</c>MFA<c>,</c> MFA<c>}</c> + | AtomConst <c>-></c> AtomConst + | <c>{</c>AtomConst<c>,</c> AtomConst<c>}</c></item> + <item>Const ::= AtomConst | FunSpec | MFA</item> + <item>AtomConst ::= Application | Module | Release</item> + <item>FunSpec ::= Module <c>:</c> Function <c>/</c> Arity</item> + <item>MFA ::= + <c>{</c>Module<c>,</c> Function<c>,</c> Arity<c>}</c></item> + <item>RegExpr ::= RegString <c>:</c> Type + | RegFunc + | RegFunc <c>:</c> Type</item> + <item>RegFunc ::= RegModule <c>:</c> RegFunction <c>/</c> RegArity</item> + <item>RegModule ::= RegAtom</item> + <item>RegFunction ::= RegAtom</item> + <item>RegArity ::= RegString | Number | <c>_</c> | <c>-1</c></item> + <item>RegAtom ::= RegString | Atom | <c>_</c></item> + <item>RegString ::= - a regular expression, as described in the + <c>regexp</c> module, enclosed in double quotes -</item> + <item>Type ::= <c>Fun</c> | <c>Mod</c> | <c>App</c> | <c>Rel</c></item> + <item>Function ::= Atom</item> + <item>Application ::= Atom</item> + <item>Module ::= Atom</item> + <item>Release ::= Atom</item> + <item>Arity ::= Number | <c>-1</c></item> + <item>Atom ::= - same as Erlang atoms -</item> + <item>Number ::= - same as non-negative Erlang integers -</item> + </list> + <p>Examples of constants are: <c>kernel</c>, <c>kernel->stdlib</c>, + <c>[kernel, sasl]</c>, <c>[pg -> mnesia, {tv, mnesia}] : Mod</c>. + It is an error if an instance of <c>Const</c> does not match any + vertex of any graph. + If there are more than one vertex matching an untyped instance + of <c>AtomConst</c>, then the one of the most general type is + chosen. + A list of constants is interpreted as a set of constants, all of + the same type. + A tuple of constants constitute a chain of calls (which may, + but does not have to, correspond to an actual chain of calls of + some graph). + Assigning a type to a list or tuple of <c>Constant</c> is + equivalent to assigning the type to each <c>Constant</c>. + </p> + <p> <marker id="regexp"></marker> +<em>Regular expressions</em> are used as a + means to select some of the vertices of a graph. + A <c>RegExpr</c> consisting of a <c>RegString</c> and a type - + an example is <c>"xref_.*" : Mod</c> - is interpreted as those + modules (or applications or releases, depending on the type) + that match the expression. + Similarly, a <c>RegFunc</c> is interpreted as those vertices + of the Call Graph that match the expression. + An example is <c>"xref_.*":"add_.*"/"(2|3)"</c>, which matches + all <c>add</c> functions of arity two or three of any of the + xref modules. + Another example, one that matches all functions of arity 10 or + more: <c>_:_/"[1-9].+"</c>. Here <c>_</c> is an abbreviation for + <c>".*"</c>, that is, the regular expression that matches + anything. + </p> + <p>The syntax of <marker id="variable"></marker> +<em>variables</em> is + simple: + </p> + <list type="bulleted"> + <item>Expression ::= Variable</item> + <item>Variable ::= - same as Erlang variables -</item> + </list> + <p>There are two kinds of variables: predefined variables and user + variables. + <marker id="predefined_variable"></marker> +<em>Predefined variables</em> + hold set up module data, and cannot be assigned to but only used + in queries. + <marker id="user_variable"></marker> +<em>User variables</em> on the other + hand can be assigned to, and are typically used for + temporary results while evaluating a query, and for keeping + results of queries for use in subsequent queries. + The predefined variables are (variables marked with (*) are + available in <c>functions</c> mode only): + </p> + <taglist> + <tag><c>E</c></tag> + <item>Call Graph Edges (*).</item> + <tag><c>V</c></tag> + <item>Call Graph Vertices (*). + </item> + <tag><c>M</c></tag> + <item>Modules. All modules: analyzed modules, used library + modules, and unknown modules.</item> + <tag><c>A</c></tag> + <item>Applications.</item> + <tag><c>R</c></tag> + <item>Releases. + </item> + <tag><c>ME</c></tag> + <item>Module Edges. All module calls.</item> + <tag><c>AE</c></tag> + <item>Application Edges. All application calls. </item> + <tag><c>RE</c></tag> + <item>Release Edges. All release calls. + </item> + <tag><c>L</c></tag> + <item>Local Functions (*). All local functions of analyzed modules.</item> + <tag><c>X</c></tag> + <item>Exported Functions. All exported functions of analyzed + modules and all used exported functions of library modules.</item> + <tag><c>F</c></tag> + <item>Functions (*).</item> + <tag><c>B</c></tag> + <item>Used BIFs. <c>B</c> is empty if <c>builtins</c> is + <c>false</c> for all analyzed modules.</item> + <tag><c>U</c></tag> + <item>Unknown Functions.</item> + <tag><c>UU</c></tag> + <item>Unused Functions (*). All local and exported functions of + analyzed modules that have not been used. </item> + <tag><c>XU</c></tag> + <item>Externally Used Functions. Functions of all modules - + including local functions - that have been used in some + external call.</item> + <tag><c>LU</c></tag> + <item>Locally Used Functions (*). Functions of all modules that have + been used in some local call. + </item> + <tag><c>LC</c></tag> + <item>Local Calls (*).</item> + <tag><c>XC</c></tag> + <item>External Calls (*). + </item> + <tag><c>AM</c></tag> + <item>Analyzed Modules.</item> + <tag><c>UM</c></tag> + <item>Unknown Modules.</item> + <tag><c>LM</c></tag> + <item>Used Library Modules. + </item> + <tag><c>UC</c></tag> + <item>Unresolved Calls. Empty in <c>modules</c> mode. + </item> + <tag><c>EE</c></tag> + <item>Inter Call Graph Edges (*). + </item> + <tag><c>DF</c></tag> + <item>Deprecated Functions. All deprecated exported + functions and all used deprecated BIFs.</item> + <tag><c>DF_1</c></tag> + <item>Deprecated Functions. All deprecated functions + to be removed in next version.</item> + <tag><c>DF_2</c></tag> + <item>Deprecated Functions. All deprecated functions + to be removed in next version or next major release.</item> + <tag><c>DF_3</c></tag> + <item>Deprecated Functions. All deprecated functions to be + removed in next version, next major release, or later.</item> + </taglist> + <p>These are a few <marker id="simple_facts"></marker> +facts about the + predefined variables (the set operators <c>+</c> (union) and + <c>-</c> (difference) as well as the cast operator + <c>(</c>Type<c>)</c> are described below): + </p> + <list type="bulleted"> + <item><c>F</c> is equal to <c>L + X</c>.</item> + <item><c>V</c> is equal to <c>X + L + B + U</c>, where <c>X</c>, + <c>L</c>, <c>B</c> and <c>U</c> are pairwise disjoint (that + is, have no elements in common).</item> + <item><c>UU</c> is equal to <c>V - (XU + LU)</c>, where + <c>LU</c> and <c>XU</c> may have elements in common. Put in + another way:</item> + <item><c>V</c> is equal to <c>UU + XU + LU</c>.</item> + <item><c>E</c> is equal to <c>LC + XC</c>. Note that <c>LC</c> + and <c>XC</c> may have elements in common, namely if some + function is locally and externally used from one and the same + function.</item> + <item><c>U</c> is a subset of <c>XU</c>.</item> + <item><c>B</c> is a subset of <c>XU</c>.</item> + <item><c>LU</c> is equal to <c>range LC</c>.</item> + <item><c>XU</c> is equal to <c>range XC</c>.</item> + <item><c>LU</c> is a subset of <c>F</c>.</item> + <item><c>UU</c> is a subset of <c>F</c>. </item> + <item><c>range UC</c> is a subset of <c>U</c>.</item> + <item><c>M</c> is equal to <c>AM + LM + UM</c>, where <c>AM</c>, + <c>LM</c> and <c>UM</c> are pairwise disjoint. </item> + <item><c>ME</c> is equal to <c>(Mod) E</c>.</item> + <item><c>AE</c> is equal to <c>(App) E</c>.</item> + <item><c>RE</c> is equal to <c>(Rel) E</c>.</item> + <item><c>(Mod) V</c> is a subset of <c>M</c>. Equality holds + if all analyzed modules have some local, exported, or unknown + function.</item> + <item><c>(App) M</c> is a subset of <c>A</c>. Equality holds + if all applications have some module.</item> + <item><c>(Rel) A</c> is a subset of <c>R</c>. Equality holds + if all releases have some application.</item> + <item><c>DF_1</c> is a subset of <c>DF_2</c>.</item> + <item><c>DF_2</c> is a subset of <c>DF_3</c>.</item> + <item><c>DF_3</c> is a subset of <c>DF</c>.</item> + <item><c>DF</c> is a subset of <c>X + B</c>.</item> + </list> + <p>An important notion is that of <marker id="conversion"></marker> +<em>conversion</em> of expressions. The syntax of + a cast expression is: + </p> + <list type="bulleted"> + <item>Expression ::= <c>(</c> Type <c>)</c> Expression</item> + </list> + <p>The interpretation of the cast operator depends on the named + type <c>Type</c>, the type of <c>Expression</c>, and the + structure of the elements of the interpretation of <c>Expression</c>. + If the named type is equal to the + expression type, no conversion is done. Otherwise, the + conversion is done one step at a time; + <c>(Fun) (App) RE</c>, for instance, is equivalent to + <c>(Fun) (Mod) (App) RE</c>. Now assume that the + interpretation of <c>Expression</c> is a set of constants + (functions, modules, applications or releases). If the named + type is more general than the expression type, say <c>Mod</c> + and <c>Fun</c> respectively, then the interpretation of the cast + expression is the set of modules that have at least one + of their functions mentioned in the interpretation of the + expression. If the named + type is more special than the expression type, say <c>Fun</c> + and <c>Mod</c>, then the interpretation is the set of all the + functions of the modules (in <c>modules</c> mode, the conversion + is partial since the local functions are not known). + The conversions to and from applications and releases + work analogously. For instance, <c>(App) "xref_.*" : Mod</c> + returns all applications containing at least one module + such that <c>xref_</c> is a prefix of the module name. + </p> + <p>Now assume that the interpretation of <c>Expression</c> is a + set of calls. If the named type is more general than the + expression type, say <c>Mod</c> and <c>Fun</c> respectively, + then the interpretation of the cast expression is the set of + calls (M1, M2) such that the interpretation of the + expression contains a call from some function + of M1 to some function of M2. If the named type is more special + than the expression type, say <c>Fun</c> and <c>Mod</c>, then + the interpretation is the set of all function calls + (F1, F2) such that the interpretation of the expression + contains a call (M1, M2) and F1 is + a function of M1 and F2 is a function of M2 (in <c>modules</c> + mode, there are no functions calls, so a cast to <c>Fun</c> + always yields an empty set). Again, the conversions to and from + applications and releases work analogously. + </p> + <p>The interpretation of constants and variables are sets, and + those sets can be used as the basis for forming new sets by the + application of <marker id="set_operator"></marker> +<em>set operators</em>. + The syntax: + </p> + <list type="bulleted"> + <item>Expression ::= Expression BinarySetOp Expression</item> + <item>BinarySetOp ::= <c>+</c> | <c>*</c> | <c>-</c></item> + </list> + <p><c>+</c>, <c>*</c> and <c>-</c> are interpreted as union, + intersection and difference respectively: the union of two sets + contains the elements of both sets; the intersection of two sets + contains the elements common to both sets; and the difference of + two sets contains the elements of the first set that are not + members of the second set. The elements of the two sets must be + of the same structure; for instance, a function call cannot be + combined with a function. But if a cast operator can make the + elements compatible, then the more general elements are + converted to the less general element type. For instance, + <c>M + F</c> is equivalent to + <c>(Fun) M + F</c>, and <c>E - AE</c> + is equivalent to <c>E - (Fun) AE</c>. One more + example: <c>X * xref : Mod</c> is interpreted as the set of + functions exported by the module <c>xref</c>; <c>xref : Mod</c> + is converted to the more special type of <c>X</c> (<c>Fun</c>, + that is) yielding all functions of <c>xref</c>, and the + intersection with <c>X</c> (all functions exported by analyzed + modules and library modules) is interpreted as those functions + that are exported by some module <em>and</em> functions of + <c>xref</c>. + </p> + <p>There are also unary set operators: + </p> + <list type="bulleted"> + <item>Expression ::= UnarySetOp Expression</item> + <item>UnarySetOp ::= <c>domain</c> | <c>range</c> | <c>strict</c></item> + </list> + <p>Recall that a call is a pair (From, To). <c>domain</c> + applied to a set of calls is interpreted as the set of all + vertices From, and <c>range</c> as the set of all vertices To. + The interpretation of the <c>strict</c> operator is the operand + with all calls on the form (A, A) removed. + </p> + <p>The interpretation of the <marker id="restriction"></marker> +<em>restriction operators</em> is a + subset of the first operand, a set of calls. The second operand, + a set of vertices, is converted to the type of the first operand. + The syntax of the restriction operators: + </p> + <list type="bulleted"> + <item>Expression ::= Expression RestrOp Expression</item> + <item>RestrOp ::= <c>|</c></item> + <item>RestrOp ::= <c>||</c></item> + <item>RestrOp ::= <c>|||</c></item> + </list> + <p>The interpretation in some detail for the three operators: + </p> + <taglist> + <tag><c>|</c></tag> + <item>The subset of calls from any of the vertices.</item> + <tag><c>||</c></tag> + <item>The subset of calls to any of the vertices.</item> + <tag><c>|||</c></tag> + <item>The subset of calls to and from any of the vertices. + For all sets of calls <c>CS</c> and all sets of vertices + <c>VS</c>, <c>CS ||| VS </c> is equivalent to + <c>CS | VS * CS || VS</c>.</item> + </taglist> + <p> <marker id="graph_analyses"></marker> +Two functions (modules, + applications, releases) belong to the same strongly connected + component if they call each other (in)directly. The + interpretation of the <c>components</c> operator is the set of + strongly connected components of a set of calls. The + <c>condensation</c> of a set of calls is a new set of calls + between the strongly connected components such that there is an + edge between two components if there is some constant of the first + component that calls some constant of the second component. + </p> + <p>The interpretation of the <c>of</c> operator is a chain of + calls of the second operand (a set of calls) that passes throw + all of the vertices of the first operand (a tuple of + constants), in the given order. The second operand + is converted to the type of the first operand. + For instance, the <c>of</c> operator can be used for finding out + whether a function calls another function indirectly, and the + chain of calls demonstrates how. The syntax of the graph + analyzing operators: + </p> + <list type="bulleted"> + <item>Expression ::= Expression GraphOp Expression</item> + <item>GraphOp ::= <c>components</c> | <c>condensation</c> | <c>of</c></item> + </list> + <p>As was mentioned before, the graph analyses operate on + the <c>digraph</c> representation of graphs. + By default, the <c>digraph</c> representation is created when + needed (and deleted when no longer used), but it can also be + created explicitly by use of the <c>closure</c> operator: + </p> + <list type="bulleted"> + <item>Expression ::= ClosureOp Expression</item> + <item>ClosureOp ::= <c>closure</c></item> + </list> + <p>The interpretation of the <c>closure</c> operator is the + transitive closure of the operand. + </p> + <p>The restriction operators are defined for closures as well; + <c>closure E | xref : Mod</c> is + interpreted as the direct or indirect function calls from the + <c>xref</c> module, while the interpretation of + <c>E | xref : Mod</c> is the set of direct + calls from <c>xref</c>. + If some graph is to be used in several graph analyses, it saves + time to assign the <c>digraph</c> representation of the graph + to a user variable, + and then make sure that every graph analysis operates on that + variable instead of the list representation of the graph. + </p> + <p>The lines where functions are defined (more precisely: where + the first clause begins) and the lines where functions are used + are available in <c>functions</c> mode. The line numbers refer + to the files where the functions are defined. This holds also for + files included with the <c>-include</c> and <c>-include_lib</c> + directives, which may result in functions defined apparently in + the same line. The <em>line operators</em> are used for assigning + line numbers to functions and for assigning sets of line numbers + to function calls. + The syntax is similar to the one of the cast operator: + </p> + <list type="bulleted"> + <item>Expression ::= <c>(</c> LineOp<c>)</c> Expression</item> + <item>Expression ::= <c>(</c> XLineOp<c>)</c> Expression</item> + <item>LineOp ::= <c>Lin</c> | <c>ELin</c> | <c>LLin</c> | <c>XLin</c></item> + <item>XLineOp ::= <c>XXL</c></item> + </list> + <p>The interpretation of the <c>Lin</c> operator applied to a set + of functions assigns to each function the line number where the + function is defined. Unknown functions and functions of library + modules are assigned the number 0. + </p> + <p>The interpretation of some LineOp operator applied to a + set of function calls assigns to each call the set of line + numbers where the first function calls the second function. Not + all calls are assigned line numbers by all operators: + </p> + <list type="bulleted"> + <item>the <c>Lin</c> operator is defined for Call Graph Edges;</item> + <item>the <c>LLin</c> operator is defined for Local Calls.</item> + <item>the <c>XLin</c> operator is defined for External Calls.</item> + <item>the <c>ELin</c> operator is defined for Inter Call Graph Edges.</item> + </list> + <p>The <c>Lin</c> (<c>LLin</c>, <c>XLin</c>) operator assigns + the lines where calls (local calls, external calls) are made. + The <c>ELin</c> operator assigns to each call (From, To), + for which it is defined, every line L such that there is + a chain of calls from From to To beginning with a call on line + L. + </p> + <p>The <c>XXL</c> operator is defined for the interpretation of + any of the LineOp operators applied to a set of function + calls. The result is that of replacing the function call with + a line numbered function call, that is, each of the two + functions of the call is replaced by a pair of the function and + the line where the function is defined. The effect of the + <c>XXL</c> operator can be undone by the LineOp operators. For + instance, <c>(Lin) (XXL) (Lin) E</c> is + equivalent to <c>(Lin) E</c>. + </p> + <p>The <c>+</c>, <c>-</c>, <c>*</c> and <c>#</c> operators are + defined for line number expressions, provided the operands are + compatible. The LineOp operators are also defined for + modules, applications, and releases; the operand is implicitly + converted to functions. Similarly, the cast operator is defined + for the interpretation of the LineOp operators. + </p> + <p>The interpretation of the <marker id="count"></marker> +<em>counting operator</em> is the number of elements of a set. The operator + is undefined for closures. The <c>+</c>, <c>-</c> and <c>*</c> + operators are interpreted as the obvious arithmetical operators + when applied to numbers. The syntax of the counting operator: + </p> + <list type="bulleted"> + <item>Expression ::= CountOp Expression</item> + <item>CountOp ::= <c>#</c></item> + </list> + <p>All binary operators are left associative; for instance, + <c>A | B || C</c> is equivalent to + <c>(A | B) || C</c>. The following is a list + of all operators, in increasing order of <marker id="precedence"></marker> +<em>precedence</em>: + </p> + <list type="bulleted"> + <item><c>+</c>, <c>-</c></item> + <item><c>*</c></item> + <item><c>#</c></item> + <item><c>|</c>, <c>||</c>, <c>|||</c></item> + <item><c>of</c></item> + <item><c>(</c>Type<c>)</c></item> + <item><c>closure</c>, <c>components</c>, <c>condensation</c>, + <c>domain</c>, <c>range</c>, <c>strict</c></item> + </list> + <p>Parentheses are used for grouping, either to make an expression + more readable or to override the default precedence of operators: + </p> + <list type="bulleted"> + <item>Expression ::= <c>(</c> Expression <c>)</c></item> + </list> + <p>A <marker id="query"></marker> +<em>query</em> is a non-empty sequence of + statements. A statement is either an assignment of a user + variable or an expression. The value of an assignment is the + value of the right hand side expression. It makes no sense to + put a plain expression anywhere else but last in queries. The + syntax of queries is summarized by these productions: + </p> + <list type="bulleted"> + <item>Query ::= Statement<c>,</c> ...</item> + <item>Statement ::= Assignment | Expression</item> + <item>Assignment ::= Variable <c>:=</c> Expression + | Variable <c>=</c> Expression</item> + </list> + <p>A variable cannot be assigned a new value unless first removed. + Variables assigned to by the <c>=</c> operator are removed at + the end of the query, while variables assigned to by the + <c>:=</c> operator can only be removed by calls to + <c>forget</c>. There are no user variables when module data + need to be set up again; if any of the functions that make it + necessary to set up module data again is called, all user + variables are forgotten. + </p> + <p><em>Types</em></p> + <pre> +application() = atom() +arity() = int() | -1 +bool() = true | false +call() = {atom(), atom()} | funcall() +constant() = mfa() | module() | application() | release() +directory() = string() +file() = string() +funcall() = {mfa(), mfa()} +function() = atom() +int() = integer() >= 0 +library() = atom() +library_path() = path() | code_path +mfa() = {module(), function(), arity()} +mode() = functions | modules +module() = atom() +release() = atom() +string_position() = int() | at_end +variable() = atom() +xref() = atom() | pid() </pre> + </description> + <funcs> + <func> + <name>add_application(Xref, Directory [, Options]) -> {ok, application()} | Error</name> + <fsummary>Add the modules of an application.</fsummary> + <type> + <v>Directory = directory()</v> + <v>Error = {error, module(), Reason}</v> + <v>Options = [Option] | Option</v> + <v>Option = {builtins, bool()} | {name, application()} | {verbose, bool()} | {warnings, bool()}</v> + <v>Reason = {application_clash, {application(), directory(), directory()}} | {file_error, file(), error()} | {invalid_filename, term()} | {invalid_options, term()} | - see also add_directory -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Adds an application, the modules of the application and <seealso marker="#module_data">module data</seealso> of the + modules to an <seealso marker="#xref_server">Xref server</seealso>. + The modules will be members of the application. + The default is to use the base name of the + directory with the version removed as application name, but + this can be overridden by the <c>name</c> option. Returns the + name of the application. + </p> + <p>If the given directory has a subdirectory named + <c>ebin</c>, modules (BEAM files) are searched for in that + directory, otherwise modules are searched for in the given + directory. + </p> + <p>If the <seealso marker="#mode">mode</seealso> of the Xref + server is <c>functions</c>, BEAM files that contain no + <seealso marker="#debug_info">debug information</seealso> are + ignored. + </p> + </desc> + </func> + <func> + <name>add_directory(Xref, Directory [, Options]) -> {ok, Modules} | Error</name> + <fsummary>Add the modules in a directory.</fsummary> + <type> + <v>Directory = directory()</v> + <v>Error = {error, module(), Reason}</v> + <v>Modules = [module()]</v> + <v>Options = [Option] | Option</v> + <v>Option = {builtins, bool()} | {recurse, bool()} | {verbose, bool()} | {warnings, bool()}</v> + <v>Reason = {file_error, file(), error()} | {invalid_filename, term()} | {invalid_options, term()} | {unrecognized_file, file()} | - error from beam_lib:chunks/2 -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Adds the modules found in the given directory and the <seealso marker="#module_data">modules' data</seealso> + to an <seealso marker="#xref_server">Xref server</seealso>. + The default is not to examine subdirectories, but if the option + <c>recurse</c> has the value <c>true</c>, modules are searched + for in subdirectories on all levels as well as in the given + directory. + Returns a sorted list of the names of the added modules. + </p> + <p>The modules added will not be members of any applications. + </p> + <p>If the <seealso marker="#mode">mode</seealso> of the Xref + server is <c>functions</c>, BEAM files that contain no + <seealso marker="#debug_info">debug information</seealso> are + ignored. + </p> + </desc> + </func> + <func> + <name>add_module(Xref, File [, Options]) -> {ok, module()} | Error</name> + <fsummary>Add a module.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>File = file()</v> + <v>Options = [Option] | Option</v> + <v>Option = {builtins, bool()} | {verbose, bool()} | {warnings, bool()}</v> + <v>Reason = {file_error, file(), error()} | {invalid_filename, term()} | {invalid_options, term()} | {module_clash, {module(), file(), file()}} | {no_debug_info, file()} | - error from beam_lib:chunks/2 -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Adds a module and its <seealso marker="#module_data">module data</seealso> to an <seealso marker="#xref_server">Xref server</seealso>. + The module will not be member of any application. + Returns the name of the module. + </p> + <p>If the <seealso marker="#mode">mode</seealso> of the Xref + server is <c>functions</c>, and the BEAM file contains no + <seealso marker="#debug_info">debug information</seealso>, + the error message <c>no_debug_info</c> is returned. + </p> + </desc> + </func> + <func> + <name>add_release(Xref, Directory [, Options]) -> {ok, release()} | Error</name> + <fsummary>Add the modules of a release.</fsummary> + <type> + <v>Directory = directory()</v> + <v>Error = {error, module(), Reason}</v> + <v>Options = [Option] | Option</v> + <v>Option = {builtins, bool()} | {name, release()} | {verbose, bool()} | {warnings, bool()}</v> + <v>Reason = {application_clash, {application(), directory(), directory()}} | {file_error, file(), error()} | {invalid_filename, term()} | {invalid_options, term()} | {release_clash, {release(), directory(), directory()}} | - see also add_directory -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Adds a release, the applications of the release, the + modules of the applications, and <seealso marker="#module_data">module data</seealso> of the + modules to an <seealso marker="#xref_server">Xref server</seealso>. + The applications will be members of the release, + and the modules will be members of the applications. + The default is to use the base name of the + directory as release name, but this can be overridden by the + <c>name</c> option. Returns the name of the release. + </p> + <p>If the given directory has a subdirectory named <c>lib</c>, + the directories in that directory are assumed to be + application directories, otherwise all subdirectories of the + given directory are assumed to be application directories. + If there are several versions of some application, the one + with the highest version is chosen. + </p> + <p>If the <seealso marker="#mode">mode</seealso> of the Xref + server is <c>functions</c>, BEAM files that contain no + <seealso marker="#debug_info">debug information</seealso> are + ignored. + </p> + </desc> + </func> + <func> + <name>analyze(Xref, Analysis [, Options]) -> {ok, Answer} | Error</name> + <fsummary>Evaluate a predefined analysis.</fsummary> + <type> + <v>Analysis = undefined_function_calls | undefined_functions | locals_not_used | exports_not_used | deprecated_function_calls | {deprecated_function_calls, DeprFlag} | deprecated_functions | {deprecated_functions, DeprFlag} | {call, FuncSpec} | {use, FuncSpec} | {module_call, ModSpec} | {module_use, ModSpec} | {application_call, AppSpec} | {application_use, AppSpec} | {release_call, RelSpec} | {release_use, RelSpec}</v> + <v>Answer = [term()]</v> + <v>AppSpec = application() | [application()]</v> + <v>DeprFlag = next_version | next_major_release | eventually</v> + <v>Error = {error, module(), Reason}</v> + <v>FuncSpec = mfa() | [mfa()]</v> + <v>ModSpec = module() | [module()]</v> + <v>Options = [Option] | Option</v> + <v>Option = {verbose, bool()}</v> + <v>RelSpec = release() | [release()]</v> + <v>Reason = {invalid_options, term()} | {parse_error, string_position(), term()} | {unavailable_analysis, term()} | {unknown_analysis, term()} | {unknown_constant, string()} | {unknown_variable, variable()}</v> + <v>Xref = xref()</v> + </type> + <desc> + <p> <marker id="analyze"></marker> +Evaluates a predefined analysis. + Returns a sorted list without duplicates of <c>call()</c> or + <c>constant()</c>, depending on the chosen analysis. The + predefined analyses, which operate on all <seealso marker="#analyzed_module">analyzed modules</seealso>, are + (analyses marked with (*) are available in <c>functions</c><seealso marker="#mode">mode</seealso> only):</p> + <taglist> + <tag><c>undefined_function_calls</c>(*)</tag> + <item>Returns a list of calls to <seealso marker="#undefined_function">undefined functions</seealso>.</item> + <tag><c>undefined_functions</c></tag> + <item>Returns a list of <seealso marker="#undefined_function">undefined functions</seealso>. </item> + <tag><c>locals_not_used</c>(*)</tag> + <item>Returns a list of local functions that have not been + locally used.</item> + <tag><c>exports_not_used</c></tag> + <item>Returns a list of exported functions that have not been + externally used.</item> + <tag><c>deprecated_function_calls</c>(*)</tag> + <item>Returns a list of external calls to <seealso marker="#deprecated_function">deprecated functions</seealso>.</item> + <tag><c>{deprecated_function_calls, DeprFlag}</c>(*)</tag> + <item>Returns a list of external calls to deprecated + functions. If <c>DeprFlag</c> is equal to + <c>next_version</c>, calls to functions to be removed in + next version are returned. If <c>DeprFlag</c> is equal to + <c>next_major_release</c>, calls to functions to be + removed in next major release are returned as well as + calls to functions to be removed in next version. Finally, + if <c>DeprFlag</c> is equal to <c>eventually</c>, all + calls to functions to be removed are returned, including + calls to functions to be removed in next version or next + major release.</item> + <tag><c>deprecated_functions</c></tag> + <item>Returns a list of externally used deprecated + functions.</item> + <tag><c>{deprecated_functions, DeprFlag}</c></tag> + <item>Returns a list of externally used deprecated + functions. If <c>DeprFlag</c> is equal to + <c>next_version</c>, functions to be removed in next + version are returned. If <c>DeprFlag</c> is equal to + <c>next_major_release</c>, functions to be removed in next + major release are returned as well as functions to be + removed in next version. Finally, if <c>DeprFlag</c> is + equal to <c>eventually</c>, all functions to be removed + are returned, including functions to be removed in next + version or next major release.</item> + <tag><c>{call, FuncSpec}</c>(*)</tag> + <item>Returns a list of functions called by some of the given + functions.</item> + <tag><c>{use, FuncSpec}</c>(*)</tag> + <item>Returns a list of functions that use some of the given + functions.</item> + <tag><c>{module_call, ModSpec}</c></tag> + <item>Returns a list of modules called by some of the given + modules.</item> + <tag><c>{module_use, ModSpec}</c></tag> + <item>Returns a list of modules that use some of the given + modules.</item> + <tag><c>{application_call, AppSpec}</c></tag> + <item>Returns a list of applications called by some of the given + applications.</item> + <tag><c>{application_use, AppSpec}</c></tag> + <item>Returns a list of applications that use some of the given + applications.</item> + <tag><c>{release_call, RelSpec}</c></tag> + <item>Returns a list of releases called by some of the given + releases.</item> + <tag><c>{release_use, RelSpec}</c></tag> + <item>Returns a list of releases that use some of the given + releases.</item> + </taglist> + </desc> + </func> + <func> + <name>d(Directory) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name> + <fsummary>Check the modules in a directory using the code path.</fsummary> + <type> + <v>Directory = directory()</v> + <v>DebugInfoResult = {deprecated, [funcall()]} | {undefined, [funcall()]} | {unused, [mfa()]}</v> + <v>Error = {error, module(), Reason}</v> + <v>NoDebugInfoResult = {deprecated, [mfa()]} | {undefined, [mfa()]}</v> + <v>Reason = {file_error, file(), error()} | {invalid_filename, term()} | {unrecognized_file, file()} | - error from beam_lib:chunks/2 -</v> + </type> + <desc> + <p>The modules found in the given directory are checked for + calls to <seealso marker="#deprecated_function">deprecated functions</seealso>, calls to <seealso marker="#undefined_function">undefined functions</seealso>, + and for unused local functions. The code path is used as + <seealso marker="#library_path">library path</seealso>. + </p> + <p>If some of the found BEAM files contain <seealso marker="#debug_info">debug information</seealso>, then those + modules are checked and a list of tuples is returned. The + first element of each tuple is one of: + </p> + <list type="bulleted"> + <item><c>deprecated</c>, the second element is a sorted list + of calls to deprecated functions;</item> + <item><c>undefined</c>, the second element is a sorted list + of calls to undefined functions;</item> + <item><c>unused</c>, the second element is a sorted list of + unused local functions.</item> + </list> + <p>If no BEAM file contains debug information, then a list of + tuples is returned. The first element of each tuple is one + of: + </p> + <list type="bulleted"> + <item><c>deprecated</c>, the second element is a sorted list + of externally used deprecated functions;</item> + <item><c>undefined</c>, the second element is a sorted list + of undefined functions.</item> + </list> + </desc> + </func> + <func> + <name>forget(Xref) -> ok</name> + <name>forget(Xref, Variables) -> ok | Error</name> + <fsummary>Remove user variables and their values.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>Reason = {not_user_variable, term()}</v> + <v>Variables = [variable()] | variable()</v> + <v>Xref = xref()</v> + </type> + <desc> + <p><c>forget/1</c> and <c>forget/2</c> remove all or some of + the <seealso marker="#user_variable">user variables</seealso> of an <seealso marker="#xref_server">xref server</seealso>.</p> + </desc> + </func> + <func> + <name>format_error(Error) -> Chars</name> + <fsummary>Return an English description of an Xref error reply.</fsummary> + <type> + <v>Error = {error, module(), term()}</v> + <v>Chars = [char() | Chars]</v> + </type> + <desc> + <p>Given the error returned by any function of this module, + the function <c>format_error</c> returns a descriptive string + of the error in English. For file errors, the function + <c>format_error/1</c> in the <c>file</c> module is called.</p> + </desc> + </func> + <func> + <name>get_default(Xref) -> [{Option, Value}]</name> + <name>get_default(Xref, Option) -> {ok, Value} | Error</name> + <fsummary>Return the default values of options.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>Option = builtins | recurse | verbose | warnings</v> + <v>Reason = {invalid_options, term()}</v> + <v>Value = bool()</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Returns the default values of one or more options.</p> + </desc> + </func> + <func> + <name>get_library_path(Xref) -> {ok, LibraryPath}</name> + <fsummary>Return the library path.</fsummary> + <type> + <v>LibraryPath = library_path()</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Returns the <seealso marker="#library_path">library path</seealso>.</p> + </desc> + </func> + <func> + <name>info(Xref) -> [Info]</name> + <name>info(Xref, Category) -> [{Item, [Info]}]</name> + <name>info(Xref, Category, Items) -> [{Item, [Info]}]</name> + <fsummary>Return information about an Xref server.</fsummary> + <type> + <v>Application = [] | [application()]</v> + <v>Category = modules | applications | releases | libraries</v> + <v>Info = {application, Application} | {builtins, bool()} | {directory, directory()} | {library_path, library_path()} | {mode, mode()} | {no_analyzed_modules, int()} | {no_applications, int()} | {no_calls, {NoResolved, NoUnresolved}} | {no_function_calls, {NoLocal, NoResolvedExternal, NoUnresolved}} | {no_functions, {NoLocal, NoExternal}} | {no_inter_function_calls, int()} | {no_releases, int()} | {release, Release} | {version, Version}</v> + <v>Item = module() | application() | release() | library()</v> + <v>Items = Item | [Item]</v> + <v>NoLocal = NoExternal = NoResolvedExternal, NoResolved = NoUnresolved = int()</v> + <v>Release = [] | [release()]</v> + <v>Version = [int()]</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>The <c>info</c> functions return information as a list of + pairs {Tag, term()} in some order about the state and the + <seealso marker="#module_data">module data</seealso> of an <seealso marker="#xref_server">Xref server</seealso>. + </p> + <p><c>info/1</c> returns information with the following tags + (tags marked with (*) are available in <c>functions</c> + mode only):</p> + <list type="bulleted"> + <item><c>library_path</c>, the <seealso marker="#library_path">library path</seealso>;</item> + <item><c>mode</c>, the <seealso marker="#mode">mode</seealso>;</item> + <item><c>no_releases</c>, number of releases;</item> + <item><c>no_applications</c>, total number of applications + (of all releases);</item> + <item><c>no_analyzed_modules</c>, total number of <seealso marker="#analyzed_module">analyzed modules</seealso>;</item> + <item><c>no_calls</c> (*), total number of calls (in all + modules), regarding instances of one function call in + different lines as separate calls;</item> + <item><c>no_function_calls</c> (*), total number of <seealso marker="#local_call">local calls</seealso>, resolved <seealso marker="#external_call">external calls</seealso> and + <seealso marker="#unresolved_call">unresolved calls</seealso>;</item> + <item><c>no_functions</c> (*), total number of local and exported + functions;</item> + <item><c>no_inter_function_calls</c> (*), total number of + calls of the <seealso marker="#inter_call_graph">Inter Call Graph</seealso>.</item> + </list> + <p><c>info/2</c> and <c>info/3</c> return information about + all or some of the analyzed modules, applications, releases + or library modules of an Xref server. + The following information is returned for every analyzed module:</p> + <list type="bulleted"> + <item><c>application</c>, an empty list if the module does + not belong to any application, otherwise a list of + the application name;</item> + <item><c>builtins</c>, whether calls to BIFs are included + in the module's data;</item> + <item><c>directory</c>, the directory where the + module's BEAM file is located;</item> + <item><c>no_calls</c> (*), number of calls, regarding + instances of one function call in different lines as + separate calls;</item> + <item><c>no_function_calls</c> (*), number of local + calls, resolved external calls and unresolved calls;</item> + <item><c>no_functions</c> (*), number of local and exported + functions;</item> + <item><c>no_inter_function_calls</c> (*), number of calls + of the Inter Call Graph;</item> + </list> + <p>The following information is returned for every application:</p> + <list type="bulleted"> + <item><c>directory</c>, the directory where the + modules' BEAM files are located;</item> + <item><c>no_analyzed_modules</c>, number of analyzed + modules;</item> + <item><c>no_calls</c> (*), number of calls of the + application's modules, regarding instances of + one function call in different lines as separate calls;</item> + <item><c>no_function_calls</c> (*), number of local + calls, resolved external calls and unresolved calls of the + application's modules;</item> + <item><c>no_functions</c> (*), number of local and exported + functions of the application's modules;</item> + <item><c>no_inter_function_calls</c> (*), number of calls + of the Inter Call Graph of the + application's modules;</item> + <item><c>release</c>, an empty list if the application does not + belong to any release, otherwise a list of the release name;</item> + <item><c>version</c>, the application's version as + a list of numbers. For instance, the directory "kernel-2.6" + results in the application name <c>kernel</c> and the + application version [2,6]; "kernel" yields the name + <c>kernel</c> and the version [].</item> + </list> + <p>The following information is returned for every release:</p> + <list type="bulleted"> + <item><c>directory</c>, the release directory;</item> + <item><c>no_analyzed_modules</c>, number of analyzed + modules;</item> + <item><c>no_applications</c>, number of applications;</item> + <item><c>no_calls</c> (*), number of calls of the + release's modules, regarding + instances of one function call in different lines as + separate calls;</item> + <item><c>no_function_calls</c> (*), number of local + calls, resolved external calls and unresolved + calls of the release's modules;</item> + <item><c>no_functions</c> (*), number of local and exported + functions of the release's modules;</item> + <item><c>no_inter_function_calls</c> (*), number of calls + of the Inter Call Graph of the release's modules.</item> + </list> + <p>The following information is returned for every library module:</p> + <list type="bulleted"> + <item><c>directory</c>, the directory where the <seealso marker="#library_module">library module's</seealso> BEAM file is located.</item> + </list> + <p>For every number of calls, functions etc. returned by the + <c>no_</c> tags, there is a query returning the same number. + Listed below are examples of such queries. Some of the + queries return the sum of a two or more of the <c>no_</c> + tags numbers. <c>mod</c> (<c>app</c>, <c>rel</c>) refers to + any module (application, release). + </p> + <list type="bulleted"> + <item> + <p><c>no_analyzed_modules</c></p> + <list type="bulleted"> + <item><c>"# AM"</c> (info/1)</item> + <item><c>"# (Mod) app:App"</c> + (application)</item> + <item><c>"# (Mod) rel:Rel"</c> (release)</item> + </list> + </item> + <item> + <p><c>no_applications</c></p> + <list type="bulleted"> + <item><c>"# A"</c> (info/1)</item> + </list> + </item> + <item> + <p><c>no_calls</c>. The sum of the number of resolved and + unresolved calls:</p> + <list type="bulleted"> + <item><c>"# (XLin) E + # (LLin) E"</c> (info/1)</item> + <item><c>"T = E | mod:Mod, # (LLin) T + # (XLin) T"</c> + (module)</item> + <item><c>"T = E | app:App, # (LLin) T + # (XLin) T"</c> + (application)</item> + <item><c>"T = E | rel:Rel, # (LLin) T + # (XLin) T"</c> + (release)</item> + </list> + </item> + <item> + <p><c>no_functions</c>. Functions in library modules and + the functions <c>module_info/0,1</c> are not counted by + <c>info</c>. Assuming that <c>"Extra := _:module_info/\\"(0|1)\\" + LM"</c> has been evaluated, the + sum of the number of local and exported functions are:</p> + <list type="bulleted"> + <item><c>"# (F - Extra)"</c> (info/1)</item> + <item><c>"# (F * mod:Mod - Extra)"</c> (module)</item> + <item><c>"# (F * app:App - Extra)"</c> (application)</item> + <item><c>"# (F * rel:Rel - Extra)"</c> (release)</item> + </list> + </item> + <item> + <p><c>no_function_calls</c>. The sum of the number of + local calls, resolved external calls and unresolved calls:</p> + <list type="bulleted"> + <item><c>"# LC + # XC"</c> (info/1)</item> + <item><c>"# LC | mod:Mod + # XC | mod:Mod"</c> (module)</item> + <item><c>"# LC | app:App + # XC | app:App"</c> (application)</item> + <item><c>"# LC | rel:Rel + # XC | mod:Rel"</c> (release)</item> + </list> + </item> + <item> + <p><c>no_inter_function_calls</c></p> + <list type="bulleted"> + <item><c>"# EE"</c> (info/1)</item> + <item><c>"# EE | mod:Mod"</c> (module)</item> + <item><c>"# EE | app:App"</c> (application)</item> + <item><c>"# EE | rel:Rel"</c> (release)</item> + </list> + </item> + <item> + <p><c>no_releases</c></p> + <list type="bulleted"> + <item><c>"# R"</c> (info/1)</item> + </list> + </item> + </list> + </desc> + </func> + <func> + <name>m(Module) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name> + <name>m(File) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name> + <fsummary>Check a module using the code path.</fsummary> + <type> + <v>DebugInfoResult = {deprecated, [funcall()]} | {undefined, [funcall()]} | {unused, [mfa()]}</v> + <v>Error = {error, module(), Reason}</v> + <v>File = file()</v> + <v>Module = module()</v> + <v>NoDebugInfoResult = {deprecated, [mfa()]} | {undefined, [mfa()]}</v> + <v>Reason = {file_error, file(), error()} | {interpreted, module()} | {invalid_filename, term()} | {cover_compiled, module()} | {no_such_module, module()} | - error from beam_lib:chunks/2 -</v> + </type> + <desc> + <p>The given BEAM file (with or without the <c>.beam</c> + extension) or the file found by calling + <c>code:which(Module)</c> is checked for calls to <seealso marker="#deprecated_function">deprecated functions</seealso>, calls to <seealso marker="#undefined_function">undefined functions</seealso>, + and for unused local functions. The code path is used as + <seealso marker="#library_path">library path</seealso>. + </p> + <p>If the BEAM file contains <seealso marker="#debug_info">debug information</seealso>, then a + list of tuples is returned. The first element of each tuple + is one of: + </p> + <list type="bulleted"> + <item><c>deprecated</c>, the second element is a sorted list + of calls to deprecated functions;</item> + <item><c>undefined</c>, the second element is a sorted list + of calls to undefined functions;</item> + <item><c>unused</c>, the second element is a sorted list of + unused local functions.</item> + </list> + <p>If the BEAM file does not contain debug information, then a + list of tuples is returned. The first element of each tuple + is one of: + </p> + <list type="bulleted"> + <item><c>deprecated</c>, the second element is a sorted list + of externally used deprecated functions;</item> + <item><c>undefined</c>, the second element is a sorted list + of undefined functions.</item> + </list> + </desc> + </func> + <func> + <name>q(Xref, Query [, Options]) -> {ok, Answer} | Error</name> + <fsummary>Evaluate a query.</fsummary> + <type> + <v>Answer = false | [constant()] | [Call] | [Component] | int() | [DefineAt] | [CallAt] | [AllLines]</v> + <v>Call = call() | ComponentCall</v> + <v>ComponentCall = {Component, Component}</v> + <v>Component = [constant()]</v> + <v>DefineAt = {mfa(), LineNumber}</v> + <v>CallAt = {funcall(), LineNumbers}</v> + <v>AllLines = {{DefineAt, DefineAt}, LineNumbers}</v> + <v>Error = {error, module(), Reason}</v> + <v>LineNumbers = [LineNumber]</v> + <v>LineNumber = int()</v> + <v>Options = [Option] | Option</v> + <v>Option = {verbose, bool()}</v> + <v>Query = string() | atom()</v> + <v>Reason = {invalid_options, term()} | {parse_error, string_position(), term()} | {type_error, string()} | {type_mismatch, string(), string()} | {unknown_analysis, term()} | {unknown_constant, string()} | {unknown_variable, variable()} | {variable_reassigned, string()}</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Evaluates a <seealso marker="#query">query</seealso> in the + context of an <seealso marker="#xref_server">Xref server</seealso>, and returns the value of the last + statement. The syntax of the value depends on the + expression: + </p> + <list type="bulleted"> + <item>A set of calls is represented by a sorted list without + duplicates of <c>call()</c>.</item> + <item>A set of constants is represented by a sorted list + without duplicates of <c>constant()</c>.</item> + <item>A set of strongly connected components is a sorted list + without duplicates of <c>Component</c>.</item> + <item>A set of calls between strongly connected components is + a sorted list without duplicates of <c>ComponentCall</c>.</item> + <item>A chain of calls is represented by a list of + <c>constant()</c>. The list contains the From vertex of every + call and the To vertex of the last call.</item> + <item>The <c>of</c> operator returns <c>false</c> if no chain + of calls between the given constants can be found.</item> + <item>The value of the <c>closure</c> operator (the + <c>digraph</c> representation) is represented by the atom + <c>'closure()'</c>.</item> + <item>A set of line numbered functions is represented by a sorted + list without duplicates of <c>DefineAt</c>.</item> + <item>A set of line numbered function calls is represented by + a sorted list without duplicates of <c>CallAt</c>.</item> + <item>A set of line numbered functions and function calls is + represented by a sorted list without duplicates of + <c>AllLines</c>.</item> + </list> + <p>For both <c>CallAt</c> and <c>AllLines</c> it holds that for + no list element is <c>LineNumbers</c> an empty list; such + elements have been removed. The constants of <c>component</c> + and the integers of <c>LineNumbers</c> are sorted and without + duplicates. + </p> + </desc> + </func> + <func> + <name>remove_application(Xref, Applications) -> ok | Error</name> + <fsummary>Remove applications and their modules.</fsummary> + <type> + <v>Applications = application() | [application()]</v> + <v>Error = {error, module(), Reason}</v> + <v>Reason = {no_such_application, application()}</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Removes applications and their modules and <seealso marker="#module_data">module data</seealso> from an <seealso marker="#xref_server">Xref server</seealso>.</p> + </desc> + </func> + <func> + <name>remove_module(Xref, Modules) -> ok | Error</name> + <fsummary>Remove analyzed modules.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>Modules = module() | [module()]</v> + <v>Reason = {no_such_module, module()}</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Removes <seealso marker="#analyzed_module">analyzed modules</seealso> and <seealso marker="#module_data">module data</seealso> from an <seealso marker="#xref_server">Xref server</seealso>.</p> + </desc> + </func> + <func> + <name>remove_release(Xref, Releases) -> ok | Error</name> + <fsummary>Remove releases and their applications and modules.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>Reason = {no_such_release, release()}</v> + <v>Releases = release() | [release()]</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Removes releases and their applications, modules and + <seealso marker="#module_data">module data</seealso> from an + <seealso marker="#xref_server">Xref server</seealso>.</p> + </desc> + </func> + <func> + <name>replace_application(Xref, Application, Directory [, Options]) -> {ok, application()} | Error</name> + <fsummary>Replace an application's modules.</fsummary> + <type> + <v>Application = application()</v> + <v>Directory = directory()</v> + <v>Error = {error, module(), Reason}</v> + <v>Options = [Option] | Option</v> + <v>Option = {builtins, bool()} | {verbose, bool()} | {warnings, bool()}</v> + <v>Reason = {no_such_application, application()} | - see also add_application -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Replaces the modules of an application with other modules + read from an application directory. Release membership of the + application is retained. Note that the name of the + application is kept; the name of the given directory is not + used. + </p> + </desc> + </func> + <func> + <name>replace_module(Xref, Module, File [, Options]) -> {ok, module()} | Error</name> + <fsummary>Replace an analyzed module.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>File = file()</v> + <v>Module = module()</v> + <v>Options = [Option] | Option</v> + <v>Option = {verbose, bool()} | {warnings, bool()}</v> + <v>ReadModule = module()</v> + <v>Reason = {module_mismatch, module(), ReadModule} | {no_such_module, module()} | - see also add_module -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Replaces <seealso marker="#module_data">module data</seealso> of an <seealso marker="#analyzed_module">analyzed module</seealso> with + data read from a BEAM file. Application membership of the + module is retained, and so is the value of the + <c>builtins</c> option of the module. An error is returned + if the name of the read module differs from the given + module. + </p> + <p>The <c>update</c> function is an alternative for updating + module data of recompiled modules.</p> + </desc> + </func> + <func> + <name>set_default(Xref, Option, Value) -> {ok, OldValue} | Error</name> + <name>set_default(Xref, OptionValues) -> ok | Error</name> + <fsummary>Set the default values of options.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>OptionValues = [OptionValue] | OptionValue</v> + <v>OptionValue = {Option, Value}</v> + <v>Option = builtins | recurse | verbose | warnings</v> + <v>Reason = {invalid_options, term()}</v> + <v>Value = bool()</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Sets the default value of one or more options. + The options that can be set this way are:</p> + <list type="bulleted"> + <item><c>builtins</c>, with initial default value <c>false</c>;</item> + <item><c>recurse</c>, with initial default value <c>false</c>;</item> + <item><c>verbose</c>, with initial default value <c>false</c>;</item> + <item><c>warnings</c>, with initial default value <c>true</c>.</item> + </list> + <p>The initial default values are set when creating an <seealso marker="#xref_server">Xref server</seealso>. + </p> + </desc> + </func> + <func> + <name>set_library_path(Xref, LibraryPath [, Options]) -> ok | Error</name> + <fsummary>Set the library path and finds the library modules.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>LibraryPath = library_path()</v> + <v>Options = [Option] | Option</v> + <v>Option = {verbose, bool()}</v> + <v>Reason = {invalid_options, term()} | {invalid_path, term()}</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Sets the <seealso marker="#library_path">library path</seealso>. If the given path is a list of + directories, the set of <seealso marker="#library_module">library modules</seealso> is + determined by choosing the first module + encountered while traversing the directories in + the given order, for those modules that occur in more than + one directory. By default, the library path is an empty list. + </p> + <p>The library path <marker id="code_path"></marker> +<c>code_path</c> is + used by the functions + <c>m/1</c> and <c>d/1</c>, but can also be set explicitly. + Note however that the code path will be traversed once for + each used <seealso marker="#library_module">library module</seealso> while setting up module data. + On the other hand, if there are only a few modules that are + used by not analyzed, using <c>code_path</c> may be faster + than setting the library path to <c>code:get_path()</c>. + </p> + <p>If the library path is set to <c>code_path</c>, the set of + library modules is not determined, and the <c>info</c> + functions will return empty lists of library modules.</p> + </desc> + </func> + <func> + <name>start(NameOrOptions) -> Return</name> + <fsummary>Create an Xref server.</fsummary> + <type> + <v>Name = atom()()</v> + <v>XrefOrOptions = Xref | Options</v> + <v>Options = [Option] | Option</v> + <v>Option = {xref_mode, mode()} | term()</v> + <v>Return = {ok, pid()} | {error, {already_started, pid()}}</v> + </type> + <desc> + <p>Creates an <seealso marker="#xref_server">Xref server</seealso>. + The process may optionally be given a name. + The default <seealso marker="#mode">mode</seealso> is <c>functions</c>. + Options that are not recognized by Xref + are passed on to <c>gen_server:start/4</c>.</p> + </desc> + </func> + <func> + <name>start(Name, Options) -> Return</name> + <fsummary>Create an Xref server.</fsummary> + <type> + <v>Name = atom()()</v> + <v>Options = [Option] | Option</v> + <v>Option = {xref_mode, mode()} | term()</v> + <v>Return = {ok, pid()} | {error, {already_started, pid()}}</v> + </type> + <desc> + <p>Creates an <seealso marker="#xref_server">Xref server</seealso> + with a given name. + The default <seealso marker="#mode">mode</seealso> is <c>functions</c>. + Options that are not recognized by Xref + are passed on to <c>gen_server:start/4</c>.</p> + </desc> + </func> + <func> + <name>stop(Xref)</name> + <fsummary>Delete an Xref server.</fsummary> + <type> + <v>Xref = xref()</v> + </type> + <desc> + <p>Stops an <seealso marker="#xref_server">Xref server</seealso>.</p> + </desc> + </func> + <func> + <name>update(Xref [, Options]) -> {ok, Modules} | Error</name> + <fsummary>Replace newly compiled analyzed modules.</fsummary> + <type> + <v>Error = {error, module(), Reason}</v> + <v>Modules = [module()]</v> + <v>Options = [Option] | Option</v> + <v>Option = {verbose, bool()} | {warnings, bool()}</v> + <v>Reason = {invalid_options, term()} | {module_mismatch, module(), ReadModule} | - see also add_module -</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Replaces the <seealso marker="#module_data">module data</seealso> of all <seealso marker="#analyzed_module">analyzed modules</seealso> the BEAM + files of which have been modified since last read by an + <c>add</c> function or <c>update</c>. Application membership + of the modules is retained, and so is the value of the + <c>builtins</c> option. Returns a sorted list + of the names of the replaced modules.</p> + </desc> + </func> + <func> + <name>variables(Xref [, Options]) -> {ok, [VariableInfo]}</name> + <fsummary>Return the names of variables.</fsummary> + <type> + <v>Options = [Option] | Option</v> + <v>Option = predefined | user | {verbose, bool()}</v> + <v>Reason = {invalid_options, term()}</v> + <v>VariableInfo = {predefined, [variable()]} | {user, [variable()]}</v> + <v>Xref = xref()</v> + </type> + <desc> + <p>Returns a sorted lists of the names of the variables of an + <seealso marker="#xref_server">Xref server</seealso>. + The default is to return the <seealso marker="#user_variable">user variables</seealso> only.</p> + </desc> + </func> + </funcs> + + <section> + <title>See Also</title> + <p>beam_lib(3), digraph(3), digraph_utils(3), regexp(3), + <seealso marker="xref_chapter">TOOLS User's Guide</seealso></p> + </section> +</erlref> + diff --git a/lib/tools/doc/src/xref_chapter.xml b/lib/tools/doc/src/xref_chapter.xml new file mode 100644 index 0000000000..39c5545af9 --- /dev/null +++ b/lib/tools/doc/src/xref_chapter.xml @@ -0,0 +1,383 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2000</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Xref - The Cross Reference Tool</title> + <prepared>Hans Bolinder</prepared> + <responsible>nobody</responsible> + <docno></docno> + <approved>nobody</approved> + <checked>no</checked> + <date>2000-08-18</date> + <rev>PA1</rev> + <file>xref_chapter.xml</file> + </header> + <p>Xref is a cross reference tool that can be used for + finding dependencies between functions, modules, applications + and releases. It does so by analyzing the defined functions + and the function calls. + </p> + <p>In order to make Xref easy to use, there are predefined + analyses that perform some common tasks. Typically, a module + or a release can be checked for calls to undefined functions. + For the somewhat more advanced user there is a small, but + rather flexible, language that can be used for selecting parts + of the analyzed system and for doing some simple graph + analyses on selected calls. + </p> + <p>The following sections show some features of Xref, beginning + with a module check and a predefined analysis. Then follow + examples that can be skipped on the first reading; not all of + the concepts used are explained, and it is assumed that the + <seealso marker="xref">reference manual</seealso> has been at + least skimmed. + </p> + + <section> + <title>Module Check</title> + <p>Assume we want to check the following module: + </p> + <pre> + -module(my_module). + + -export([t/1]). + + t(A) -> + my_module:t2(A). + + t2(_) -> + true. </pre> + <p>Cross reference data are read from BEAM files, so the first + step when checking an edited module is to compile it: + </p> + <pre> + 1> <input>c(my_module, debug_info).</input> + ./my_module.erl:10: Warning: function t2/1 is unused + {ok, my_module} </pre> + <p>The <c>debug_info</c> option ensures that the BEAM file + contains debug information, which makes it possible to find + unused local functions. + </p> + <p>The module can now be checked for calls to <seealso marker="xref#deprecated_function">deprecated functions</seealso>, calls to <seealso marker="xref#undefined_function">undefined functions</seealso>, + and for unused local functions: + </p> + <pre> + 2> <input>xref:m(my_module)</input> + [{deprecated,[]}, + {undefined,[{{my_module,t,1},{my_module,t2,1}}]}, + {unused,[{my_module,t2,1}]}] </pre> + <p><c>m/1</c> is also suitable for checking that the + BEAM file of a module that is about to be loaded into a + running a system does not call any undefined functions. In + either case, the code path of the code server (see the module + <c>code</c>) is used for finding modules that export externally + called functions not exported by the checked module itself, so + called <seealso marker="xref#library_module">library modules</seealso>. + </p> + </section> + + <section> + <title>Predefined Analysis</title> + <p>In the last example the module to analyze was given as an + argument to <c>m/1</c>, and the code path was (implicitly) + used as <seealso marker="xref#library_path">library path</seealso>. In this example an <seealso marker="xref#xref_server">xref server</seealso> will be used, + which makes it possible to analyze applications and releases, + and also to select the library path explicitly. + </p> + <p>Each Xref server is referred to by a unique name. The name + is given when creating the server: + </p> + <pre> + 1> <input>xref:start(s).</input> + {ok,<0.27.0>} </pre> + <p>Next the system to be analyzed is added to the Xref server. + Here the system will be OTP, so no library path will be needed. + Otherwise, when analyzing a system that uses OTP, the OTP + modules are typically made library modules by + setting the library path to the default OTP code path (or to + <c>code_path</c>, see the <seealso marker="xref#code_path">reference manual</seealso>). By + default, the names of read BEAM files and warnings are output + when adding analyzed modules, but these messages can be avoided + by setting default values of some options: + </p> + <pre> + 2> <input>xref:set_default(s, [{verbose,false}, {warnings,false}]).</input> + ok + 3> <input>xref:add_release(s, code:lib_dir(), {name, otp}).</input> + {ok,otp} </pre> + <p><c>add_release/3</c> assumes that all subdirectories of the + library directory returned by <c>code:lib_dir()</c> contain + applications; the effect is that of reading all + applications' BEAM files. + </p> + <p>It is now easy to check the release for calls to undefined + functions: + </p> + <pre> + 4> <input>xref:analyze(s, undefined_function_calls).</input> + {ok, [...]} </pre> + <p>We can now continue with further analyses, or we can delete + the Xref server: + </p> + <pre> + 5> <input>xref:stop(s).</input> </pre> + <p>The check for calls to undefined functions is an example of a + predefined analysis, probably the most useful one. Other + examples are the analyses that find unused local + functions, or functions that call some given functions. See + the <seealso marker="xref#analyze">analyze/2,3</seealso> + functions for a complete list of predefined analyses. + </p> + <p>Each predefined analysis is a shorthand for a <seealso marker="xref#query">query</seealso>, a sentence of a tiny + language providing cross reference data as + values of <seealso marker="xref#predefined_variable">predefined variables</seealso>. + The check for calls to undefined functions can thus be stated as + a query: + </p> + <pre> + 4> <input>xref:q(s, "(XC - UC) || (XU - X - B)").</input> + {ok,[...]} </pre> + <p>The query asks for the restriction of external calls except the + unresolved calls to calls to functions that are externally used + but neither exported nor built-in functions (the <c>||</c> + operator restricts the used functions while the <c>|</c> + operator restricts the calling functions). The <c>-</c> operator + returns the difference of two sets, and the <c>+</c> operator to + be used below returns the union of two sets. + </p> + <p>The relationships between the predefined variables + <c>XU</c>, <c>X</c>, <c>B</c> and a few + others are worth elaborating upon. + The reference manual mentions two ways of expressing the set of + all functions, one that focuses on how they are defined: + <c>X + L + B + U</c>, and one + that focuses on how they are used: + <c>UU + LU + XU</c>. + The reference also mentions some <seealso marker="xref#simple_facts">facts</seealso> about the + variables: + </p> + <list type="bulleted"> + <item><c>F</c> is equal to <c>L + X</c> (the defined functions + are the local functions and the external functions);</item> + <item><c>U</c> is a subset of <c>XU</c> (the unknown functions + are a subset of the externally used functions since + the compiler ensures that locally used functions are defined);</item> + <item><c>B</c> is a subset of <c>XU</c> (calls to built-in + functions are always external by definition, and unused + built-in functions are ignored);</item> + <item><c>LU</c> is a subset of <c>F</c> (the locally used + functions are either local functions or exported functions, + again ensured by the compiler);</item> + <item><c>UU</c> is equal to + <c>F - (XU + LU)</c> (the unused functions + are defined functions that are neither used externally nor + locally);</item> + <item><c>UU</c> is a subset of <c>F</c> (the unused functions + are defined in analyzed modules).</item> + </list> + <p>Using these facts, the two small circles in the picture below + can be combined. + </p> + <image file="venn1.gif"> + <icaption>Definition and use of functions</icaption> + </image> + <p>It is often clarifying to mark the variables of a query in such + a circle. This is illustrated in the picture below for some of + the predefined analyses. Note that local functions used by local + functions only are not marked in the <c>locals_not_used</c> + circle. <marker id="venn2"></marker> +</p> + <image file="venn2.gif"> + <icaption>Some predefined analyses as subsets of all functions</icaption> + </image> + </section> + + <section> + <title>Expressions</title> + <p>The module check and the predefined analyses are useful, but + limited. Sometimes more flexibility is needed, for instance one + might not need to apply a graph analysis on all calls, but some + subset will do equally well. That flexibility is provided with + a simple language. Below are some expressions of the language + with comments, focusing on elements of the language rather than + providing useful examples. The analyzed system is assumed to be + OTP, so in order to run the queries, first evaluate these calls: + </p> + <pre> + xref:start(s). + xref:add_release(s, code:root_dir()). </pre> + <taglist> + <tag><c>xref:q(s, "(Fun) xref : Mod").</c></tag> + <item>All functions of the <c>xref</c> module. </item> + <tag><c>xref:q(s, "xref : Mod * X").</c></tag> + <item>All exported functions of the <c>xref</c> module. The first + operand of the intersection operator <c>*</c> is implicitly + converted to the more special type of the second operand.</item> + <tag><c>xref:q(s, "(Mod) tools").</c></tag> + <item>All modules of the <c>tools</c> application.</item> + <tag><c>xref:q(s, '"xref_.*" : Mod').</c></tag> + <item>All modules with a name beginning with <c>xref_</c>.</item> + <tag><c>xref:q(s, "# E | X ").</c></tag> + <item>Number of calls from exported functions.</item> + <tag><c>xref:q(s, "XC || L ").</c></tag> + <item>All external calls to local functions.</item> + <tag><c>xref:q(s, "XC * LC").</c></tag> + <item>All calls that have both an external and a local version.</item> + <tag><c>xref:q(s, "(LLin) (LC * XC)").</c></tag> + <item>The lines where the local calls of the last example + are made.</item> + <tag><c>xref:q(s, "(XLin) (LC * XC)").</c></tag> + <item>The lines where the external calls of the example before + last are made.</item> + <tag><c>xref:q(s, "XC * (ME - strict ME)").</c></tag> + <item>External calls within some module.</item> + <tag><c>xref:q(s, "E ||| kernel").</c></tag> + <item>All calls within the <c>kernel</c> application. </item> + <tag><c>xref:q(s, "closure E | kernel || kernel").</c></tag> + <item>All direct and indirect calls within the <c>kernel</c> + application. Both the calling and the used functions of + indirect calls are defined in modules of the kernel + application, but it is possible that some functions outside + the kernel application are used by indirect calls.</item> + <tag><c>xref:q(s, "{toolbar,debugger}:Mod of ME").</c></tag> + <item>A chain of module calls from <c>toolbar</c> to + <c>debugger</c>, if there is such a chain, otherwise + <c>false</c>. The chain of calls is represented by a list of + modules, <c>toolbar</c> being the first element and + <c>debugger</c>the last element.</item> + <tag><c>xref:q(s, "closure E | toolbar:Mod || debugger:Mod").</c></tag> + <item>All (in)direct calls from functions in <c>toolbar</c> to + functions in <c>debugger</c>.</item> + <tag><c>xref:q(s, "(Fun) xref -> xref_base").</c></tag> + <item>All function calls from <c>xref</c> to <c>xref_base</c>.</item> + <tag><c>xref:q(s, "E * xref -> xref_base").</c></tag> + <item>Same interpretation as last expression.</item> + <tag><c>xref:q(s, "E || xref_base | xref").</c></tag> + <item>Same interpretation as last expression.</item> + <tag><c>xref:q(s, "E * [xref -> lists, xref_base -> digraph]").</c></tag> + <item>All function calls from <c>xref</c> to <c>lists</c>, and + all function calls from <c>xref_base</c> to <c>digraph</c>.</item> + <tag><c>xref:q(s, "E | [xref, xref_base] || [lists, digraph]").</c></tag> + <item>All function calls from <c>xref</c> and <c>xref_base</c> + to <c>lists</c> and <c>digraph</c>.</item> + <tag><c>xref:q(s, "components EE").</c></tag> + <item>All strongly connected components of the Inter Call + Graph. Each component is a set of exported or unused local functions + that call each other (in)directly.</item> + <tag><c>xref:q(s, "X * digraph * range (closure (E | digraph) | (L * digraph))").</c></tag> + <item>All exported functions of the <c>digraph</c> module + used (in)directly by some function in <c>digraph</c>.</item> + <tag><c>xref:q(s, "L * yeccparser:Mod - range (closure (E |</c></tag> + <item></item> + <tag><c>yeccparser:Mod) | (X * yeccparser:Mod))").</c></tag> + <item>The interpretation is left as an exercise. </item> + </taglist> + </section> + + <section> + <title>Graph Analysis</title> + <p>The list <seealso marker="xref#representation">representation of graphs</seealso> is used analyzing direct calls, + while the <c>digraph</c> representation is suited for analyzing + indirect calls. The restriction operators (<c>|</c>, <c>||</c> + and <c>|||</c>) are the only operators that accept both + representations. This means that in order to analyze indirect + calls using restriction, the <c>closure</c> operator (which creates the + <c>digraph</c> representation of graphs) has to been + applied explicitly. + </p> + <p>As an example of analyzing indirect calls, the following Erlang + function tries to answer the question: + if we want to know which modules are used indirectly by some + module(s), is it worth while using the <seealso marker="xref#call_graph">function graph</seealso> rather + than the module graph? Recall that a module M1 is said to call + a module M2 if there is some function in M1 that calls some + function in M2. It would be nice if we could use the much + smaller module graph, since it is available also in the light + weight <c>modules</c><seealso marker="xref#mode">mode</seealso> of Xref servers. + </p> + <code type="erl"> + t(S) -> + {ok, _} = xref:q(S, "Eplus := closure E"), + {ok, Ms} = xref:q(S, "AM"), + Fun = fun(M, N) -> + Q = io_lib:format("# (Mod) (Eplus | ~p : Mod)", [M]), + {ok, N0} = xref:q(S, lists:flatten(Q)), + N + N0 + end, + Sum = lists:foldl(Fun, 0, Ms), + ok = xref:forget(S, 'Eplus'), + {ok, Tot} = xref:q(S, "# (closure ME | AM)"), + 100 * ((Tot - Sum) / Tot). </code> + <p>Comments on the code: + </p> + <list type="bulleted"> + <item>We want to find the reduction of the closure of the + function graph to modules. + The direct expression for doing that would be + <c>(Mod) (closure E | AM)</c>, but then we + would have to represent all of the transitive closure of E in + memory. Instead the number of indirectly used modules is + found for each analyzed module, and the sum over all modules + is calculated. + </item> + <item>A user variable is employed for holding the <c>digraph</c> + representation of the function graph for use in many + queries. The reason is efficiency. As opposed to the + <c>=</c> operator, the <c>:=</c> operator saves a value for + subsequent analyses. Here might be the place to note that + equal subexpressions within a query are evaluated only once; + <c>=</c> cannot be used for speeding things up. + </item> + <item><c>Eplus | ~p : Mod</c>. The <c>|</c> operator converts + the second operand to the type of the first operand. In this + case the module is converted to all functions of the + module. It is necessary to assign a type to the module + (<c>: Mod</c>), otherwise modules like <c>kernel</c> would be + converted to all functions of the application with the same + name; the most general constant is used in cases of ambiguity. + </item> + <item>Since we are only interested in a ratio, the unary + operator <c>#</c> that counts the elements of the operand is + used. It cannot be applied to the <c>digraph</c> representation + of graphs. + </item> + <item>We could find the size of the closure of the module graph + with a loop similar to one used for the function graph, but + since the module graph is so much smaller, a more direct + method is feasible. + </item> + </list> + <p>When the Erlang function <c>t/1</c> was applied to an Xref + server loaded with the current version of OTP, the returned + value was close to 84 (percent). This means that the number + of indirectly used modules is approximately six times greater + when using the module graph. + So the answer to the above stated question is that it is + definitely worth while using the function graph for this + particular analysis. + Finally, note that in the presence of unresolved calls, the + graphs may be incomplete, which means that there may be + indirectly used modules that do not show up. + </p> + </section> +</chapter> + |