AutoDox Readme file

AutoDox Readme

AutoDox is intended to promote code reuse by documenting key programs,
including their parameters, internal procedures, and functions.
One specific purpose is to use this product to generate documentation
for your persistent procedures, so that all developers, particularly those
who are learning your software application, will be able to easily look
up key features of the most important programs to be reused.

AutoDox documents all of the procedures and functions in your programs,
including those found in include files.
Because Proparse does its own preprocessing, AutoDox works as if working
with preprocessed source, rather than with raw, un-preprocessed source.

Future Directions

AutoDox is an open-source project, and as such, contributions are welcome.
This section describes some of the things that we will do...
if nobody else does them first. :-)
Most urgently: AutoDox must be made accessible and customizable.

Accessible

Currently, AutoDox takes a list of programs to document,
and generates detail pages, the table of contents, the index frame, and
the summary page, all in one pass. This does not make it easy to regenerate
the detail page for a single compile unit, nor does it make it easy to
add a single new program to the documentation set.

Customizable

The AutoDox code is mostly one large program file.
It must be restructured so that individual bits of it can be
over-ridden, without making it difficult to accept new versions
of AutoDox.

We recognize that the easiest way to do this would be with V9 features,
but we feel that there are still enough people on 8.3
that it is important to to find another way.
Perhaps we could structure things so that the core code can be
over-ridden, using V9 features, but the core code still works with 8.3?

Methods from Include Files

AutoDox currently shows all methods and all functions,
even those which come from include files.
It would be good to be able to specify include files which are
commonly used, whose methods should only be documented once in a
separate details page.
The include file would then be documented more like a distinct "method library".
The programs which reference that include would then just have a link from
their page to the include's page.


Instructions

  • Unzip autodox.zip into a directory in your propath. It will unzip into a directory
    called "autodox".
  • Build a list of the names of the programs (.w, .p, etc.) that you want to document.
    The filenames that you put into this fileList are the ones that are
    used in the resulting HTML, and should be absolute references.
    Put one program name per line. Lines can be commented out by inserting
    lines containing nothing but open comment (/*) and closing comment (*/).
  • Run AutoDox from somewhere in your propath, for example
    "RUN autodox/autodox.p (INPUT "yourDirectory/yourFileList.txt")."
  • You'll enter your required HTML output directory, and your application's name.
  • Open the resulting HTML file "index.html" in your output directory to view
    your generated documentation.

As needed, identification of other significant code structures can be added
to autodox/autodox2.p and thus to the resulting documentation. These may perhaps
include definition of global variables, external procedure RUN statements, etc.


Generated HTML Files

This program generates the following set of .html files containing the documentation:


  • index.html: main document with links to the summary and a table of contents.

  • toc.html: a table of contents listing all of the program names only.

  • summary.html: a summary page listing all of the programs
    with a one-line description.

  • detail<n>.html: one detail page per program,
    with the significant features listed.






Customizing AutoDox For Your Application

AutoDox may be customized as necessary to tailor the result to your application. The following
sections will help with this. See also the Future Directions section above.


AutoDox HTML Notes

Since autodox/autodox2.p generates HTML which will then be analyzed and displayed by
your web browser, please note the following:

  • to make your HTML appear properly in your web browser, put a ‘<BR>’ in
    your PUT UNFORMATTEDs in this program wherever you want a newline in your web page
    as viewed from your web browser. It is very important that you use the single quotes
    above in the program - see autodox/autodox2.p for examples.
  • to make your HTML more readable, put a ‘~n’ in your PUT UNFORMATTEDs in
    this program wherever you want a newline in your HTML. These won't affect how
    your finished pages look when viewed by your browser. Remember to use the single quotes too.
  • use single quotes around your HTML in your PUT UNFORMATTEDs, but use double
    quotes inside these single quotes wherever you need a double quote to be
    in the resulting HTML.

Working with the Parse Tree

AutoDox uses Proparse to generate a parse tree of your program,
then does various manipulations
through this tree (using the Proparse API)
to gather the data for the HTML documentation.
For more information about working with parse trees and using the Proparse API,
see your Proparse Documentation.

Looking for Comments

Points to note when looking for your program's comments and white space when working with
the Proparse-generated parse tree:

  • comments are stored in hidden tokens with a type of "COMMENT"
  • white space is stored in hidden tokens with a type of "WS", and is contiguous
    (a block of white space may contain line feeds and therefore extend over many
    lines, from one real text node or comment token to the next real text node or
    comment token).
  • depending on your code conventions, you may put the comment for a statement
    before the statement, or after the statement.
    An example:

     
      /* This is a comment BEFORE the x statement. */
      DEFINE VARIABLE x AS INTEGER NO-UNDO. 
    
      DEFINE VARIABLE y AS INTEGER NO-UNDO. /* This is a comment AFTER the y statement. */
      

    If these two statements existed in your code, there would also be a further hidden
    token between them, of type "WS", and containing the line feed after the first
    " NO-UNDO.", plus any spaces and the line feed on the line between the two
    define statements. Therefore, the one hidden WS token would span all of the "empty
    space" between the PERIOD of the first DEFINE statement and the beginning DEFINE of
    the next one.

  • you could find this white space by either looking up the parserHiddenGetAfter() token
    after the . (PERIOD) node at the end of the first statement, or you could find it
    by looking for the parserHiddenGetBefore() token before the second DEFINE node.

