Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 1527

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css">
<title>Erlang -- Xref - The Cross Reference Tool</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/tools-2.6.8.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Tools</strong><br><strong>User's Guide</strong><br><small>Version 2.6.8</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../../../../doc/js/flipmenu">
<li id="no" title="cover" expanded="false">cover<ul>
<li><a href="cover_chapter.html">
              Top of chapter
            </a></li>
<li title="Introduction"><a href="cover_chapter.html#id64809">Introduction</a></li>
<li title="Getting Started With Cover"><a href="cover_chapter.html#id62638">Getting Started With Cover</a></li>
<li title="Miscellaneous"><a href="cover_chapter.html#id60749">Miscellaneous</a></li>
<li title="Using the Web Based User Interface to Cover"><a href="cover_chapter.html#id63969">Using the Web Based User Interface to Cover</a></li>
</ul>
</li>
<li id="no" title="cprof - The Call Count Profiler" expanded="false">cprof - The Call Count Profiler<ul>
<li><a href="cprof_chapter.html">
              Top of chapter
            </a></li>
<li title="Example: Background work"><a href="cprof_chapter.html#id62155">Example: Background work</a></li>
<li title="Example: One module"><a href="cprof_chapter.html#id62215">Example: One module</a></li>
<li title="Example: In the code"><a href="cprof_chapter.html#id62262">Example: In the code</a></li>
</ul>
</li>
<li id="no" title="The Erlang mode for Emacs" expanded="false">The Erlang mode for Emacs<ul>
<li><a href="erlang_mode_chapter.html">
              Top of chapter
            </a></li>
<li title="Purpose"><a href="erlang_mode_chapter.html#id64082">Purpose</a></li>
<li title="Pre-requisites"><a href="erlang_mode_chapter.html#id64101">Pre-requisites</a></li>
<li title="Elisp"><a href="erlang_mode_chapter.html#id64113">Elisp</a></li>
<li title="Setup on UNIX"><a href="erlang_mode_chapter.html#id64126">Setup on UNIX</a></li>
<li title="Setup on Windows "><a href="erlang_mode_chapter.html#id64160">Setup on Windows </a></li>
<li title="Indentation"><a href="erlang_mode_chapter.html#id64228">Indentation</a></li>
<li title="Editing"><a href="erlang_mode_chapter.html#id64277">Editing</a></li>
<li title="Syntax highlighting"><a href="erlang_mode_chapter.html#id64373">Syntax highlighting</a></li>
<li title="Tags"><a href="erlang_mode_chapter.html#id64396">Tags</a></li>
<li title="Etags"><a href="erlang_mode_chapter.html#id64430">Etags</a></li>
<li title="Shell"><a href="erlang_mode_chapter.html#id64528">Shell</a></li>
<li title="Compilation"><a href="erlang_mode_chapter.html#id64585">Compilation</a></li>
</ul>
</li>
<li id="no" title="fprof - The File Trace Profiler" expanded="false">fprof - The File Trace Profiler<ul>
<li><a href="fprof_chapter.html">
              Top of chapter
            </a></li>
<li title="Profiling from the source code"><a href="fprof_chapter.html#id64914">Profiling from the source code</a></li>
<li title="Profiling a function"><a href="fprof_chapter.html#id64995">Profiling a function</a></li>
<li title="Immediate profiling"><a href="fprof_chapter.html#id65025">Immediate profiling</a></li>
</ul>
</li>
<li id="no" title="lcnt - The Lock Profiler" expanded="false">lcnt - The Lock Profiler<ul>
<li><a href="lcnt_chapter.html">
              Top of chapter
            </a></li>
<li title=" Enabling lock-counting "><a href="lcnt_chapter.html#id65145"> Enabling lock-counting </a></li>
<li title="Getting started"><a href="lcnt_chapter.html#id65194">Getting started</a></li>
<li title=" Example of usage "><a href="lcnt_chapter.html#id65262"> Example of usage </a></li>
<li title=" Example with Mnesia Transaction Benchmark "><a href="lcnt_chapter.html#id65351"> Example with Mnesia Transaction Benchmark </a></li>
<li title=" Deciphering the output "><a href="lcnt_chapter.html#id65488"> Deciphering the output </a></li>
<li title="See Also"><a href="lcnt_chapter.html#id65506">See Also</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Xref - The Cross Reference Tool" expanded="true">Xref - The Cross Reference Tool<ul>
<li><a href="xref_chapter.html">
              Top of chapter
            </a></li>
