Replacing text version of coding standards with a HTML one.
authorjongfoster <jongfoster@users.sourceforge.net>
Mon, 10 Sep 2001 19:00:25 +0000 (19:00 +0000)
committerjongfoster <jongfoster@users.sourceforge.net>
Mon, 10 Sep 2001 19:00:25 +0000 (19:00 +0000)
This is a cosmetic change only.

doc/STANDARDS.txt [deleted file]
doc/standards.html [new file with mode: 0644]

diff --git a/doc/STANDARDS.txt b/doc/STANDARDS.txt
deleted file mode 100644 (file)
index 705c33b..0000000
+++ /dev/null
@@ -1,1134 +0,0 @@
-@ Introduction
-
-
-This set of standards is designed to make our lives easier. It is
-developed with the simple goal of helping us keep the "new and
-improved Junkbusters" consistent and reliable.  Thus making
-maintenance easier and increasing chances of success of the
-project.
-
-And that of course comes back to us as individuals. If we can
-increase our development and product efficiencies then we can
-solve more of the request for changes/improvements and in general 
-feel good about ourselves.  ;->
-
-
-@ Using Comments
-
-
-@@ Comment, Comment, Comment
-
-@@@ Explanation:
-
-Comment as much as possible without commenting the obvious.  For
-example do not comment "aVariable is equal to bVariable".  Instead
-explain why aVariable should be equal to the bVariable.  Just
-because a person can read code does not mean they will understand
-why or what is being done.  A reader may spend a lot more time
-figuring out what is going on when a simple comment or explanation
-would have prevented the extra research.  Please help your brother
-IJB'ers out!
-
-The comments will also help justify the intent of the code.  If the
-comment describes something different than what the code is doing
-then maybe a programming error is occurring.
-
-@@@ Example:
-
-/* if page size greater than 1k ... */
-if ( PageLength() > 1024 )
-{
-    ... "block" the page up ...
-}
-
-/* if page size is small, send it in blocks */
-if ( PageLength() > 1024 )
-{
-    ... "block" the page up ...
-}
-
-This demonstrates 2 cases of "what not to do".  The first is a
-"syntax comment".  The second is a comment that does not fit what
-is actually being done.
-
-
-@@ Use blocks for comments
-
-@@@ Explanation:
-
-Comments can help or they can clutter.  They help when they are
-differentiated from the code they describe.  One line comments do
-not offer effective separation between the comment and the code.
-Block identifiers do, by surrounding the code with a clear,
-definable pattern.
-
-@@@ Example:
-
-/*********************************************************************
- * This will stand out clearly in your code!
- *********************************************************************/
-if ( thisVariable == thatVariable )
-{
-   DoSomethingVeryImportant();
-}
-
-
-/* unfortunately, this may not */
-if ( thisVariable == thatVariable )
-{
-   DoSomethingVeryImportant();
-}
-
-
-if ( thisVariable == thatVariable ) /* this may not either */
-{
-   DoSomethingVeryImportant();
-}
-
-@@@ Exception:
-
-If you are trying to add a small logic comment and do not wish to
-"disrubt" the flow of the code, feel free to use a 1 line comment
-which is NOT on the same line as the code.
-
-
-@@ Keep Comments on their own line
-
-@@@ Explanation:
-
-It goes back to the question of readability.  If the comment is on
-the same line as the code it will be harder to read than the
-comment that is on its own line.
-
-There are three exceptions to this rule, which should be violated
-freely and often: during the definition of variables, at the end
-of closing braces, when used to comment parameters.
-
-@@@ Example:
-
-/*********************************************************************
- * This will stand out clearly in your code,
- * But the second example won't.
- *********************************************************************/
-if ( thisVariable == thatVariable )
-{
-   DoSomethingVeryImportant();
-}
-
-if ( thisVariable == thatVariable ) /*can you see me?*/
-{
-   DoSomethingVeryImportant(); /*not easily*/
-}
-
-
-/*********************************************************************
- * But, the encouraged exceptions:
- *********************************************************************/
-int urls_read     = 0;     /* # of urls read + rejected */
-int urls_rejected = 0;     /* # of urls rejected */
-
-if ( 1 == X )
-{
-   DoSomethingVeryImportant();
-}
-
-
-short DoSomethingVeryImportant(
-   short firstParam,   /* represents something */
-   short nextParam     /* represents something else */ )
-{
-   ...code here...
-
-}   /* -END- DoSomethingVeryImportant */
-
-
-@@ Comment each logical step
-
-@@@ Explanation:
-
-Logical steps should be commented to help others follow the
-intent of the written code and comments will make the code more
-readable.
-
-If you have 25 lines of code without a comment, you should
-probably go back into it to see where you forgot to put one.
-
-Most "for", "while", "do", etc... loops _probably_ need a
-comment.  After all, these are usually major logic containers.
-
-
-@@ Comment All Functions Thoroughly
-
-@@@ Explanation:
-
-A reader of the code should be able to look at the comments just
-prior to the beginning of a function and discern the reason for
-its existence and the consequences of using it.  The reader
-should not have to read through the code to determine if a given
-function is safe for a desired use.  The proper information
-thoroughly presented at the introduction of a function not only
-saves time for subsequent maintenance or debugging, it more
-importantly aids in code reuse by allowing a user to determine
-the safety and applicability of any function for the problem at
-hand.  As a result of such benefits, all functions should contain
-the information presented in the addendum section of this
-document.
-
-
-@@ Comment at the end of braces if the content is more than one screen length
-
-@@@ Explanation:
-
-Each closing brace should be followed on the same line by a
-comment that describes the origination of the brace if the
-original brace is off of the screen, or otherwise far away from
-the closing brace.  This will simplify the debugging, maintenance,
-and readability of the code.
-
-As a suggestion , use the following flags to make the comment and
-its brace more readable:
-
-use following a closing brace:
-   } /* -END- if() or while () or etc... */
-
-@@@ Example:
-
-if ( 1 == X )
-{
-   DoSomethingVeryImportant();
-   ...some long list of commands...
-} /* -END- if x is 1 */
-
-or:
-
-if ( 1 == X )
-{
-   DoSomethingVeryImportant();
-   ...some long list of commands...
-} /* -END- if ( 1 == X ) */
-
-
-@ Naming Conventions
-
-
-@@ Variable Names
-
-@@@ Explanation:
-
-Use all lowercase, and seperate words via an underscore ('_').
-Do not start an identifier with an underscore.  (ANSI C
-reserves these for use by the compiler and system headers.)
-Do not use identifiers which are reserved in ANSI C++.
-(E.g. template, class, true, false, ...).  This is in case
-we ever decide to port JunkBuster to C++.
-
-@@@ Example:
-
-int ms_iis5_hack = 0;
-
-@@@ Instead of:
-
-int msiis5hack = 0;
-int msIis5Hack = 0;
-
-
-@@ Function Names
-
-@@@ Explanation:
-
-Use all lowercase, and seperate words via an underscore ('_').
-Do not start an identifier with an underscore.  (ANSI C
-reserves these for use by the compiler and system headers.)
-Do not use identifiers which are reserved in ANSI C++.
-(E.g. template, class, true, false, ...).  This is in case
-we ever decide to port JunkBuster to C++.
-
-@@@ Example:
-
-int load_some_file( struct client_state *csp )
-
-@@@ Instead of:
-
-int loadsomefile( struct client_state *csp )
-int loadSomeFile( struct client_state *csp )
-
-
-@@ Header file prototypes
-
-@@@ Explanation:
-
-Use a descriptive parameter name in the function prototype in
-header files.  Use the same parameter name in the header file
-that you use in the c file.
-
-@@@ Example:
-
-(.h) extern int load_aclfile( struct client_state *csp );
-(.c) int load_aclfile( struct client_state *csp )
-
-@@@ Instead of:
-(.h) extern int load_aclfile( struct client_state * );   or
-(.h) extern int load_aclfile();
-(.c) int load_aclfile( struct client_state *csp )
-
-
-@@  Enumerations, and #defines
-
-@@@ Explanation:
-
-Use all capital letters, with underscores between words.
-Do not start an identifier with an underscore.  (ANSI C
-reserves these for use by the compiler and system headers.)
-
-@@@ Example:
-
-(enumeration) : enum Boolean { FALSE, TRUE };
-(#define) : #define DEFAULT_SIZE 100;
-
-@@@ Note: We have a standard naming scheme for #defines that
-toggle a feature in the preprocessor: FEATURE_xxx, where 
-xxx is a short (preferably 1 or 2 word) description.
-
-@@@ Example:
-
-#define FEATURE_FORCE 1
-
-#ifdef FEATURE_FORCE
-#define FORCE_PREFIX blah
-#endif /* def FEATURE_FORCE */
-
-
-@@ Constants
-
-@@@ Explanation:
-
-Spell common words out entirely (do not remove vowels).
-
-Use only widely-known domain acronyms and abbreviations.  Capitalize
-all letters of an acronym.
-
-Use underscore (_) to separate adjacent acronyms and
-abbreviations.  Never terminate a name with an underscore.
-
-@@@ Example:
-
-#define USE_IMAGE_LIST 1
-
-@@@ Instead of:
-
-#define USE_IMG_LST 1       or
-#define _USE_IMAGE_LIST 1   or
-#define USE_IMAGE_LIST_ 1   or
-#define use_image_list  1   or
-#define UseImageList    1
-
-
-@ Using Space
-
-
-@@ Put braces on a line by themselves.
-
-@@@ Explanation:
-
-The brace needs to be on a line all by itself, not at the end of
-the statement.  Curly braces should line up with the construct
-that they're associated with.  This practice makes it easier to
-identify the opening and closing braces for a block.
-
-@@@ Example:
-
-if ( this == that )
-{
-   ...
-}
-
-@@@ Instead of:
-
-if ( this == that ) {
-   ...
-}
-
-or
-
-if ( this == that ) { ...  }
-
-@@@ Note: In the special case that the if-statement is inside a loop,
-and it is trivial, i.e. it tests for a condidtion that is obvious
-from the purpose of the block, one-liners as above may optically
-preserve the loop structure and make it easier to read.
-
-@@@ Status: developer-discrection.
-
-@@@ Example exception:
-
-while ( more lines are read )
-{
-   /* Please document what is/is not a comment line here */
-   if ( it's a comment ) continue;
-
-   do_something( line );
-}
-
-
-@@ ALL control statements should have a block
-
-@@@ Explanation:
-
-Using braces to make a block will make your code more readable
-and less prone to error.  All control statements should have a
-block defined.
-
-@@@ Example:
-
-if ( this == that )
-{
-   DoSomething();
-   DoSomethingElse();
-}
-
-@@@ Instead of:
-
-if ( this == that )
-   DoSomething();
-   DoSomethingElse();
-
-or
-
-if ( this == that ) DoSomething();
-
-@@@ Note: The first example in "Instead of" will execute in a manner
-other than that which the developer desired (per indentation).  Using
-code braces would have prevented this "feature".  The "explanation"
-and "exception" from the point above also applies.
-
-
-@@ Do not belabor/blow-up boolean expressions
-
-@@@ Example:
-
-structure->flag = ( condition );
-
-@@@ Instead of:
-
-if ( condition )
-{
-   structure->flag = 1;
-}
-else
-{
-   structure->flag = 0;
-}
-
-@@@ Note: The former is readable and consice.  The later is wordy and
-inefficient.  Please assume that any developer new to the project has
-at least a "good" knowledge of C/C++.  (Hope I do not offend by that
-last comment ... 8-)
-
-
-@@ Use white space freely because it is free
-
-@@@ Explanation:
-
-Make it readable.  The notable exception to using white space
-freely is listed in the next guideline.
-
-@@@ Example:
-
-int firstValue   = 0;
-int someValue    = 0;
-int anotherValue = 0;
-int thisVariable = 0;
-
-if ( thisVariable == thatVariable )
-
-firstValue = oldValue + ( ( someValue - anotherValue ) - whatever )
-
-
-@@ Don't use white space around structure operators
-
-@@@ Explanation:
-
-- structure pointer operator ( "->" ) 
-- member operator ( "." )
-- functions and parentheses
-
-It is a general coding practice to put pointers, references, and
-function parentheses next to names.  With spaces, the connection
-between the object and variable/function name is not as clear.
-
-@@@ Example:
-
-aStruct->aMember;
-aStruct.aMember;
-FunctionName();
-
-@@@ Instead of:
-aStruct -> aMember;
-aStruct .  aMember;
-FunctionName ();
-
-
-@@ Make the last brace of a function stand out
-
-@@@ Example:
-
-int function1( ... )
-{
-   ...code...
-   return( retCode );
-
-}   /* -END- function1 */
-
-
-int function2( ... )
-{
-}   /* -END- function2 */
-
-
-@@@ Instead of:
-
-int function1( ... )
-{
-   ...code...
-   return( retCode );
-}
-int function2( ... )
-{
-}
-
-@@@ Note: Use 1 blank line before the closing brace and 2 lines
-afterwards.  This makes the end of function standout to the most
-casual viewer.  Although function comments help seperate functions,
-this is still a good coding practice.  In fact, I follow these rules
-when using blocks in "for", "while", "do" loops, and long if {}
-statements too.  After all whitespace is free!
-
-@@@ Status: developer-discrection on the number of blank lines.
-Enforced is the end of function comments.
-
-
-@@ Use 3 character indentions
-
-@@@ Explanation:
-
-If some use 8 character TABs and some use 3 character TABs, the code
-can look *very* ragged.  So use 3 character indentions only.  If you
-like to use TABs, pass your code through a filter such as "expand -t3"
-before checking in your code.
-
-@@@ Example:
-
-static const char * const url_code_map[256] =
-{
-   NULL, ...
-};
-
-
-int function1( ... )
-{
-   if ( 1 )
-   {
-      return( ALWAYS_TRUE );
-   }
-   else
-   {
-      return( HOW_DID_YOU_GET_HERE );
-   }
-
-   return( NEVER_GETS_HERE );
-
-}
-
-
-@ Initializing
-
-
-@@ Initialize all variables
-
-@@@ Explanation:
-
-Do not assume that the variables declared will not be used until
-after they have been assigned a value somewhere else in the
-code.  Remove the chance of accidentally using an unassigned
-variable.
-
-@@@ Example:
-
-short anShort = 0;
-float aFloat  = 0;
-struct *ptr = NULL;
-
-@@@ Note: It is much easier to debug a SIGSEGV if the message says
-you are trying to access memory address 00000000 and not
-129FA012; or arrayPtr[20] causes a SIGSEV vs. arrayPtr[0].
-
-@@@ Status: developer-discrection if and only if the variable is
-assigned a value "shortly after" declaration.
-
-
-@ Functions
-
-
-@@ Name functions that return a boolean as a question.
-
-@@@ Explanation:
-
-Value should be phrased as a question that would logically be
-answered as a true or false statement
-
-@@@ Example:
-
-ShouldWeBlockThis();
-ContainsAnImage();
-IsWebPageBlank();
-
-
-@@ Always specify a return type for a function.
-
-@@@ Explanation:
-
-The default return for a function is an int.  To avoid ambiguity,
-create a return for a function when the return has a purpose, and
-create a void return type if the function does not need to return
-anything.
-
-
-@@ Minimize function calls when iterating by using variables
-
-@@@ Explanation:
-
-It is easy to write the following code, and a clear argument can
-be made that the code is easy to understand:
-
-@@@ Example:
-
-for ( size_t cnt = 0; cnt < blockListLength(); cnt ++ )
-{
-   ....
-}
-
-@@@ Note: Unfortunately, this makes a function call for each and every
-iteration.  This increases the overhead in the program, because the
-compiler has to look up the function each time, call it, and return a
-value.  Depending on what occurs in the blockListLength() call, it
-might even be creating and destroying structures with each iteration,
-even though in each case it is comparing "cnt" to the same value, over
-and over.  Remember too - even a call to blockListLength() is a
-function call, with the same overhead.
-
-Instead of using a function call during the iterations, assign
-the value to a variable, and evaluate using the variable.
-
-@@@ Example:
-
-size_t len = blockListLength();
-
-for ( size_t cnt = 0; cnt < len; cnt ++ )
-{
-   ....
-}
-
-@@@ Exceptions: if the value of blockListLength() *may* change or could
-*potentially* change, then you must code the function call in the
-for/while loop.
-
-
-@@ Pass and Return by Const Reference
-
-@@@ Explanation:
-
-This allows a developer to define a const pointer and call your
-function.  If your function does not have the const keyword, we
-may not be able to use your function.  Consider strcmp, if it
-were defined as:
-   extern int strcmp( char *s1, char *s2 );
-
-I could then not use it to compare argv's in main:
-   int main( int argc, const char *argv[] )
-   {
-     strcmp( argv[0], "junkbusters" );
-   }
-
-Both these pointers are *const*!  If the c runtime library maintainers
-do it, we should too.
-
-
-@@ Pass and Return by Value
-
-@@@ Explanation:
-
-Most structures cannot fit onto a normal stack entry (i.e. they
-are not 4 bytes or less).  Aka, a function declaration like:
-   int load_aclfile( struct client_state csp )
-
-would not work.  So, to be consistent, we should declare all
-prototypes with "pass by value":
-   int load_aclfile( struct client_state *csp )
-
-
-@@ Use #include <fileName> and #include "fileName" for locals
-
-@@@ Explanation:
-
-Your include statements should contain the file name without a
-path.  The path should be listed in the Makefile, using -I as
-processor directive to search the indicated paths.  An exception
-to this would be for some proprietary software that utilizes a
-partial path to distinguish their header files from system or
-other header files.
-
-@@@ Example:
-
-#include <iostream.h>     /* This is not a local include */
-#include "config.h"       /* This IS a local include */
-
-@@@ Exception:
-
-/* This is not a local include, but requires a path element. */
-#include <sys/fileName.h>
-
-@@@ Note: Please! do not add "-I." to the Makefile without a _very_
-good reason.  This duplicates the #include "file.h" behaviour.
-
-
-@@ Provide multiple inclusion protection
-
-@@@ Explanation:
-
-Prevents compiler and linker errors resulting from redefinition of
-items.
-
-Wrap each header file with the following syntax to prevent multiple
-inclusions of the file.  Of course, replace PROJECT_H with
-your file name, with "." Changed to "_", and make it uppercase.
-
-@@@ Example:
-
-#ifndef PROJECT_H_INCLUDED
-#define PROJECT_H_INCLUDED
- ...
-#endif /* ndef PROJECT_H_INCLUDED */
-
-
-@@ Use `extern "C"` when appropriate
-
-@@@ Explanation:
-
-If our headers are included from C++, they must declare our 
-functions as `extern "C"`.  This has no cost in C, but increases
-the potential re-usability of our code.
-
-@@@ Example:
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* def __cplusplus */
-
-... function definitions here ...
-
-#ifdef __cplusplus
-}
-#endif /* def __cplusplus */
-
-
-@@ Where Possible, Use Forward Struct Declaration Instead of Includes
-
-@@@ Explanation:
-
-Useful in headers that include pointers to other struct's.
-Modifications to excess header files may cause needless compiles.
-
-@@@ Example:
-
-/*********************************************************************
- * We're avoiding an include statement here!
- *********************************************************************/
-struct file_list;
-extern file_list *xyz;
-
-@@@ Note: If you declare "file_list xyz;" (without the pointer), then
-including the proper header file is necessary.  If you only want to
-prototype a pointer, however, the header file is unneccessary.
-
-@@@ Status: Use with discrection.
-
-
-@ General Coding Practices
-
-
-@@ Turn on warnings
-
-@@@ Explanation
-
-Compiler warnings are meant to help you find bugs.  You should turn
-on as many as possible.  With GCC, the switch is "-Wall".  Try and 
-fix as many warnings as possible.
-
-
-@@ Provide a default case for all switch statements
-
-@@@ Explanation:
-
-What you think is guaranteed is never really guaranteed.  The value
-that you don't think you need to check is the one that someday will be
-passed.  So, to protect yourself from the unknown, always have a
-default step in a switch statement.
-
-@@@ Example:
-
-switch( hash_string( cmd ) )
-{
-   case hash_actions_file :
-      ... code ...
-      break;
-
-   case hash_confdir :
-      ... code ...
-      break;
-
-   default :
-      log_error( ... );
-      ... anomly code goes here ...
-      continue; / break; / exit( 1 ); / etc ...
-
-} /* end switch( hash_string( cmd ) ) */
-
-@@@ Note: If you already have a default condition, you are obviously
-exempt from this point.  Of note, most of the WIN32 code calls
-`DefWindowProc' after the switch statement.  This API call
-*should* be included in a default statement.
-
-@@@ Another Note: This is not so much a readability issue as a robust
-programming issue.  The "anomly code goes here" may be no more than a
-print to the STDERR stream (as in load_config).  Or it may really be
-an ABEND condition.
-
-@@@ Status: Programmer discretion is advised.
-
-
-@@ Try to avoid falling through cases in a switch statement.
-
-@@@ Explanation:
-
-In general, you will want to have a 'break' statement within each
-'case' of a switch statement.  This allows for the code to be more
-readable and understandable, and furthermore can prevent unwanted
-surprises if someone else later gets creative and moves the code
-around.
-
-The language allows you to plan the fall through from one case
-statement to another simply by omitting the break statement within the
-case statement.  This feature does have benefits, but should only be
-used in rare cases.  In general, use a break statement for each case
-statement.
-
-If you choose to allow fall through, you should comment both the fact
-of the fall through and reason why you felt it was necessary.
-
-
-@@ Use 'long' or 'short' Instead of 'int'
-
-@@@ Explanation:
-
-On 32-bit platforms, int usually has the range of long.  On 16-bit
-platforms, int has the range of short.
-
-@@@ Status: open-to-debate.  In the case of most FSF projects
-(including X/GNU-Emacs), there are typedefs to int4, int8, int16, (or
-equivalence ... I forget the exact typedefs now).  Should we add these
-to IJB now that we have a "configure" script?
-
-
-@@ Don't mix size_t and other types
-
-@@@Explanation:
-
-The type of size_t varies across platforms.  Do not make assumptions
-about whether it is signed or unsigned, or about how long it is.
-Do not compare a size_t against another variable of a different type
-(or even against a constant) without casting one of the values.  
-Try to avoid using size_t if you can.
-
-
-@@ Declare each variable and struct on its own line.
-
-@@@ Explanation:
-
-It can be tempting to declare a series of variables all on one line.
-Don't.
-
-@@@ Example:
-
-long a = 0;
-long b = 0;
-long c = 0;
-
-@@@ Instead of:
-
-long a, b, c;
-
-@@@ Explanation:
-- there is more room for comments on the individual variables
-- easier to add new variables without messing up the original ones
-- when searching on a variable to find its type, there is less
-  clutter to "visually" eliminate
-
-@@@ Exceptions: when you want to declare a bunch of loop variables or
-other trivial variables; feel free to declare them on 1 line.  You
-should, although, provide a good comment on their functions.
-
-@@@ Status: developer-discrection.
-
-
-@@ Use malloc/zalloc sparingly
-
-@@@ Explanation:
-
-Create a local stuct (on the stack) if the variable will live
-and die within the context of one function call.
-
-Only "malloc" a struct (on the heap) if the variable's life will
-extend beyond the context of one function call.
-
-@@@ Example:
-
-If a function creates a struct and stores a pointer to it in a
-list, then it should definately be allocated via `malloc'.
-
-
-@@ The Programmer Who Uses 'malloc' is Responsible for Ensuring 'free'
-
-@@@ Explanation:
-
-If you have to "malloc" an instance, you are responsible for insuring
-that the instance is `free'd, even if the deallocation event falls
-within some other programmer's code.  You are also responsible for
-ensuring that deletion is timely (i.e. not too soon, not too late).
-This is known as "low-coupling" and is a "good thing (tm)".  You may
-need to offer a free/unload/destuctor type function to accomodate
-this.
-
-@@@ Example:
-
-int load_re_filterfile( struct client_state *csp ) { ... }
-static void unload_re_filterfile( void *f ) { ... }
-
-@@@ Exceptions:
-
-The developer cannot be expected to provide `free'ing functions for 
-C run-time library functions ... such as `strdup'.
-
-@@@ Status: developer-discrection.  The "main" use of this standard is
-for allocating and freeing data structures (complex or nested).
-
-
-@@ Add loaders to the `file_list' structure and in order
-
-@@@ Explanation:
-
-I have ordered all of the "blocker" file code to be in alpha
-order.  It is easier to add/read new blockers when you expect a
-certain order.
-
-@@@ Note: It may appear that the alpha order is broken in places by
-POPUP tests coming before PCRS tests.  But since POPUPs can also
-be referred to as KILLPOPUPs, it is clear that it should come
-first.
-
-
-@@ "Uncertain" new code and/or changes to exitinst code, use FIXME
-
-@@@ Explanation:
-
-If you have enough confidence in new code or confidence in your
-changes, but are not *quite* sure of the reprocussions, add this:
-
-/* FIXME: this code has a logic error on platform XYZ,
- * attempthing to fix
- */
-#ifdef PLATFORM
-   ...changed code here...
-#endif
-
-or:
-
-/* FIXME: I think the original author really meant this... */
-   ...changed code here...
-
-or:
-
-/* FIXME: new code that *may* break something else... */
-   ...new code here...
-
-@@@ Note: If you make it clear that this may or may not be a "good
-thing (tm)", it will be easier to identify and include in the project
-(or conversly exclude from the project).
-
-
-@ Addendum: Template for files and function comment blocks:
-
-
-@@@ Example for file comments:
-
-const char FILENAME_rcs[] = "$Id: STANDARDS.txt,v 1.4 2001/07/13 01:27:19 iwanttokeepanon Exp $";
-/*********************************************************************
- *
- * File        :  $S<!-- Break CVS Substitution -->ource$
- *
- * Purpose     :  (Fill me in with a good description!)
- *
- * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
- *                IJBSWA team.  http://ijbswa.sourceforge.net
- *
- *                Based on the Internet Junkbuster originally written
- *                by and Copyright (C) 1997 Anonymous Coders and 
- *                Junkbusters Corporation.  http://www.junkbusters.com
- *
- *                This program is free software; you can redistribute it 
- *                and/or modify it under the terms of the GNU General
- *                Public License as published by the Free Software
- *                Foundation; either version 2 of the License, or (at
- *                your option) any later version.
- *
- *                This program is distributed in the hope that it will
- *                be useful, but WITHOUT ANY WARRANTY; without even the
- *                implied warranty of MERCHANTABILITY or FITNESS FOR A
- *                PARTICULAR PURPOSE.  See the GNU General Public
- *                License for more details.
- *
- *                The GNU General Public License should be included with
- *                this file.  If not, you can view it at
- *                http://www.gnu.org/copyleft/gpl.html
- *                or write to the Free Software Foundation, Inc., 59
- *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * Revisions   :
- *    $L<!-- Break CVS Substitution -->og$
- *
- *********************************************************************/
-\f
-
-#include "config.h"
-
-   ...necessary include files for us to do our work...
-
-const char FILENAME_h_rcs[] = FILENAME_H_VERSION;
-
-
-@@@ Note: This declares the rcs variables that should be added to the
-"show-proxy-args" page.  If this is a brand new creation by you, you
-are free to change the "Copyright" section to represent the rights you
-wish to maintain.
-
-@@@ Note: The formfeed character that is present right after the
-comment flower box is handy for (X|GNU)Emacs users to skip the verbige
-and get to the heart of the code (via `forward-page' and
-`backward-page').  Please include it if you can.
-
-@@@ Example for file header comments:
-
-#ifndef _FILENAME_H
-#define _FILENAME_H
-#define FILENAME_H_VERSION "$Id: STANDARDS.txt,v 1.4 2001/07/13 01:27:19 iwanttokeepanon Exp $"
-/*********************************************************************
- *
- * File        :  $S<!-- Break CVS Substitution -->ource$
- *
- * Purpose     :  (Fill me in with a good description!)
- *
- * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
- *                IJBSWA team.  http://ijbswa.sourceforge.net
- *
- *                Based on the Internet Junkbuster originally written
- *                by and Copyright (C) 1997 Anonymous Coders and 
- *                Junkbusters Corporation.  http://www.junkbusters.com
- *
- *                This program is free software; you can redistribute it 
- *                and/or modify it under the terms of the GNU General
- *                Public License as published by the Free Software
- *                Foundation; either version 2 of the License, or (at
- *                your option) any later version.
- *
- *                This program is distributed in the hope that it will
- *                be useful, but WITHOUT ANY WARRANTY; without even the
- *                implied warranty of MERCHANTABILITY or FITNESS FOR A
- *                PARTICULAR PURPOSE.  See the GNU General Public
- *                License for more details.
- *
- *                The GNU General Public License should be included with
- *                this file.  If not, you can view it at
- *                http://www.gnu.org/copyleft/gpl.html
- *                or write to the Free Software Foundation, Inc., 59
- *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * Revisions   :
- *    $L<!-- Break CVS Substitution -->og$
- *
- *********************************************************************/
-\f
-
-#include "project.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-   ... function headers here ...
-
-
-/* Revision control strings from this header and associated .c file */
-extern const char FILENAME_rcs[];
-extern const char FILENAME_h_rcs[];
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ndef _FILENAME_H */
-
-/*
-  Local Variables:
-  tab-width: 3
-  end:
-*/
-
-
-@@@ Example for function comments:
-
-/*********************************************************************
- *
- * Function    :  FUNCTION_NAME
- *
- * Description :  (Fill me in with a good description!)
- *
- * Parameters  :
- *          1  :  param1 = pointer to an important thing
- *          2  :  x      = pointer to something else
- *
- * Returns     :  0 => Ok, everything else is an error.
- *
- *********************************************************************/
-int FUNCTION_NAME( void *param1, const char *x )
-{
-   ...
-   return( 0 );
-
-}
-
-
-@@@ Note: If we all follow this practice, we should be able to parse
-our code to create a "self-documenting" web page.
-
-
-@ Local variables for this standards file
-
-
-\f
-Local variables:
-mode: outline
-mode: auto-fill
-outline-regexp: "[@]+"
-tab-width: 3
-End:
diff --git a/doc/standards.html b/doc/standards.html
new file mode 100644 (file)
index 0000000..257c382
--- /dev/null
@@ -0,0 +1,1485 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>JunkBuster Coding Standards</title>
+  </head>
+
+  <body>
+    <h1><a name="top"></a>JunkBuster Coding Standards</h1>
+
+    <h1><a name="contents"></a>Contents</h1>
+
+    <h3><a href="#s1">Introduction</a></h3>
+
+    <h3><a href="#s2">Using Comments</a></h3>
+
+    <ul>
+      <li><a href="#s3">Comment, Comment, Comment</a></li>
+
+      <li><a href="#s4">Use blocks for comments</a></li>
+
+      <li><a href="#s5">Keep Comments on their own line</a></li>
+
+      <li><a href="#s6">Comment each logical step</a></li>
+
+      <li><a href="#s7">Comment All Functions Thoroughly</a></li>
+
+      <li><a href="#s8">Comment at the end of braces if the content
+      is more than one screen length</a></li>
+    </ul>
+
+    <h3><a href="#s9">Naming Conventions</a></h3>
+
+    <ul>
+      <li><a href="#s10">Variable Names</a></li>
+
+      <li><a href="#s11">Function Names</a></li>
+
+      <li><a href="#s12">Header file prototypes</a></li>
+
+      <li><a href="#s13">Enumerations, and #defines</a></li>
+
+      <li><a href="#s14">Constants</a></li>
+    </ul>
+
+    <h3><a href="#s15">Using Space</a></h3>
+
+    <ul>
+      <li><a href="#s16">Put braces on a line by
+      themselves.</a></li>
+
+      <li><a href="#s17">ALL control statements should have a
+      block</a></li>
+
+      <li><a href="#s18">Do not belabor/blow-up boolean
+      expressions</a></li>
+
+      <li><a href="#s19">Use white space freely because it is
+      free</a></li>
+
+      <li><a href="#s20">Don't use white space around structure
+      operators</a></li>
+
+      <li><a href="#s21">Make the last brace of a function stand
+      out</a></li>
+
+      <li><a href="#s22">Use 3 character indentions</a></li>
+    </ul>
+
+    <h3><a href="#s23">Initializing</a></h3>
+
+    <ul>
+      <li><a href="#s24">Initialize all variables</a></li>
+    </ul>
+
+    <h3><a href="#s25">Functions</a></h3>
+
+    <ul>
+      <li><a href="#s26">Name functions that return a boolean as a
+      question.</a></li>
+
+      <li><a href="#s27">Always specify a return type for a
+      function.</a></li>
+
+      <li><a href="#s28">Minimize function calls when iterating by
+      using variables</a></li>
+
+      <li><a href="#s29">Pass and Return by Const
+      Reference</a></li>
+
+      <li><a href="#s30">Pass and Return by Value</a></li>
+
+      <li><a href="#s31">Use #include &lt;fileName&gt; and #include
+      "fileName" for locals</a></li>
+
+      <li><a href="#s32">Provide multiple inclusion
+      protection</a></li>
+
+      <li><a href="#s33">Use `extern "C"` when appropriate</a></li>
+
+      <li><a href="#s34">Where Possible, Use Forward Struct
+      Declaration Instead of Includes</a></li>
+    </ul>
+
+    <h3><a href="#s35">General Coding Practices</a></h3>
+
+    <ul>
+      <li><a href="#s36">Turn on warnings</a></li>
+
+      <li><a href="#s37">Provide a default case for all switch
+      statements</a></li>
+
+      <li><a href="#s38">Try to avoid falling through cases in a
+      switch statement.</a></li>
+
+      <li><a href="#s39">Use 'long' or 'short' Instead of
+      'int'</a></li>
+
+      <li><a href="#s40">Don't mix size_t and other types</a></li>
+
+      <li><a href="#s41">Declare each variable and struct on its
+      own line.</a></li>
+
+      <li><a href="#s42">Use malloc/zalloc sparingly</a></li>
+
+      <li><a href="#s43">The Programmer Who Uses 'malloc' is
+      Responsible for Ensuring 'free'</a></li>
+
+      <li><a href="#s44">Add loaders to the `file_list' structure
+      and in order</a></li>
+
+      <li><a href="#s45">"Uncertain" new code and/or changes to
+      exitinst code, use FIXME</a></li>
+    </ul>
+
+    <h3><a href="#s46">Addendum: Template for files and function
+    comment blocks:</a></h3>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s1"></a>Introduction</h1>
+
+    <p>This set of standards is designed to make our lives easier.
+    It is developed with the simple goal of helping us keep the
+    "new and improved Junkbusters" consistent and reliable. Thus
+    making maintenance easier and increasing chances of success of
+    the project.</p>
+
+    <p>And that of course comes back to us as individuals. If we
+    can increase our development and product efficiencies then we
+    can solve more of the request for changes/improvements and in
+    general feel good about ourselves. ;-&gt;</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s2"></a>Using Comments</h1>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s3"></a>Comment, Comment, Comment</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Comment as much as possible without commenting the obvious.
+    For example do not comment "aVariable is equal to bVariable".
+    Instead explain why aVariable should be equal to the bVariable.
+    Just because a person can read code does not mean they will
+    understand why or what is being done. A reader may spend a lot
+    more time figuring out what is going on when a simple comment
+    or explanation would have prevented the extra research. Please
+    help your brother IJB'ers out!</p>
+
+    <p>The comments will also help justify the intent of the code.
+    If the comment describes something different than what the code
+    is doing then maybe a programming error is occurring.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+/* if page size greater than 1k ... */
+if ( PageLength() &gt; 1024 )
+{
+    ... "block" the page up ...
+}
+
+/* if page size is small, send it in blocks */
+if ( PageLength() &gt; 1024 )
+{
+    ... "block" the page up ...
+}
+
+This demonstrates 2 cases of "what not to do".  The first is a
+"syntax comment".  The second is a comment that does not fit what
+is actually being done.
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s4"></a>Use blocks for comments</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Comments can help or they can clutter. They help when they
+    are differentiated from the code they describe. One line
+    comments do not offer effective separation between the comment
+    and the code. Block identifiers do, by surrounding the code
+    with a clear, definable pattern.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+/*********************************************************************
+ * This will stand out clearly in your code!
+ *********************************************************************/
+if ( thisVariable == thatVariable )
+{
+   DoSomethingVeryImportant();
+}
+
+
+/* unfortunately, this may not */
+if ( thisVariable == thatVariable )
+{
+   DoSomethingVeryImportant();
+}
+
+
+if ( thisVariable == thatVariable ) /* this may not either */
+{
+   DoSomethingVeryImportant();
+}
+
+</pre>
+
+    <p><b>Exception:</b></p>
+
+    <p>If you are trying to add a small logic comment and do not
+    wish to "disrubt" the flow of the code, feel free to use a 1
+    line comment which is NOT on the same line as the code.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s5"></a>Keep Comments on their own line</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>It goes back to the question of readability. If the comment
+    is on the same line as the code it will be harder to read than
+    the comment that is on its own line.</p>
+
+    <p>There are three exceptions to this rule, which should be
+    violated freely and often: during the definition of variables,
+    at the end of closing braces, when used to comment
+    parameters.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+/*********************************************************************
+ * This will stand out clearly in your code,
+ * But the second example won't.
+ *********************************************************************/
+if ( thisVariable == thatVariable )
+{
+   DoSomethingVeryImportant();
+}
+
+if ( thisVariable == thatVariable ) /*can you see me?*/
+{
+   DoSomethingVeryImportant(); /*not easily*/
+}
+
+
+/*********************************************************************
+ * But, the encouraged exceptions:
+ *********************************************************************/
+int urls_read     = 0;     /* # of urls read + rejected */
+int urls_rejected = 0;     /* # of urls rejected */
+
+if ( 1 == X )
+{
+   DoSomethingVeryImportant();
+}
+
+
+short DoSomethingVeryImportant(
+   short firstParam,   /* represents something */
+   short nextParam     /* represents something else */ )
+{
+   ...code here...
+
+}   /* -END- DoSomethingVeryImportant */
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s6"></a>Comment each logical step</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Logical steps should be commented to help others follow the
+    intent of the written code and comments will make the code more
+    readable.</p>
+
+    <p>If you have 25 lines of code without a comment, you should
+    probably go back into it to see where you forgot to put
+    one.</p>
+
+    <p>Most "for", "while", "do", etc... loops _probably_ need a
+    comment. After all, these are usually major logic
+    containers.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s7"></a>Comment All Functions Thoroughly</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>A reader of the code should be able to look at the comments
+    just prior to the beginning of a function and discern the
+    reason for its existence and the consequences of using it. The
+    reader should not have to read through the code to determine if
+    a given function is safe for a desired use. The proper
+    information thoroughly presented at the introduction of a
+    function not only saves time for subsequent maintenance or
+    debugging, it more importantly aids in code reuse by allowing a
+    user to determine the safety and applicability of any function
+    for the problem at hand. As a result of such benefits, all
+    functions should contain the information presented in the
+    addendum section of this document.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s8"></a>Comment at the end of braces if the
+    content is more than one screen length</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Each closing brace should be followed on the same line by a
+    comment that describes the origination of the brace if the
+    original brace is off of the screen, or otherwise far away from
+    the closing brace. This will simplify the debugging,
+    maintenance, and readability of the code.</p>
+
+    <p>As a suggestion , use the following flags to make the
+    comment and its brace more readable:</p>
+
+    <p>use following a closing brace: } /* -END- if() or while ()
+    or etc... */</p>
+
+    <p><b>Example:</b></p>
+<pre>
+if ( 1 == X )
+{
+   DoSomethingVeryImportant();
+   ...some long list of commands...
+} /* -END- if x is 1 */
+
+or:
+
+if ( 1 == X )
+{
+   DoSomethingVeryImportant();
+   ...some long list of commands...
+} /* -END- if ( 1 == X ) */
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s9"></a>Naming Conventions</h1>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s10"></a>Variable Names</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Use all lowercase, and seperate words via an underscore
+    ('_'). Do not start an identifier with an underscore. (ANSI C
+    reserves these for use by the compiler and system headers.) Do
+    not use identifiers which are reserved in ANSI C++. (E.g.
+    template, class, true, false, ...). This is in case we ever
+    decide to port JunkBuster to C++.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+int ms_iis5_hack = 0;
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>int msiis5hack = 0; int msIis5Hack = 0;</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s11"></a>Function Names</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Use all lowercase, and seperate words via an underscore
+    ('_'). Do not start an identifier with an underscore. (ANSI C
+    reserves these for use by the compiler and system headers.) Do
+    not use identifiers which are reserved in ANSI C++. (E.g.
+    template, class, true, false, ...). This is in case we ever
+    decide to port JunkBuster to C++.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+int load_some_file( struct client_state *csp )
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>int loadsomefile( struct client_state *csp ) int
+    loadSomeFile( struct client_state *csp )</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s12"></a>Header file prototypes</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Use a descriptive parameter name in the function prototype
+    in header files. Use the same parameter name in the header file
+    that you use in the c file.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+(.h) extern int load_aclfile( struct client_state *csp );
+(.c) int load_aclfile( struct client_state *csp )
+
+</pre>
+
+    <p><b>Instead of:</b> (.h) extern int load_aclfile( struct
+    client_state * ); or (.h) extern int load_aclfile(); (.c) int
+    load_aclfile( struct client_state *csp )</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s13"></a>Enumerations, and #defines</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Use all capital letters, with underscores between words. Do
+    not start an identifier with an underscore. (ANSI C reserves
+    these for use by the compiler and system headers.)</p>
+
+    <p><b>Example:</b></p>
+<pre>
+(enumeration) : enum Boolean { FALSE, TRUE };
+(#define) : #define DEFAULT_SIZE 100;
+
+</pre>
+
+    <p><b>Note:</b> We have a standard naming scheme for #defines
+    that toggle a feature in the preprocessor: FEATURE_xxx, where
+    xxx is a short (preferably 1 or 2 word) description.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+#define FEATURE_FORCE 1
+
+#ifdef FEATURE_FORCE
+#define FORCE_PREFIX blah
+#endif /* def FEATURE_FORCE */
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s14"></a>Constants</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Spell common words out entirely (do not remove vowels).</p>
+
+    <p>Use only widely-known domain acronyms and abbreviations.
+    Capitalize all letters of an acronym.</p>
+
+    <p>Use underscore (_) to separate adjacent acronyms and
+    abbreviations. Never terminate a name with an underscore.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+#define USE_IMAGE_LIST 1
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>#define USE_IMG_LST 1 or #define _USE_IMAGE_LIST 1 or
+    #define USE_IMAGE_LIST_ 1 or #define use_image_list 1 or
+    #define UseImageList 1</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s15"></a>Using Space</h1>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s16"></a>Put braces on a line by themselves.</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>The brace needs to be on a line all by itself, not at the
+    end of the statement. Curly braces should line up with the
+    construct that they're associated with. This practice makes it
+    easier to identify the opening and closing braces for a
+    block.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+if ( this == that )
+{
+   ...
+}
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>if ( this == that ) { ... }</p>
+
+    <p>or</p>
+
+    <p>if ( this == that ) { ... }</p>
+
+    <p><b>Note:</b> In the special case that the if-statement is
+    inside a loop, and it is trivial, i.e. it tests for a
+    condidtion that is obvious from the purpose of the block,
+    one-liners as above may optically preserve the loop structure
+    and make it easier to read.</p>
+
+    <p><b>Status:</b> developer-discrection.</p>
+
+    <p><b>Example exception:</b></p>
+<pre>
+while ( more lines are read )
+{
+   /* Please document what is/is not a comment line here */
+   if ( it's a comment ) continue;
+
+   do_something( line );
+}
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s17"></a>ALL control statements should have a
+    block</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Using braces to make a block will make your code more
+    readable and less prone to error. All control statements should
+    have a block defined.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+if ( this == that )
+{
+   DoSomething();
+   DoSomethingElse();
+}
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>if ( this == that ) DoSomething(); DoSomethingElse();</p>
+
+    <p>or</p>
+
+    <p>if ( this == that ) DoSomething();</p>
+
+    <p><b>Note:</b> The first example in "Instead of" will execute
+    in a manner other than that which the developer desired (per
+    indentation). Using code braces would have prevented this
+    "feature". The "explanation" and "exception" from the point
+    above also applies.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s18"></a>Do not belabor/blow-up boolean
+    expressions</h2>
+
+    <p><b>Example:</b></p>
+<pre>
+structure-&gt;flag = ( condition );
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>if ( condition ) { structure-&gt;flag = 1; } else {
+    structure-&gt;flag = 0; }</p>
+
+    <p><b>Note:</b> The former is readable and consice. The later
+    is wordy and inefficient. Please assume that any developer new
+    to the project has at least a "good" knowledge of C/C++. (Hope
+    I do not offend by that last comment ... 8-)</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s19"></a>Use white space freely because it is
+    free</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Make it readable. The notable exception to using white space
+    freely is listed in the next guideline.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+int firstValue   = 0;
+int someValue    = 0;
+int anotherValue = 0;
+int thisVariable = 0;
+
+if ( thisVariable == thatVariable )
+
+firstValue = oldValue + ( ( someValue - anotherValue ) - whatever )
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s20"></a>Don't use white space around structure
+    operators</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>- structure pointer operator ( "-&gt;" ) - member operator (
+    "." ) - functions and parentheses</p>
+
+    <p>It is a general coding practice to put pointers, references,
+    and function parentheses next to names. With spaces, the
+    connection between the object and variable/function name is not
+    as clear.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+aStruct-&gt;aMember;
+aStruct.aMember;
+FunctionName();
+
+</pre>
+
+    <p><b>Instead of:</b> aStruct -&gt; aMember; aStruct . aMember;
+    FunctionName ();</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s21"></a>Make the last brace of a function stand
+    out</h2>
+
+    <p><b>Example:</b></p>
+<pre>
+int function1( ... )
+{
+   ...code...
+   return( retCode );
+
+}   /* -END- function1 */
+
+
+int function2( ... )
+{
+}   /* -END- function2 */
+
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>int function1( ... ) { ...code... return( retCode ); } int
+    function2( ... ) { }</p>
+
+    <p><b>Note:</b> Use 1 blank line before the closing brace and 2
+    lines afterwards. This makes the end of function standout to
+    the most casual viewer. Although function comments help
+    seperate functions, this is still a good coding practice. In
+    fact, I follow these rules when using blocks in "for", "while",
+    "do" loops, and long if {} statements too. After all whitespace
+    is free!</p>
+
+    <p><b>Status:</b> developer-discrection on the number of blank
+    lines. Enforced is the end of function comments.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s22"></a>Use 3 character indentions</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>If some use 8 character TABs and some use 3 character TABs,
+    the code can look *very* ragged. So use 3 character indentions
+    only. If you like to use TABs, pass your code through a filter
+    such as "expand -t3" before checking in your code.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+static const char * const url_code_map[256] =
+{
+   NULL, ...
+};
+
+
+int function1( ... )
+{
+   if ( 1 )
+   {
+      return( ALWAYS_TRUE );
+   }
+   else
+   {
+      return( HOW_DID_YOU_GET_HERE );
+   }
+
+   return( NEVER_GETS_HERE );
+
+}
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s23"></a>Initializing</h1>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s24"></a>Initialize all variables</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Do not assume that the variables declared will not be used
+    until after they have been assigned a value somewhere else in
+    the code. Remove the chance of accidentally using an unassigned
+    variable.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+short anShort = 0;
+float aFloat  = 0;
+struct *ptr = NULL;
+
+</pre>
+
+    <p><b>Note:</b> It is much easier to debug a SIGSEGV if the
+    message says you are trying to access memory address 00000000
+    and not 129FA012; or arrayPtr[20] causes a SIGSEV vs.
+    arrayPtr[0].</p>
+
+    <p><b>Status:</b> developer-discrection if and only if the
+    variable is assigned a value "shortly after" declaration.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s25"></a>Functions</h1>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s26"></a>Name functions that return a boolean as a
+    question.</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Value should be phrased as a question that would logically
+    be answered as a true or false statement</p>
+
+    <p><b>Example:</b></p>
+<pre>
+ShouldWeBlockThis();
+ContainsAnImage();
+IsWebPageBlank();
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s27"></a>Always specify a return type for a
+    function.</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>The default return for a function is an int. To avoid
+    ambiguity, create a return for a function when the return has a
+    purpose, and create a void return type if the function does not
+    need to return anything.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s28"></a>Minimize function calls when iterating by
+    using variables</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>It is easy to write the following code, and a clear argument
+    can be made that the code is easy to understand:</p>
+
+    <p><b>Example:</b></p>
+<pre>
+for ( size_t cnt = 0; cnt &lt; blockListLength(); cnt ++ )
+{
+   ....
+}
+
+</pre>
+
+    <p><b>Note:</b> Unfortunately, this makes a function call for
+    each and every iteration. This increases the overhead in the
+    program, because the compiler has to look up the function each
+    time, call it, and return a value. Depending on what occurs in
+    the blockListLength() call, it might even be creating and
+    destroying structures with each iteration, even though in each
+    case it is comparing "cnt" to the same value, over and over.
+    Remember too - even a call to blockListLength() is a function
+    call, with the same overhead.</p>
+
+    <p>Instead of using a function call during the iterations,
+    assign the value to a variable, and evaluate using the
+    variable.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+size_t len = blockListLength();
+
+for ( size_t cnt = 0; cnt &lt; len; cnt ++ )
+{
+   ....
+}
+
+</pre>
+
+    <p><b>Exceptions:</b> if the value of blockListLength() *may*
+    change or could *potentially* change, then you must code the
+    function call in the for/while loop.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s29"></a>Pass and Return by Const Reference</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>This allows a developer to define a const pointer and call
+    your function. If your function does not have the const
+    keyword, we may not be able to use your function. Consider
+    strcmp, if it were defined as: extern int strcmp( char *s1,
+    char *s2 );</p>
+
+    <p>I could then not use it to compare argv's in main: int main(
+    int argc, const char *argv[] ) { strcmp( argv[0], "junkbusters"
+    ); }</p>
+
+    <p>Both these pointers are *const*! If the c runtime library
+    maintainers do it, we should too.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s30"></a>Pass and Return by Value</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Most structures cannot fit onto a normal stack entry (i.e.
+    they are not 4 bytes or less). Aka, a function declaration
+    like: int load_aclfile( struct client_state csp )</p>
+
+    <p>would not work. So, to be consistent, we should declare all
+    prototypes with "pass by value": int load_aclfile( struct
+    client_state *csp )</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s31"></a>Use #include &lt;fileName&gt; and
+    #include "fileName" for locals</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Your include statements should contain the file name without
+    a path. The path should be listed in the Makefile, using -I as
+    processor directive to search the indicated paths. An exception
+    to this would be for some proprietary software that utilizes a
+    partial path to distinguish their header files from system or
+    other header files.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+#include &lt;iostream.h&gt;     /* This is not a local include */
+#include "config.h"       /* This IS a local include */
+
+</pre>
+
+    <p><b>Exception:</b></p>
+
+    <p>/* This is not a local include, but requires a path element.
+    */ #include &lt;sys/fileName.h&gt;</p>
+
+    <p><b>Note:</b> Please! do not add "-I." to the Makefile
+    without a _very_ good reason. This duplicates the #include
+    "file.h" behaviour.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s32"></a>Provide multiple inclusion
+    protection</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Prevents compiler and linker errors resulting from
+    redefinition of items.</p>
+
+    <p>Wrap each header file with the following syntax to prevent
+    multiple inclusions of the file. Of course, replace PROJECT_H
+    with your file name, with "." Changed to "_", and make it
+    uppercase.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+#ifndef PROJECT_H_INCLUDED
+#define PROJECT_H_INCLUDED
+ ...
+#endif /* ndef PROJECT_H_INCLUDED */
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s33"></a>Use `extern "C"` when appropriate</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>If our headers are included from C++, they must declare our
+    functions as `extern "C"`. This has no cost in C, but increases
+    the potential re-usability of our code.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* def __cplusplus */
+
+... function definitions here ...
+
+#ifdef __cplusplus
+}
+#endif /* def __cplusplus */
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s34"></a>Where Possible, Use Forward Struct
+    Declaration Instead of Includes</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Useful in headers that include pointers to other struct's.
+    Modifications to excess header files may cause needless
+    compiles.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+/*********************************************************************
+ * We're avoiding an include statement here!
+ *********************************************************************/
+struct file_list;
+extern file_list *xyz;
+
+</pre>
+
+    <p><b>Note:</b> If you declare "file_list xyz;" (without the
+    pointer), then including the proper header file is necessary.
+    If you only want to prototype a pointer, however, the header
+    file is unneccessary.</p>
+
+    <p><b>Status:</b> Use with discrection.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s35"></a>General Coding Practices</h1>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s36"></a>Turn on warnings</h2>
+
+    <p><b>Explanation</b></p>
+
+    <p>Compiler warnings are meant to help you find bugs. You
+    should turn on as many as possible. With GCC, the switch is
+    "-Wall". Try and fix as many warnings as possible.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s37"></a>Provide a default case for all switch
+    statements</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>What you think is guaranteed is never really guaranteed. The
+    value that you don't think you need to check is the one that
+    someday will be passed. So, to protect yourself from the
+    unknown, always have a default step in a switch statement.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+switch( hash_string( cmd ) )
+{
+   case hash_actions_file :
+      ... code ...
+      break;
+
+   case hash_confdir :
+      ... code ...
+      break;
+
+   default :
+      log_error( ... );
+      ... anomly code goes here ...
+      continue; / break; / exit( 1 ); / etc ...
+
+} /* end switch( hash_string( cmd ) ) */
+
+</pre>
+
+    <p><b>Note:</b> If you already have a default condition, you
+    are obviously exempt from this point. Of note, most of the
+    WIN32 code calls `DefWindowProc' after the switch statement.
+    This API call *should* be included in a default statement.</p>
+
+    <p><b>Another Note:</b> This is not so much a readability issue
+    as a robust programming issue. The "anomly code goes here" may
+    be no more than a print to the STDERR stream (as in
+    load_config). Or it may really be an ABEND condition.</p>
+
+    <p><b>Status:</b> Programmer discretion is advised.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s38"></a>Try to avoid falling through cases in a
+    switch statement.</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>In general, you will want to have a 'break' statement within
+    each 'case' of a switch statement. This allows for the code to
+    be more readable and understandable, and furthermore can
+    prevent unwanted surprises if someone else later gets creative
+    and moves the code around.</p>
+
+    <p>The language allows you to plan the fall through from one
+    case statement to another simply by omitting the break
+    statement within the case statement. This feature does have
+    benefits, but should only be used in rare cases. In general,
+    use a break statement for each case statement.</p>
+
+    <p>If you choose to allow fall through, you should comment both
+    the fact of the fall through and reason why you felt it was
+    necessary.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s39"></a>Use 'long' or 'short' Instead of
+    'int'</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>On 32-bit platforms, int usually has the range of long. On
+    16-bit platforms, int has the range of short.</p>
+
+    <p><b>Status:</b> open-to-debate. In the case of most FSF
+    projects (including X/GNU-Emacs), there are typedefs to int4,
+    int8, int16, (or equivalence ... I forget the exact typedefs
+    now). Should we add these to IJB now that we have a "configure"
+    script?</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s40"></a>Don't mix size_t and other types</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>The type of size_t varies across platforms. Do not make
+    assumptions about whether it is signed or unsigned, or about
+    how long it is. Do not compare a size_t against another
+    variable of a different type (or even against a constant)
+    without casting one of the values. Try to avoid using size_t if
+    you can.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s41"></a>Declare each variable and struct on its
+    own line.</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>It can be tempting to declare a series of variables all on
+    one line. Don't.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+long a = 0;
+long b = 0;
+long c = 0;
+
+</pre>
+
+    <p><b>Instead of:</b></p>
+
+    <p>long a, b, c;</p>
+
+    <p><b>Explanation:</b> - there is more room for comments on the
+    individual variables - easier to add new variables without
+    messing up the original ones - when searching on a variable to
+    find its type, there is less clutter to "visually"
+    eliminate</p>
+
+    <p><b>Exceptions:</b> when you want to declare a bunch of loop
+    variables or other trivial variables; feel free to declare them
+    on 1 line. You should, although, provide a good comment on
+    their functions.</p>
+
+    <p><b>Status:</b> developer-discrection.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s42"></a>Use malloc/zalloc sparingly</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>Create a local stuct (on the stack) if the variable will
+    live and die within the context of one function call.</p>
+
+    <p>Only "malloc" a struct (on the heap) if the variable's life
+    will extend beyond the context of one function call.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+If a function creates a struct and stores a pointer to it in a
+list, then it should definately be allocated via `malloc'.
+
+
+</pre>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s43"></a>The Programmer Who Uses 'malloc' is
+    Responsible for Ensuring 'free'</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>If you have to "malloc" an instance, you are responsible for
+    insuring that the instance is `free'd, even if the deallocation
+    event falls within some other programmer's code. You are also
+    responsible for ensuring that deletion is timely (i.e. not too
+    soon, not too late). This is known as "low-coupling" and is a
+    "good thing (tm)". You may need to offer a
+    free/unload/destuctor type function to accomodate this.</p>
+
+    <p><b>Example:</b></p>
+<pre>
+int load_re_filterfile( struct client_state *csp ) { ... }
+static void unload_re_filterfile( void *f ) { ... }
+
+</pre>
+
+    <p><b>Exceptions:</b></p>
+
+    <p>The developer cannot be expected to provide `free'ing
+    functions for C run-time library functions ... such as
+    `strdup'.</p>
+
+    <p><b>Status:</b> developer-discrection. The "main" use of this
+    standard is for allocating and freeing data structures (complex
+    or nested).</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s44"></a>Add loaders to the `file_list' structure
+    and in order</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>I have ordered all of the "blocker" file code to be in alpha
+    order. It is easier to add/read new blockers when you expect a
+    certain order.</p>
+
+    <p><b>Note:</b> It may appear that the alpha order is broken in
+    places by POPUP tests coming before PCRS tests. But since
+    POPUPs can also be referred to as KILLPOPUPs, it is clear that
+    it should come first.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h2><a name="s45"></a>"Uncertain" new code and/or changes to
+    exitinst code, use FIXME</h2>
+
+    <p><b>Explanation:</b></p>
+
+    <p>If you have enough confidence in new code or confidence in
+    your changes, but are not *quite* sure of the reprocussions,
+    add this:</p>
+
+    <p>/* FIXME: this code has a logic error on platform XYZ, *
+    attempthing to fix */ #ifdef PLATFORM ...changed code here...
+    #endif</p>
+
+    <p>or:</p>
+
+    <p>/* FIXME: I think the original author really meant this...
+    */ ...changed code here...</p>
+
+    <p>or:</p>
+
+    <p>/* FIXME: new code that *may* break something else... */
+    ...new code here...</p>
+
+    <p><b>Note:</b> If you make it clear that this may or may not
+    be a "good thing (tm)", it will be easier to identify and
+    include in the project (or conversly exclude from the
+    project).</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+
+    <h1><a name="s46"></a>Addendum: Template for files and function
+    comment blocks:</h1>
+
+    <p><b>Example for file comments:</b></p>
+<pre>
+const char FILENAME_rcs[] = "$Id: STANDARDS.txt,v 1.5 2001/09/10 18:37:48 jongfoster Exp $";
+/*********************************************************************
+ *
+ * File        :  $S<!-- Break CVS Substitution -->ource$
+ *
+ * Purpose     :  (Fill me in with a good description!)
+ *
+ * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
+ *                IJBSWA team.  http://ijbswa.sourceforge.net
+ *
+ *                Based on the Internet Junkbuster originally written
+ *                by and Copyright (C) 1997 Anonymous Coders and
+ *                Junkbusters Corporation.  http://www.junkbusters.com
+ *
+ *                This program is free software; you can redistribute it
+ *                and/or modify it under the terms of the GNU General
+ *                Public License as published by the Free Software
+ *                Foundation; either version 2 of the License, or (at
+ *                your option) any later version.
+ *
+ *                This program is distributed in the hope that it will
+ *                be useful, but WITHOUT ANY WARRANTY; without even the
+ *                implied warranty of MERCHANTABILITY or FITNESS FOR A
+ *                PARTICULAR PURPOSE.  See the GNU General Public
+ *                License for more details.
+ *
+ *                The GNU General Public License should be included with
+ *                this file.  If not, you can view it at
+ *                http://www.gnu.org/copyleft/gpl.html
+ *                or write to the Free Software Foundation, Inc., 59
+ *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Revisions   :
+ *    $L<!-- Break CVS Substitution -->og$
+ *
+ *********************************************************************/
+
+
+#include "config.h"
+
+   ...necessary include files for us to do our work...
+
+const char FILENAME_h_rcs[] = FILENAME_H_VERSION;
+
+
+</pre>
+
+    <p><b>Note:</b> This declares the rcs variables that should be
+    added to the "show-proxy-args" page. If this is a brand new
+    creation by you, you are free to change the "Copyright" section
+    to represent the rights you wish to maintain.</p>
+
+    <p><b>Note:</b> The formfeed character that is present right
+    after the comment flower box is handy for (X|GNU)Emacs users to
+    skip the verbige and get to the heart of the code (via
+    `forward-page' and `backward-page'). Please include it if you
+    can.</p>
+
+    <p><b>Example for file header comments:</b></p>
+<pre>
+#ifndef _FILENAME_H
+#define _FILENAME_H
+#define FILENAME_H_VERSION "$Id: STANDARDS.txt,v 1.5 2001/09/10 18:37:48 jongfoster Exp $"
+/*********************************************************************
+ *
+ * File        :  $S<!-- Break CVS Substitution -->ource$
+ *
+ * Purpose     :  (Fill me in with a good description!)
+ *
+ * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
+ *                IJBSWA team.  http://ijbswa.sourceforge.net
+ *
+ *                Based on the Internet Junkbuster originally written
+ *                by and Copyright (C) 1997 Anonymous Coders and
+ *                Junkbusters Corporation.  http://www.junkbusters.com
+ *
+ *                This program is free software; you can redistribute it
+ *                and/or modify it under the terms of the GNU General
+ *                Public License as published by the Free Software
+ *                Foundation; either version 2 of the License, or (at
+ *                your option) any later version.
+ *
+ *                This program is distributed in the hope that it will
+ *                be useful, but WITHOUT ANY WARRANTY; without even the
+ *                implied warranty of MERCHANTABILITY or FITNESS FOR A
+ *                PARTICULAR PURPOSE.  See the GNU General Public
+ *                License for more details.
+ *
+ *                The GNU General Public License should be included with
+ *                this file.  If not, you can view it at
+ *                http://www.gnu.org/copyleft/gpl.html
+ *                or write to the Free Software Foundation, Inc., 59
+ *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Revisions   :
+ *    $L<!-- Break CVS Substitution -->og$
+ *
+ *********************************************************************/
+
+
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   ... function headers here ...
+
+
+/* Revision control strings from this header and associated .c file */
+extern const char FILENAME_rcs[];
+extern const char FILENAME_h_rcs[];
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _FILENAME_H */
+
+/*
+  Local Variables:
+  tab-width: 3
+  end:
+*/
+
+
+</pre>
+
+    <p><b>Example for function comments:</b></p>
+<pre>
+/*********************************************************************
+ *
+ * Function    :  FUNCTION_NAME
+ *
+ * Description :  (Fill me in with a good description!)
+ *
+ * Parameters  :
+ *          1  :  param1 = pointer to an important thing
+ *          2  :  x      = pointer to something else
+ *
+ * Returns     :  0 =&gt; Ok, everything else is an error.
+ *
+ *********************************************************************/
+int FUNCTION_NAME( void *param1, const char *x )
+{
+   ...
+   return( 0 );
+
+}
+
+
+</pre>
+
+    <p><b>Note:</b> If we all follow this practice, we should be
+    able to parse our code to create a "self-documenting" web
+    page.</p>
+
+    <p>&nbsp;</p>
+
+    <p>&nbsp;</p>
+  </body>
+</html>
+