autodox/autodox2.p contains two internal procedures for finding comments,
called getCommentBefore and getCommentAfter.

Configuration Parameters

The following configuration parameters in autodox/autodox.p are used to change where
AutoDox will look for your comments. Unfortunately, using a generalization like this
will miss certain comments in your code unless your code is incredibly consistently
commented. For example, it is fairly common that when programmers comment variable
definitions, they will put the comment to the right ("after") the DEFINE statement
if it is a short comment, and put it on the line above ("before") the DEFINE
statement if it is a long comment. Only one of these at a time can be meaningfully picked up
by AutoDox, so it is best to configure AutoDox to aim for the majority of cases
based on your own code.

Internal Procedure Comments

Use setProcCommentLoc = TRUE (before) to look for a comment before the procedure
statement, actually immediately before the PROCEDURE node itself,
for example when your code looks like this:

  /* comment for myProc */
  PROCEDURE myProc:   ...

Use setProcCommentLoc = FALSE (after) to look for a comment after the procedure statement,
more specifically after the COLON (LEXCOLON) or PERIOD terminating your
PROCEDURE statement, for example when your code looks like this:

  PROCEDURE myProc.     /* the comment I'm looking for */ 
    /* rest of myProc */
  END PROCEDURE.
or: 
  PROCEDURE myExtProc EXTERNAL "myProc.dll":   /* the comment I'm looking for */ 
    /* rest of myExtProc */
  END PROCEDURE.

Function Comments

Use setFuncCommentLoc = TRUE (before) to look for a comment before the function
statement, actually immediately before the FUNCTION node itself,
for example when your code looks like this:

  /* comment for myFunc */
  FUNCTION myFunc:   ...

Use setFuncCommentLoc = FALSE (after) to look for a comment after the function statement,
more specifically after the COLON (LEXCOLON) or PERIOD terminating your
FUNCTION statement, for example when your code looks like this:

  FUNCTION myFunc RETURNS LOGICAL FORWARD.   /* the comment I'm looking for */ 
or: 
  FUNCTION myFunc RETURNS LOGICAL:           /* the comment I'm looking for */ 
    /* rest of myFunc */
  END FUNCTION.

Parameter Comments

Use setParamCommentLoc = TRUE (before) to look for a comment before the DEFINE
PARAMETER statement, actually immediately before the DEFINE node itself,
for example when your code looks like this:

  /* comment for myParam */
  DEFINE INPUT PARAMETER myParam AS CHARACTER NO-UNDO. 

Use setParamCommentLoc = FALSE (after) to look for a comment after the DEFINE PARAMETER
statement, more specifically after the PERIOD terminating
your DEFINE statement, for example when your code looks like this:

  DEFINE INPUT PARAMETER myParam AS CHARACTER NO-UNDO.   /* the comment I'm looking for */ 

Note: for parameter comments after the DEFINE statement, it is best to only
accept comments that are on the same line as the DEFINE statement. Otherwise, you may
pick up a comment after your DEFINE and before the next DEFINE statement, but that
belongs to the next DEFINE statement. For example, with this code you could accidentally pick up
the comment for myParam3 when you are really looking for the comment AFTER myParam2,
which doesn't exist:

  DEFINE INPUT PARAMETER myParam1 AS CHARACTER NO-UNDO.   /* the comment for myParam1 */ 
  DEFINE INPUT PARAMETER myParam2 AS CHARACTER NO-UNDO.   

  /* the comment for myParam3, in a BEFORE position. */ 
  DEFINE INPUT PARAMETER myParam3 AS CHARACTER NO-UNDO.   

See autodox/autodox2.p internal procedure getCommentAfter for an example of checking
that your comments are on the same line.

Finding the First Comment in a Program

This is the first step in documenting a program. See autodox/autodox2.p Step 1.
(internal procedure getProcComment).

To find the first comment in a program, (hopefully a description of the program!),
start at the topmost node, the Program_root node. This is a synthetic node (didn't
exist in the original program, but exists for working with the parse tree).
In a loop, do a parserNodeFirstChild of this synthetic Program_root node (and its' children's
children as needed) until you find a real node instead of a synthetic node. Real
nodes are the nodes for which parserGetNodeText() will return true. They have text
because they existed in the original program text.

Then, from this first real node,
work backwards through any hidden tokens linked to it (only real nodes will have
hidden text, i.e. comments and whitespace, linked to them) by doing a
parserHiddenGetBefore(), then as many parserHiddenGetPrevious() calls as necessary
and discarding any hidden nodes that are not parserHiddenGetType() = "COMMENT".
When you run out of hidden nodes linked to the beginning of the real node ("before"
the real node), the last (uppermost) hidden "COMMENT" node you found will be the
first comment appearing in the original program text. You may need more than this
one node depending on the commenting convention in your programs, for example if you
have each comment line as its' own comment (one /* */ pair on each line).

Hidden node examples:

  /* This is all 
   * one hidden comment
   * token, with line 
   * feeds 
   * and all */
  
  /* This is a hidden token on its' own (of parserHiddenGetType() = "COMMENT") */
  /* and this is another separate hidden comment token. */

(These last two hidden comment tokens are actually separated by a line feed, which is
in yet another hidden token, of parserHiddenGetType() = "WS".)