<li title="Module Check"><a href="xref_chapter.html#id65613">Module Check</a></li>
<li title="Predefined Analysis"><a href="xref_chapter.html#id65693">Predefined Analysis</a></li>
<li title="Expressions"><a href="xref_chapter.html#id65996">Expressions</a></li>
<li title="Graph Analysis"><a href="xref_chapter.html#id66325">Graph Analysis</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>6 Xref - The Cross Reference Tool</h1>
  
  <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
    <span class="bold_code"><a href="xref.html">reference manual</a></span> has been at
    least skimmed.
    </p>

  <h3><a name="id65613">6.1 
        Module Check</a></h3>
    
    <p>Assume we want to check the following module:
      </p>
    <div class="example"><pre>
    -module(my_module).

    -export([t/1]).

    t(A) -&gt;
      my_module:t2(A).

    t2(_) -&gt;
      true.    </pre></div>
    <p>Cross reference data are read from BEAM files, so the first
      step when checking an edited module is to compile it:
      </p>
    <div class="example"><pre>
    1&gt; <span class="bold_code">c(my_module, debug_info).</span>
    ./my_module.erl:10: Warning: function t2/1 is unused
    {ok, my_module}    </pre></div>
    <p>The <span class="code">debug_info</span> 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 <span class="bold_code"><a href="xref.html#deprecated_function">deprecated functions</a></span>, calls to <span class="bold_code"><a href="xref.html#undefined_function">undefined functions</a></span>,
      and for unused local functions:
      </p>
    <div class="example"><pre>
    2&gt; <span class="bold_code">xref:m(my_module)</span>
    [{deprecated,[]},
     {undefined,[{{my_module,t,1},{my_module,t2,1}}]},
     {unused,[{my_module,t2,1}]}]    </pre></div>
    <p><span class="code">m/1</span> 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
      <span class="code">code</span>) is used for finding modules that export externally
      called functions not exported by the checked module itself, so
      called <span class="bold_code"><a href="xref.html#library_module">library modules</a></span>.
      </p>
  

  <h3><a name="id65693">6.2 
        Predefined Analysis</a></h3>
    
    <p>In the last example the module to analyze was given as an
      argument to <span class="code">m/1</span>, and the code path was (implicitly)
      used as <span class="bold_code"><a href="xref.html#library_path">library path</a></span>. In this example an <span class="bold_code"><a href="xref.html#xref_server">xref server</a></span> 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>
    <div class="example"><pre>
    1&gt; <span class="bold_code">xref:start(s).</span>
    {ok,&lt;0.27.0&gt;}    </pre></div>
    <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
      <span class="code">code_path</span>, see the <span class="bold_code"><a href="xref.html#code_path">reference manual</a></span>). 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>
    <div class="example"><pre>
    2&gt; <span class="bold_code">xref:set_default(s, [{verbose,false}, {warnings,false}]).</span>
    ok
    3&gt; <span class="bold_code">xref:add_release(s, code:lib_dir(), {name, otp}).</span>
    {ok,otp}    </pre></div>
    <p><span class="code">add_release/3</span> assumes that all subdirectories of the
      library directory returned by <span class="code">code:lib_dir()</span> 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>
    <div class="example"><pre>
    4&gt; <span class="bold_code">xref:analyze(s, undefined_function_calls).</span>
    {ok, [...]}    </pre></div>
    <p>We can now continue with further analyses, or we can delete
      the Xref server:
      </p>
    <div class="example"><pre>
    5&gt; <span class="bold_code">xref:stop(s).</span>    </pre></div>
    <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 <span class="bold_code"><a href="xref.html#analyze">analyze/2,3</a></span>
      functions for a complete list of predefined analyses.
      </p>
    <p>Each predefined analysis is a shorthand for a <span class="bold_code"><a href="xref.html#query">query</a></span>, a sentence of a tiny
      language providing cross reference data as
      values of <span class="bold_code"><a href="xref.html#predefined_variable">predefined variables</a></span>.
      The check for calls to undefined functions can thus be stated as
      a query:
      </p>
    <div class="example"><pre>
    4&gt; <span class="bold_code">xref:q(s, "(XC - UC) || (XU - X - B)").</span>
    {ok,[...]}    </pre></div>
    <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 <span class="code">||</span>
      operator restricts the used functions while the <span class="code">|</span>
      operator restricts the calling functions). The <span class="code">-</span> operator
      returns the difference of two sets, and the <span class="code">+</span> operator to
      be used below returns the union of two sets.
      </p>
    <p>The relationships between the predefined variables
      <span class="code">XU</span>, <span class="code">X</span>, <span class="code">B</span> 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:
      <span class="code">X + L + B + U</span>, and one
      that focuses on how they are used:
      <span class="code">UU + LU + XU</span>. 
      The reference also mentions some <span class="bold_code"><a href="xref.html#simple_facts">facts</a></span> about the
      variables:
      </p>
    <ul>
      <li>
