Copyright Digital Equipment Corp. All rights reserved.

Advanced_Query_Examples

   The examples in this section use the SCA$EXAMPLE library. You are
   encouraged to try these queries using the example library.

   1.  FIND CALLED_BY( END=translit, DEPTH=ALL)

   This query gives the full call tree for TRANSLIT.

   2.  FIND CALLED_BY( END=translit, BEGIN=signal_duplicate, DEPTH=ALL)

   This query returns all the call paths emanating from translit that
   end up calling SIGNAL_DUPLICATE.

   3.  FIND CALLED_BY( translit, DEPTH=ALL, TRACE=(NOT OPEN*))

   This query gives the full call tree for TRANSLIT, but does not
   show any calls from items named OPEN*. Calls to items named OPEN*
   appear in the call tree; however, items which are called by OPEN*
   do not appear. Try the query without the trace expression and
   compare the results when the TRACE is given.

   4.  FIND CALLED_BY( END=translit,
                       BEGIN=(NOT DOMAIN=PREDEFINED and NOT lib$*),
                       DEPTH=ALL )

   This example leaves predefined functions and functions named
   LIB$* out of the call graph. Functions such as CHR and WRITELN
   in Pascal, MAX in FORTRAN, a builtin like _ADAWI in C, and so
   forth are predefined. These functions are defined by the language,
   not the programmer.


   5.  FIND IN( build_table and occ=comp, max_code )

   This example finds all occurrences of MAX_CODE in the module
   BUILD_TABLE. In this case, module has the same meaning as it
   does in SHOW MODULE. This is the fastest way to limit a query to
   occurrences in a particular module. The first parameter to the IN
   function tells SCA in what container to look. The "and occ=comp"
   part of the query ensures that the BUILD_TABLE you are looking
   in is one of the modules displayed by SHOW MODULE, rather than
   something else.

   The second parameter to the IN function tells SCA what to look
   for. This is faster than specifying the following:

         FIND IN( build_table and occ=comp ) and max_code

   Both queries in this example produce the same result.


   Routines Used in a Module But Declared Elsewhere


   In this example, you find functions that are used in a given
   module but have their primary declaration in some other module.
   This example is a multistep process that makes use of previous
   queries. Each query in this section is numbered so that you can
   refer to a specific query. If you refer to a query, adjust the
   query name (for example, where @1 is used) to refer to the query
   name you have created.

   1.  FIND IN( translit and occurrence=compilation_unit, -
            symbol=function and domain=(global,inheritable) )

   This query finds all occurrences of functions, either declarations
   or references, in the module TRANSLIT.

   You use "domain=(global,inheritable)" to limit the query only
   to occurrence in which you are interested. Only global and
   inheritable symbols can be imported because module-specific
   symbols are from the same module, and predefined symbols come
   from the language. Next, you have to remove any functions that
   have their primary declaration in the module.


   2.  FIND @1 AND NOT EXPAND( @1 and occurrence=primary )

   This query removes any functions that have a primary declaration
   in the module TRANSLIT. What remains are those global or
   inheritable functions that do not have a primary declaration in
   TRANSLIT.

   The EXPAND function in this query can be evaluated efficiently
   by SCA. The parameter to EXPAND, @1 and occurrence=primary, can
   be evaluated by looking at the result of query 1, so SCA does not
   have to use the SCA library. Because the overall query does @1 AND
   ..., everything in the result is present in the result of query 1.
   All we are doing is removing occurrences. In this case, SCA can
   evaluate the whole query expression by looking at the result of
   query 1 and does not have to use the SCA library.


   Items Declared In a Module But Not Used Anywhere In the Module


   In this example, you find occurrences of functions or variables
   that are declared in a module but are not used in the module. This
   example is a multistep process that makes use of previous queries.
   The numbers by each query are used to refer to it later. If you
   refer to a query, adjust the query name (for example, where @1 is
   used) to refer to the query names you have created.

   1.  FIND IN( translit and occurrence=compilation_unit, -
                symbol=(function, variable) )

   This query finds all occurrences of functions or variables, either
   declarations or references, in the module TRANSLIT.


   2.  FIND @1 AND NOT EXPAND( @1 and occurrence=reference )

   This query removes from our first query any functions or variables
   that have a reference in the module TRANSLIT. What remains are
   those functions or variables that are not used anywhere in the
   module.

   The EXPAND function in this query can be evaluated efficiently
   by SCA. The parameter to EXPAND, @1 and occ=reference, can be
   evaluated just by looking at the result of query 1, so SCA does
   not have to use the SCA library. Because the overall query does
   @1 AND ..., everything in the result is present in the result of
   query 1. All we are doing is removing items. In this case, SCA can
   evaluate the whole query expression by looking at the result of
   query 1, and does not have to use the SCA library.


   Finding Unused Functions


   This example finds functions or subroutines that are never used.
   It provides several ways of solving the problem. Some of these are
   easy to understand, but can be very slow on larger SCA libraries.
   The more complex ones are intended to improve performance on
   larger SCA libraries. They do not have a significant impact on
   smaller libraries.

   The first example finds unused functions only. Note that instead
   of saying "occurrence=call" to find functions that are called, you
   specify "occurrence=reference" to find functions that are used at
   all. The query is as follows:

     FIND symbol=function AND occurrence=primary -
         AND NOT EXPAND( symbol=function and occurrence=reference )

   On the SCA$EXAMPLE library, this query works well because it is
   a small library. On a larger library, it may be too slow. To
   evaluate this query, SCA must first evaluate "symbol=function
   and occurrence=primary." It must then evaluate "symbol=function
   and occurrence=reference" before doing any additional processing.
   In this case, SCA has to do twice what is essentially the same
   work. Also, SCA does not discard information about functions that
   are referenced until the end, so it uses a lot of memory.


   Using Previous Query Results to Find Unused Functions Faster

   The next example also finds unused functions. However, it uses
   previous query results, so the work is done only once. For this
   reason, it is faster than the previous example. It also uses
   somewhat less memory, but still not enough to make a difference on
   a large library.

     FIND symbol=function and occurrence=(primary,reference)

   In the previous query, we find all the occurrences that we want to
   use. We ignore the associated declarations at this point because
   they are not essential to the query.

   Next, we must select those functions that are not used as in the
   following query:

     FIND @1 AND occurrence=primary -
          AND NOT EXPAND( @1 AND occurrence=reference )

   This query removes from the list of functions in our system any
   that are referenced, leaving only unreferenced functions. Because
   you are using a previous query with all the information in it,
   SCA does not have to access the SCA library, and performance is
   generally faster.

   However, on a large library, this may still be slow. The reason
   for this is that it ends up keeping a list of all the functions
   and all their references in memory.


   Using Iteration to Find Unused Functions Faster


   This is the most complex example. It includes some repetitive
   parts that the query language does not provide directly. You
   can do these using the callable interface, or by writing a .COM
   procedure, or you can do the repetitive parts manually. This is
   also the fastest form of the example and uses less memory.

   Basically, you are going to split up the work into smaller pieces
   to avoid having to keep everything in memory at the same time. In
   this example, you process one module at a time, so you need to get
   a list of modules first. You can do this by entering the following
   query:

   1. FIND occurrence=compilation_unit

      In the next step, you have to loop through each of the
      occurrences found in step 1. This part cannot be done directly
      using the query language. You can do this using one of the
      following methods:

      o  Do this manually, stepping through the occurrences in the
         query one by one, and using INDICATED() in the following
         queries where module_name is specified.

      o  Use the /DISPLAY options to specify only the name of each
         occurrence found, capture the result in a file, and write
         a command procedure to loop over the names. In this case,
         you use "module_name and occurrence=compilation_unit" in the
         following queries where module_name is specified.

      o  Use the callable interface. By writing a small program
         using the callable interface, you can do the loop relatively
         easily, using SCA$GET_OCCURRENCE and SCA$SELECT_OCCURRENCE.

      In any case, you repeat the following steps for each of the
      modules found in step 1.

   2. FIND IN( module_name, symbol=function and occurrence=primary )

      This step finds primary declarations of functions in the
      current module. You want only primary declarations at this
      stage because there may be some calls in other modules. In the
      next step, you find any references to those functions:

   3. FIND EXPAND( @2 )

      This finds everything you need. At this point, what you do is
      very similar to what you did for the examples in the previous
      section.

   4. FIND @3 and occurrence=primary -
           AND NOT EXPAND( @3 and occurrence=reference )

      This finds those functions in a particular module that are not
      referenced anywhere. Steps 2 through 4 must be repeated for
      each module.