NOUSERMACRO(oxref function tree)

includefile(../../release.yo)

htmlbodyopt(text)(#27408B)
htmlbodyopt(bgcolor)(#FFFAF0)
whenhtml(mailto(Frank B. Brokken: f.b.brokken@rug.nl))

DEFINEMACRO(lsoption)(3)(\
    bf(--ARG1)=tt(ARG3) (bf(-ARG2))\
)
DEFINEMACRO(laoption)(2)(\
    bf(--ARG1)=tt(ARG2)\
)
DEFINEMACRO(loption)(1)(\
    bf(--ARG1)\
)
DEFINEMACRO(soption)(1)(\
    bf(-ARG1)\
)


DELETEMACRO(tt)
DEFINEMACRO(tt)(1)(em(ARG1))

COMMENT( man-request, section, date, distribution file, general name)
manpage(oxref)(1)(_CurYrs_)(oxref._CurVers_)
        (oxref - cross reference utility)

COMMENT( man-request, larger title )
manpagename(oxref)(cross reference utility for various languages)

COMMENT( all other: add after () )
manpagesynopsis()
       bf(oxref) [OPTIONS] tt(arguments) nl()
        [OPTIONS] - see the bf(OPTIONS) section below nl()
        arguments - object files and/or libraries to process nl()

    The cross reference listing is written to the standard output stram.

manpagedescription()

The program bf(oxref) generates cross reference listings, program or function
call-trees, and/or (recursive) called-by overviews of specified functions
using non-stripped object files and/or libraries.

Cross reference listings contain the names and source files of functions
defined in the specified object files and/or libraries, as well as an overview
of the functions calling these functions.

Call-trees show the (nested) tree of functions directly or indirectly 
called from the top-level (main program) function.

Called-by overviews start from a specified function name, and 
(recursively) show the functions calling the specified function.

Brief examples of these three modes of operation are shown below.

Especially the 'called-by' overview is useful information during program
development and debugging phases, as it immediately provides the hierarchy of
functions directly or indirectly calling the specified function name.

E.g., assuming that the signature; the pre-conditions or the
post-conditions of a function must be changed it is important to know from
what function(s) the function-to-modify is called to verify that the changes
to the modified function do not break its calling functions.

bf(Oxref)'s output starts with a header showing information about the
program, a time stamp and the arguments passed to tt(oxref). E.g.,

verb(
oxref by Frank B. Brokken (f.b.brokken@rug.nl)
oxref V 2.01.00 2012-2023

CREATED Wed, 25 Oct 2023 11:56:44 +0000
OXREF ARGUMENTS: -t main -r replace -fxs tmp/main.o tmp/libmodules.a 
----------------------------------------------------------------------
)

The header is (depending on the specified options) followed by the cross
reference information, the call tree and/or the called-by overview.

bf(Cross reference listings) show the symbols, as well as (optionally) their 
full names (e.g., prefixed by class-names), source files and the source files
and names of functions using the symbols. The cross reference listings of a
global variable and a function looks like this:
    verb(
    author
      Full name: Icmbuild::author
      Source:    version.cc 
      Used By:
        header.cc: header(int, char**)
        usage.cc: usage(std::string const&)
    
    calledFrom(unsigned long)
      Full name: XrefData::calledFrom(unsigned long)
      Source:    calledfrom.cc 
      Used By:
        undefined.cc: Store::undefined(std::string const&)
    )

bf(Call trees) show the names of all entities used or called from a certain
starting point. For bf(C) and bf(C++) programs the starting point tt(main)
produces the program's full call tree. A (partially shown) call tree might
look like this:
        verb(
    CALL TREE FOR: main
    
    main
    +-usage(std::string const&)
    | +-Icmbuild::version
    +-Storage::Storage()
    | +-Store::Store()
    | +-Storage::patternFile(std::string const&)
    +-Storage::tree() const
      +-Store::tree(std::string const&) const
        +-Tree::print(unsigned long, unsigned long)
          +-Tree::calls(unsigned long, unsigned long)
          | +-Tree::calls(unsigned long, XrefData const&)
          +-Tree::indent(unsigned long) const
        )
    Calling levels are indented using +- indicators, continuation at identical
levels are indicated by vertical lines, using | characters. In the shown call
tree tt(main) calls tt(usage), the tt(Storage) constructor and the
tt(Storage::tree()) member. Likewise, the tt(Storage) constructor calls the
tt(Store) constructor and the member tt(Storage::patternFile). Recursively
called functions appear in the overview where their names are followed by
tt(==> nr) arrows where tt(nr) refers to the call-level where the function is
defined. The top level (e.g. tt(main)) is referred to as level 0. Here is an
example showing recursion in the call-tree of the tt(bisonc++) program:
        verb(
    main
    ...
    +-Grammar::deriveSentence()
    | +-Rules::s_startSymbol
    | +-Grammar::derivable(Symbol const*)
    |   +-Grammar::becomesDerivable(Production const*)
    |   | +-Grammar::derivable(Symbol const*) ==> 2
    |   +-Grammar::isDerivable(Production const*)
    ...
        )
    Indirect recursion is shown this way as well.

Caveat: in order to produce the program's call tree the object file containing
the program's starting point (e.g., tt(main)) must be available to
tt(oxref). If tt(main.o) is the object file of the function tt(main) then
tt(main.o) must explicitly be specified as tt(oxref's) command-line argument
(see, e.g., the command specification shown above in the header line of 
tt(oxref's) output).

bf(Called-by listings) start from a specified function (specified as a regular
expression but usually simply specified as tt(ClassName::memberFunction),
showing (recursively) the functions calling the specified function (see option
tt(--called-by) below):
    verb(
    CALLED-BY LISTING:
    
    Store::define(std::string const&, bool) (define.cc): called by
        Store::setFunction(std::string const&) (setfunction.cc)
        Store::setObject(std::string const&) (setobject.cc)
        Store::setSource(std::string const&) (setsource.cc)
    
    Store::setFunction(std::string const&) (setfunction.cc): called by
        Storage::function(std::string const&) (function.cc)
    
    Store::setObject(std::string const&) (setobject.cc): called by
        Storage::object(std::string const&) (object.cc)
    
    Store::setSource(std::string const&) (setsource.cc): called by
        Storage::sourceFile(std::string const&) (sourcefile.cc)
    
    Storage::function(std::string const&) (function.cc): called by
        Storage::push_back(std::string) (pushback.cc)
    
    Storage::object(std::string const&) (object.cc): called by
        Storage::push_back(std::string) (pushback.cc)
    
    Storage::sourceFile(std::string const&) (sourcefile.cc): called by
        Storage::push_back(std::string) (pushback.cc)
    
    Storage::push_back(std::string) (pushback.cc): called by
        main (main.cc)
)

manpagesection(RETURN VALUE)

    bf(Oxref) returns 1 to the operating system if an error occurs or
if bf(oxref) automatically shows its usage info. 

    bf(Oxref) returns 0 if the requested action was successfully completed, or
if the tt(--version) or tt(--help) options are specified.

manpageoptions()

    Where available, single letter options are listed between parentheses
following their associated long-option variants. Single letter options require
arguments if their associated long options require arguments as well.

    itemization(
    it() lsoption(arg)(a)(mode)nl()
        Mode specifies the way the output is abbreviated:nl()

        bf(count) - function parameters are suppressed; instead the number of
        arguments required by a function is shown in its parameter
        list. Example:
      verb(
    usage(1)
        )
    instead of
        verb(
    usage(std::string const&)
        )

    bf(first) - only show the first word of parameters. Example:
        verb(
    insertDefined(unsigned, std::ostream&, std::vector&)
        )
    instead of
        verb(
    insertDefined(unsigned int, std::ostream&, 
                  std::vector<XrefData, 
                  std::allocator<XrefData> > const&)
        )

        bf(len) - where tt(len) is a positive integral number (5 is used if
        tt(len) is less than 5). The value tt(len) specifies the maximum
        length of parameter names. If parameter names need to be truncated, an
        ellipsis replaces the truncated characters.  Example using tt(-a 12):
       verb(
    insertDefined(unsigned int, std::ostream&, std::vect...&)
        )
    instead of
        verb(
    insertDefined(unsigned int, std::ostream&, 
                  std::vector<XrefData, 
                  std::allocator<XrefData> > const&)
        )

    it() lsoption(called-by)(c)(spec)nl()
       tt(spec) is a regular expression showing (recursively) the function(s)
        and the functions calling those functions. Although tt(spec) can refer
        to multiple functions, a single function can be specified as, e.g.,
        its name, prefixed by the function's class. E.g., tt(Store::define)
        (which is a member function of bf(oxref)'s tt(Store) class, see the
        bf(DESCRIPTION) section).

        When specifying the tt(--called-by) option the tt(-f) and tt(-s)
        options do not have to be specified. If only the called-by hierarchy
        is requested the tt(--no-xref) option can be specified to prevent
        writing the cross-reference listing to the standard output stream.

        As an example: to generated the tt(called-by) listing for bf(oxref)'s
        tt(Store::define) function the following command was issued:
            verb(
oxref -Xc Store::define -r replacements tmp/main.o tmp/libmodules.a
            )
        (with tt(replacements) being the file containing bf(oxref)'s type
        replacements, see option tt(--replace-file) below).

    it() loption(full-symbol) soption(f)nl()
       The full names of the symbols are shown, in addition to the plain
        symbol names (see also options tt(object-files, source-files) and
        tt(xref-source-files)).nl() 
       Full names include class names and/or namespace identifiers. Example:
       verb(
insertDefined(unsigned int, std::ostream&, std::vector<XrefData,
              std::allocator<XrefData> > const&) 
  Full name: Store::insertDefined(unsigned int, std::ostream&,
          std::vector<XrefData, std::allocator<XrefData> > const&) 
        )
        
    it() loption(help) (soption(h))nl() 
       Basic usage information is written to the standard error stream.

    it() loption(no-xref) (soption(X))nl()
       The tt(no-xref) option prevents the cross-reference information from
        being written to the standard output stream. It can be useful in
        situations where you're only interested in the program's 
        call-tree (cf. option tt(--tree)).

    it() laoption(objdump)(command)nl()
       The tt(command) option value specifies how the object-dumping program
        is called. By default it is called as tt(/usr/bin/objdump -C -t). In
        practice there's probably no reason for using this option.

    it() loption(object-files) (soption(o))nl()
       Include in the cross reference listing the name of object files in
        which symbols (data, functions) are defined (see also options
        tt(full-symbol, source-files) and tt(xref-source-files))

    it() laoption(replace)(spec) (soption(R))nl()
       Output generated by tt(objdump) may show the compiler's ideas of what,
        e.g., a bf(C++) tt(std::string) is. Thus, instead of a parameter
        tt(std::sting const &) it may show
   verb(
    std::__cxx11::basic_string<char, std::char_traits<char> 
                                                    const &
   )
        tt(R) options are used to specify text replacements of the form 
    verb(
    #find#replace#
    )
       where tt(#) can be any character not used in either the tt(find) text
        or the tt(replace) text. For example:
    verb(
    #std::__cxx11::basic_string<char, std::char_traits<char>#std::string#
    )
       Multiple tt(R) options may be specified, which are applied in sequence
        line-by-line to all output lines of tt(objdump). E.g, after replacing
        the above long definition of a string into tt(std::string) subsequent
        replacements should use tt(std::string) rather than the original long
        definition provided by the compiler.

        In practice replacement specifications are specified after initially
        running tt(oxref) without any specifications. The required
        replacements are then derived from the obtained output

    it() laoption(replace-file)(fname) (soption(r))nl()
       Replacement specifications can also be stored in a file. Specifications
        read from file are handled like those obtained from tt(replace)
        options with the tt(replace) options being processed before the
        replacement specifications read from the file specified with the
        tt(replace_file) are processed.

    it() laoption(select)(name)nl()
       Only display the cross-reference of tt(name), where tt(name) is the
        (case sensitive) initial substring of a symbol

    it() laoption(select-pattern)(regex)nl()
       Only display the cross-reference of symbols matching the regular
        expression tt(regex), where tt(regex) is a regular expression matching
        the bf(regex)(7) specification, including the extensions offered by
        the bf(pattern)(3bobcat) bf(Pattern) class. Case sensitive matching is
        used here, too.

    it() loption(source-files) (soption(s))nl()
       Include in the cross reference listing the names of the source files in
        which symbols are defined (see also options tt(full-symbol,
        object-files) and tt(xref-source-files))

    it() laoption(tree)(fname) (soption(t))nl()
       The tt(tree) option generates a call tree for function tt(fname). The
        argument tt(fname) defines the starting point of the call tree. Note
        that the program's starting point (usually tt(main)) does not normally
        appear in a cross-reference listing, as it is not used by other parts
        of the program. To obtain the call tree for the program's starting
        function in these cases specify tt(--tree main). Otherwise, if the
        call tree of another function is requested its `Full name'
        specification as used in the cross-reference listing must be
        used.

    it() loption(xref-source-files) (soption(x))nl()
       Include in the cross reference listing the name of source files in
        which used symbols are defined (see also options tt(full-symbol,
        object-files) and tt(source-files))

    it() loption(version) (soption(v))nl()
       tt(Oxref)'s version number is written to the standard error stream.
    )    

manpagesection(EXAMPLES)

    The examples show how tt(oxref) was called, followed by a representative
example of a cross-reference listing for a symbol. tt(Oxref)'s own cross
reference listing was used:
    verb(
called as: oxref liboxref

define(std::string const&, bool)
  Used By:
    Store::setFunction(std::string const&)
    Store::setObject(std::string const&)
    Store::setSource(std::string const&)

--------------------

called as: oxref -foxs liboxref

define(std::string const&, bool)
  Full name: Store::define(std::string const&, bool)
  Source:    define.cc (1define.o)
  Used By:
    setfunction.cc: Store::setFunction(std::string const&)
    setobject.cc: Store::setObject(std::string const&)
    setsource.cc: Store::setSource(std::string const&)
    )

manpagebugs()

    No bugs reported

manpagesection(ABOUT)

    In theory, creating cross reference listings is a complex matter as it
requires a full syntax analysis of the sources defining a program. Especially
with complex languages like bf(C++) this is a difficult hurdle to pass. 

    Looking for `cross reference programs' using a search engine returns
remarkably few hits. LXR is a promising cross referencing program (see
lurl(http://lxr.linux.no/)), but it requires the use of data base packages,
making it somewhat complex to use. Other links refer to cross-reference
programs for textual documents, not programs.

    The complexity of developing a program generating a 
cross reference listing has baffled me for a long time. Eventually I realized
that in practice the essential information has already been generated by the
compiler, when it compiles our source files. So why do it all again?

    Once a program has been compiled one or (usually) more object files are
available. The linker uses tables of defined and external symbols embedded
in the object files to connect the various functions. If all requirements can
be satisfied the linker is able to create a running program.

    Programs like bf(nm)(1) and bf(objdump)(1) can be used to produce human 
readable output from the information embedded in object files. tt(Oxref) reads
this information and organizes it, creating a cross reference listing.

    Since all compilable program languages generate identically organized
object files (or maybe better: generate object files that can be interpreted
by bf(objdump)(1)), tt(oxref) can broadly be applied. As long as
bf(objdump)(1) produces sensible output tt(oxref) should be able to generate a
cross reference listing.

    tt(Oxref)'s name consists of two syllables: tt(o) and tt(xref). The tt(o)
represents the program bf(objdump)(1), called from tt(oxref) as a child
program. The important part is of course the cross-referencing of
symbols. Like the common abbreviation of em(rail-road crossing), em(rail-road
xing), cross referencing is abbreviated to tt(xref). Hence tt(oxref). 

    Of course, nearly everybody will read tt(oxref) as
tt(ox-ref). Fortunately, here too we're on familiar ground: Bison, Cow, Gnu,
Yacc: all are bovine animals. To that important list tt(oxref) adds the Ox.

manpagefiles()
    
    An example of tt(oxref)'s own cross reference listing is provided (on
Debian systems) in the file
        verb(
    /usr/share/doc/oxref/oxref.xref.gz
        )

manpageseealso()

bf(nm)(1), bf(objdump)(1), bf(pattern)(3bobcat), bf(regex)(7)

manpageauthor()

Frank B. Brokken (f.b.brokken@rug.nl).