<span class="code">F</span> is equal to <span class="code">L + X</span> (the defined functions
       are the local functions and the external functions);</li>
      <li>
<span class="code">U</span> is a subset of <span class="code">XU</span> (the unknown functions
       are a subset of the externally used functions since
       the compiler ensures that locally used functions are defined);</li>
      <li>
<span class="code">B</span> is a subset of <span class="code">XU</span> (calls to built-in
       functions are always external by definition, and unused
       built-in functions are ignored);</li>
      <li>
<span class="code">LU</span> is a subset of <span class="code">F</span> (the locally used
       functions are either local functions or exported functions,
       again ensured by the compiler);</li>
      <li>
<span class="code">UU</span> is equal to
      <span class="code">F - (XU + LU)</span> (the unused functions
       are defined functions that are neither used externally nor
       locally);</li>
      <li>
<span class="code">UU</span> is a subset of <span class="code">F</span> (the unused functions
       are defined in analyzed modules).</li>
    </ul>
    <p>Using these facts, the two small circles in the picture below
      can be combined. 
      </p>
    <img alt="IMAGE MISSING" src="venn1.gif"><br>
      <em>Figure
        6.1:
         
        Definition and use of functions</em>
    
    <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 <span class="code">locals_not_used</span>
      circle.       <a name="venn2"></a>
