Copyleft (c) 1997 by Tom Howland (tom@rahul.net)

			XREF: CROSS-REFERENCING PROGRAM

The xref program has been replaced by one contributed by Tom Howland of
KnowledgeWare which is considerably faster and more robust.

The main purpose of this cross referencer is to find unreachable code.
Therefore, it begins by looking for a definition for runtime_entry/1
and also looks for initialization and extern directives to start tracing
the reachable code from.

A second function of xref is to aid in the formation of module statements,
xref can list all of the required module/2 and use_module/2 statements by
file. Unlike the previous version of xref, it does not automatically modify
files to include these statements.

I.  BASIC USE OF THE PROGRAM

The simplest way to use the program is to build a runtime system with
the command:

	make BIN=<arch> qpxref

and then invoke <arch>/qpxref with one of more Prolog file specifications.

qpxref takes a number of options, as follows:

usage: qpxref [-v] [-c] [-i ifile] [-w wfile] [-x xfile] [-u ufile] fspec ...
 
  -c ......... generate standard compiler style error messages
  -v ......... verbose output. This echoes the names of the files being read to
               stderr.
  -i ifile ... an initialization file. This is the same as the initialization
               file supplied to qpc.
  -w wfile ... warning file. Warnings are written to stderr by default.
  -x xfile ... cross reference file. The cross reference is written to stdout by
               default.
  -m mfile ... generate a file indicating which predicates are imported and
               which are exported for each file. This is not generated by
               default.
  -u ufile ... generate a file listing all the undefined predicates.  This is
               not generated by default.
  fspec ...... one or more prolog file specifications.

II. PRACTICE & EXPERIENCE

Your code will probably rely on operator declarations and possibly term
expansion. The cross referencer handles this in the same way as qpc
(Quintus Prolog Compiler): you must supply an initialization file.

Supply meta_predicate definitions for your meta predicates. Otherwise
the cross referencer will not follow the meta predicates arguments. The
cross referencer doesn't care if they appear in module(user), unlike
qpc. Be sure the cross referencer has read the meta predicate definition
*before* it reads calls to it.

You must supply a definition for runtime_entry/1, so the cross
referencer knows where to start looking: this cross referencer is a tool
for finding unreachable code.

The cross referencer follows runtime_entry/1, initializations, and
externs. The way it handles meta-predicates requires that your
application load its module files before its non-module files.

This cross referencer was written in order to tear out the copious dead code
from the application that the author became responsible for. If you are doing
such a thing, the cross referencer is an invaluable tool. Be sure to
save the output from the first run that you get from the cross
referencer: this is very useful resource to help you find things that
you've accidentally ripped out and that you really needed after all.

There are situations where the cross referencer does not follow certain
predicates. This can happen if the predicate name is constructed on the
fly, or if it is retrieved from the database. In this case, create a
file that calls these from runtime_entry(start).  Alternatively, you
could create term expansions that are peculiar to the cross referencer.

III. FUTURE WORK

qpc understands the "when(compile_time)" directive to load_files/2. The
cross referencer uses the same flag to ignore a file. The reason is that
there is no easy way of removing changes that such a load would cause once
the context of that load is finished. Supplying the file as part of the
initialization is only a partial solution.