</p>
    <img alt="IMAGE MISSING" src="venn2.gif"><br>
      <em>Figure
        6.2:
         
        Some predefined analyses as subsets of all functions</em>
    
  

  <h3><a name="id65996">6.3 
        Expressions</a></h3>
    
    <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>
    <div class="example"><pre>
    xref:start(s).
    xref:add_release(s, code:root_dir()).    </pre></div>
    <dl>
      <dt><strong><span class="code">xref:q(s, "(Fun) xref : Mod").</span></strong></dt>
      <dd>All functions of the <span class="code">xref</span> module. </dd>
      <dt><strong><span class="code">xref:q(s, "xref : Mod * X").</span></strong></dt>
      <dd>All exported functions of the <span class="code">xref</span> module. The first
       operand of the intersection operator <span class="code">*</span> is implicitly
       converted to the more special type of the second operand.</dd>
      <dt><strong><span class="code">xref:q(s, "(Mod) tools").</span></strong></dt>
      <dd>All modules of the <span class="code">tools</span> application.</dd>
      <dt><strong><span class="code">xref:q(s, '"xref_.*" : Mod').</span></strong></dt>
      <dd>All modules with a name beginning with <span class="code">xref_</span>.</dd>
      <dt><strong><span class="code">xref:q(s, "# E | X ").</span></strong></dt>
      <dd>Number of calls from exported functions.</dd>
      <dt><strong><span class="code">xref:q(s, "XC || L ").</span></strong></dt>
      <dd>All external calls to local functions.</dd>
      <dt><strong><span class="code">xref:q(s, "XC * LC").</span></strong></dt>
      <dd>All calls that have both an external and a local version.</dd>
      <dt><strong><span class="code">xref:q(s, "(LLin) (LC * XC)").</span></strong></dt>
      <dd>The lines where the local calls of the last example
       are made.</dd>
      <dt><strong><span class="code">xref:q(s, "(XLin) (LC * XC)").</span></strong></dt>
      <dd>The lines where the external calls of the example before
       last are made.</dd>
      <dt><strong><span class="code">xref:q(s, "XC * (ME - strict ME)").</span></strong></dt>
      <dd>External calls within some module.</dd>
      <dt><strong><span class="code">xref:q(s, "E ||| kernel").</span></strong></dt>
      <dd>All calls within the <span class="code">kernel</span> application. </dd>
      <dt><strong><span class="code">xref:q(s, "closure E | kernel || kernel").</span></strong></dt>
      <dd>All direct and indirect calls within the <span class="code">kernel</span>
       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.</dd>
      <dt><strong><span class="code">xref:q(s, "{toolbar,debugger}:Mod of ME").</span></strong></dt>
      <dd>A chain of module calls from <span class="code">toolbar</span> to
      <span class="code">debugger</span>, if there is such a chain, otherwise
      <span class="code">false</span>. The chain of calls is represented by a list of
       modules, <span class="code">toolbar</span> being the first element and
      <span class="code">debugger</span>the last element.</dd>
      <dt><strong><span class="code">xref:q(s, "closure E | toolbar:Mod || debugger:Mod").</span></strong></dt>
      <dd>All (in)direct calls from functions in <span class="code">toolbar</span> to
       functions in <span class="code">debugger</span>.</dd>
      <dt><strong><span class="code">xref:q(s, "(Fun) xref -&gt; xref_base").</span></strong></dt>
      <dd>All function calls from <span class="code">xref</span> to <span class="code">xref_base</span>.</dd>
      <dt><strong><span class="code">xref:q(s, "E * xref -&gt; xref_base").</span></strong></dt>
      <dd>Same interpretation as last expression.</dd>
      <dt><strong><span class="code">xref:q(s, "E || xref_base | xref").</span></strong></dt>
      <dd>Same interpretation as last expression.</dd>
      <dt><strong><span class="code">xref:q(s, "E * [xref -&gt; lists, xref_base -&gt; digraph]").</span></strong></dt>
      <dd>All function calls from <span class="code">xref</span> to <span class="code">lists</span>, and
       all function calls from <span class="code">xref_base</span> to <span class="code">digraph</span>.</dd>
      <dt><strong><span class="code">xref:q(s, "E | [xref, xref_base] || [lists, digraph]").</span></strong></dt>
      <dd>All function calls from <span class="code">xref</span> and <span class="code">xref_base</span>
       to <span class="code">lists</span> and <span class="code">digraph</span>.</dd>
      <dt><strong><span class="code">xref:q(s, "components EE").</span></strong></dt>
      <dd>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.</dd>
      <dt><strong><span class="code">xref:q(s,  "X * digraph * range (closure (E | digraph) | (L * digraph))").</span></strong></dt>
      <dd>All exported functions of the <span class="code">digraph</span> module
       used (in)directly by some function in <span class="code">digraph</span>.</dd>
      <dt><strong><span class="code">xref:q(s, "L * yeccparser:Mod - range (closure (E |</span></strong></dt>
      <dd></dd>
      <dt><strong><span class="code">yeccparser:Mod) | (X * yeccparser:Mod))").</span></strong></dt>
      <dd>The interpretation is left as an exercise. </dd>
    </dl>
  

  <h3><a name="id66325">6.4 
        Graph Analysis</a></h3>
    
    <p>The list <span class="bold_code"><a href="xref.html#representation">representation of graphs</a></span> is used analyzing direct calls,
      while the <span class="code">digraph</span> representation is suited for analyzing
      indirect calls. The restriction operators (<span class="code">|</span>, <span class="code">||</span>
      and <span class="code">|||</span>) are the only operators that accept both
      representations. This means that in order to analyze indirect
      calls using restriction, the <span class="code">closure</span> operator (which creates the
      <span class="code">digraph</span> representation of graphs) has to be
      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 <span class="bold_code"><a href="xref.html#call_graph">function graph</a></span> 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 <span class="code">modules</span><span class="bold_code"><a href="xref.html#mode">mode</a></span> of Xref servers.
      </p>
    <div class="example"><pre>
    t(S) -&gt;
      {ok, _} = xref:q(S, "Eplus := closure E"),
      {ok, Ms} = xref:q(S, "AM"),
      Fun = fun(M, N) -&gt; 
          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).    </pre></div>
    <p>Comments on the code:
      </p>
    <ul>
      <li>We want to find the reduction of the closure of the
       function graph to modules. 
       The direct expression for doing that would be
      <span class="code">(Mod) (closure E | AM)</span>, 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.
      </li>
      <li>A user variable is employed for holding the <span class="code">digraph</span>
       representation of the function graph for use in many
       queries. The reason is efficiency. As opposed to the
      <span class="code">=</span> operator, the <span class="code">:=</span> operator saves a value for
       subsequent analyses.  Here might be the place to note that
       equal subexpressions within a query are evaluated only once;
      <span class="code">=</span> cannot be used for speeding things up.
      </li>
      <li>
<span class="code">Eplus | ~p : Mod</span>. The <span class="code">|</span> 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
       (<span class="code">: Mod</span>), otherwise modules like <span class="code">kernel</span> would be
       converted to all functions of the application with the same
       name; the most general constant is used in cases of ambiguity.
      </li>
      <li>Since we are only interested in a ratio, the unary
       operator <span class="code">#</span> that counts the elements of the operand is
       used. It cannot be applied to the <span class="code">digraph</span> representation
       of graphs.
      </li>
      <li>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.
      </li>
    </ul>
    <p>When the Erlang function <span class="code">t/1</span> 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>
  
</div>
<div class="footer">
<hr>
<p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>