 1 Overview

  This document describes the coding style and practices that will
  be followed by this project.  The goal of these guidelines is to
  produce consistent, maintainable code.  However, since style is
  a personal thing, feel free develop in a style and environment
  that best suits your needs.  However, before any code is accepted
  by the project, it must comply with the following guidelines.
  Over time, we hope to build/assemble tools and processes that
  automatically check code and/or convert it to the required format
  and style.  Until then, the best rule of thumb is to follow the
  lead of the code that already exists.

1.1 Revision

  $Id: README.STYLE,v 1.23 2012/02/13 21:51:06 mavrik Exp $

1.2 Table of Contents

  Section 1 .................... Overview
  Section 1.1 .................. Revision
  Section 1.2 .................. Table of Contents
  Section 1.3 .................. General
  Section 1.3.1 ................ Caveats
  Section 1.4 .................. Margins
  Section 1.4.1 ................ Margins for Code
  Section 1.4.2 ................ Margins for Comments
  Section 1.5 .................. Indentation
  Section 1.6 .................. Headers
  Section 1.6.1 ................ Header for C
  Section 1.6.2 ................ Header for Perl
  Section 1.6.3 ................ Header for Shell
  Section 1.7 .................. Comments
  Section 1.7.1 ................ Comments for C
  Section 1.7.2 ................ Comments for Perl
  Section 1.7.3 ................ Comments for Shell
  Section 1.7.4 ................ Comments for CVS
  Section 1.8 .................. Braces
  Section 1.9 .................. Variables
  Section 1.9.1 ................ Variable Names
  Section 1.9.1.1 .............. Variable Names for C
  Section 1.9.1.2 .............. Variable Names for Perl
  Section 1.9.1.3 .............. Variable Names for Shell
  Section 1.10 ................. Functions
  Section 1.10.1 ............... Function Declarations
  Section 1.10.1.1 ............. Function Declarations for C
  Section 1.10.1.2 ............. Function Declarations for Perl
  Section 1.10.2 ............... Function Prototypes
  Section 1.10.2.1 ............. Function Prototypes for C
  Section 1.10.2.2 ............. Function Prototypes for Perl
  Section 1.11 ................. Whitespace
  Section 1.11.1 ............... Trailing Spaces
  Section 1.11.2 ............... Tabs
  Section 1.11.3 ............... Calls and Conditionals
  Section 1.11.4 ............... Parentheses and Arguments
  Section 1.12 ................. Usage
  Section 1.12.1 ............... Usage Exit Code
  Section 1.12.2 ............... Usage Statements
  Section 1.13 ................. Punctuation
  Section 1.13.1 ............... Punctuation for Perl
  Section 1.13.1.1 ............. Semi-colons
  Section 1.13.1.2 ............. Commas
  Section 1.13.2 ............... Punctuation for Shell
  Section 1.13.2.1 ............. Semi-colons
  Section 1.13.2.2 ............. Backslashes
  Section 1.14 ................. Quotes
  Section 1.14.1 ............... Quotes for Perl
  Section 1.14.1.1 ............. Variable Assignments
  Section 1.14.1.2 ............. Hash Keys
  Section 1.14.2 ............... Quotes for Shell
  Section 1.14.2.1 ............. Variable Assignments
  Section 1.15 ................. Constants, Enumerations, Macros, Structures, and Unions
  Section 1.15.1 ............... Constant Declarations
  Section 1.15.1.1 ............. Constant Declarations for C
  Section 1.15.2 ............... Enumeration Declarations
  Section 1.15.2.1 ............. Enumeration Declarations for C
  Section 1.15.3 ............... Macro Declarations
  Section 1.15.3.1 ............. Macro Declarations for C
  Section 1.15.4 ............... Structure and Union Declarations
  Section 1.15.4.1 ............. Structure and Union Declarations for C
  Section 1.16 ................. Documentation
  Section 1.16.1 ............... Man Pages

1.3 General

  As a general rule, before any changes are checked in, they must
  conform to the style guidelines and code must compile cleanly and
  run on all supported platforms.

1.3.1 Caveats

  This document is a work in progress.  It's not perfect; it's not
  complete; but it's better than nothing.

1.4 Margins

1.4.1 Margins for Code

  A hard margin is not imposed for code.  Whenever possible, code
  should be written such that there is one statement per line.

  As a general rule, if you can print the code out in landscape
  mode without the lines wrapping, you're probably fine.  Also, if
  you can resize your xterm such that the entire line can be viewed
  on a single screen without wrapping, you're probably fine.

  In situations where this is not practical or readable, let the
  following examples guide you.  The idea is to stack items (e.g.,
  arguments or logic tests) vertically.

  In the example shown here, putting the entire statement on one
  line is too much -- even on a fairly wide xterm.

  snprintf(acData, iLength, "Some format with a lot of arguments %s, %s, %s, %s, %s, %s\n", psProperties->acSomeVariable1, psProperties->acSomeVariable2, psProperties->acSomeVariable3, psProperties->acSomeVariable4, psProperties->acSomeVariable5, psProperties->acSomeVariable6);

  Thus, it should be reformatted as follows:

  snprintf(acData, iLength, "Some format with a lot of arguments %s, %s, %s, %s, %s, %s\n",
    psProperties->acSomeVariable1,
    psProperties->acSomeVariable2,
    psProperties->acSomeVariable3,
    psProperties->acSomeVariable4,
    psProperties->acSomeVariable5,
    psProperties->acSomeVariable6
    );

  It should not, however, be reformatted like this:

    snprintf(acData, iLength, "Some format with a lot of arguments %s, %s, %s, %s, %s, %s\n",
      psProperties->acSomeVariable1, psProperties->acSomeVariable2, psProperties->acSomeVariable3,
      psProperties->acSomeVariable4, psProperties->acSomeVariable5, psProperties->acSomeVariable6);

  Here's an example of a large if statement:

  if ((conditionA && conditionB && conditionC && conditionD) || (conditionE && conditionF && conditionG && conditionH) || (conditionI && conditionJ && conditionK && conditionL) || (conditionM && conditionN && conditionO && conditionP))

  This should be reformatted as follows:

  if
  (
    (conditionA && conditionB && conditionC && conditionD) ||
    (conditionE && conditionF && conditionG && conditionH) ||
    (conditionI && conditionJ && conditionK && conditionL) ||
    (conditionM && conditionN && conditionO && conditionP)
  )

  or

  if
  (
       (conditionA && conditionB && conditionC && conditionD)
    || (conditionE && conditionF && conditionG && conditionH)
    || (conditionI && conditionJ && conditionK && conditionL)
    || (conditionM && conditionN && conditionO && conditionP)
  )

  Note: The first form is being phased out since the second form is
  easier maintain and less likely to introduce logic errors.  For
  example, suppose the maintainer wants to add append a new set of
  condtitions based on {M, N, O, P} called {Q, R, S, T}.  The natural
  tendency for the programmer would be to copy and paste the line
  containing {M, N, O, P} resulting in the following intermediate
  code:

  if
  (
    (conditionA && conditionB && conditionC && conditionD) ||
    (conditionE && conditionF && conditionG && conditionH) ||
    (conditionI && conditionJ && conditionK && conditionL) ||
    (conditionM && conditionN && conditionO && conditionP)
    (conditionM && conditionN && conditionO && conditionP)
  )

  or

  if
  (
       (conditionA && conditionB && conditionC && conditionD)
    || (conditionE && conditionF && conditionG && conditionH)
    || (conditionI && conditionJ && conditionK && conditionL)
    || (conditionM && conditionN && conditionO && conditionP)
    || (conditionM && conditionN && conditionO && conditionP)
  )

  Next, the programmer would edit the new line to set the desired
  condtitions {Q, R, S, T} resulting in the following code:

  if
  (
    (conditionA && conditionB && conditionC && conditionD) ||
    (conditionE && conditionF && conditionG && conditionH) ||
    (conditionI && conditionJ && conditionK && conditionL) ||
    (conditionM && conditionN && conditionO && conditionP)
    (conditionQ && conditionR && conditionS && conditionT)
  )

  or

  if
  (
       (conditionA && conditionB && conditionC && conditionD)
    || (conditionE && conditionF && conditionG && conditionH)
    || (conditionI && conditionJ && conditionK && conditionL)
    || (conditionM && conditionN && conditionO && conditionP)
    || (conditionQ && conditionR && conditionS && conditionT)
  )

  At this point, the first code block requires one final edit (i.e.,
  to add the missing '||'), but second code block is complete.

1.4.2 Margins for Comments

  The soft and hard margins for comments are 68 and 70, respectively.
  Here's an example:

1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
  ####################################################################
  #
  # If you are inserting a descriptive comment, try to ensure that it
  # does not exceed the soft margin like the previous line just did.
  #
  ####################################################################

  If that happens, try running the comment lines through the fmt(1)
  command.  Here's the previous comment after it has been processed
  by fmt:

1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
  ####################################################################
  #
  # If you are inserting a descriptive comment, try to ensure that
  # it does not exceed the soft margin like the previous line just
  # did.
  #
  ####################################################################

1.5 Indentation

  Use 2 spaces for each additional indentation level.  Tabs are not
  allowed.  If your editor automatically inserts tabs, you'll need
  to figure out how to disable that behavior, or you'll need a way
  to convert tabs into the correct number of spaces.

1.6 Headers

  All text files (i.e., scripts, C code, Makefiles, etc.) should
  display a standard header that includes a CVS Id and a copyright.

1.6.1 Header for C

------------------------------------------------------------------------
123456789012345678901234567890123456789012345678901234567890123456789012
         1         2         3         4         5         6         7
/*-
 ***********************************************************************
 *
 * $Id: README.STYLE,v 1.23 2012/02/13 21:51:06 mavrik Exp $
 *
 ***********************************************************************
 *
 * Copyright <YYYY> - <YYYY> The <Name> Project, All Rights Reserved.
 *
 ***********************************************************************
 */
#include "all-includes.h"

/*-
 ***********************************************************************
 *
 * Main
 *
 ***********************************************************************
 */
int
main(int iArgumentCount, char *ppcArgumentVector[])
{
  <code>
}
------------------------------------------------------------------------

1.6.2 Header for Perl

----------------------------------------------------------------------
1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
#!/usr/bin/perl -w
######################################################################
#
# $Id: README.STYLE,v 1.23 2012/02/13 21:51:06 mavrik Exp $
#
######################################################################
#
# Copyright <YYYY> - <YYYY> The <Name> Project, All Rights Reserved.
#
######################################################################
#
# Purpose: <Description>
#
######################################################################

use strict;
use File::Basename;

######################################################################
#
# Main
#
######################################################################

######################################################################
#
# Main Routine
#
######################################################################

  ####################################################################
  #
  # Punch in and go to work.
  #
  ####################################################################

  my ($sProgram);

  $sProgram = basename(__FILE__);

  ####################################################################
  #
  # Get Options.
  #
  ####################################################################

  my (%hOptions);

  if (!getopts('<your_list>', \%hOptions))
  {
    Usage($sProgram);
  }

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

1.6.3 Header for Shell

  For shell scripts, three variables should always be set: PROGRAM,
  PATH, and IFS.  The standard IFS variable should contain the
  following characters: space, tab, and newline.  Note that cutting
  and pasting this header may corrupt the IFS variable, so be sure
  to check it each time you create a new script.

----------------------------------------------------------------------
1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
#!/bin/sh
######################################################################
#
# $Id: README.STYLE,v 1.23 2012/02/13 21:51:06 mavrik Exp $
#
######################################################################
#
# Copyright <YYYY> - <YYYY> The <Name> Project, All Rights Reserved.
#
######################################################################
#
# Purpose: <Description>
#
######################################################################

IFS=' 	
'

PATH="/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin"

PROGRAM=`basename $0`

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

1.7 Comments

  Major comment blocks and CVS commit messages should be formatted
  with fmt(1).  This can be done in vi as follows:

  From edit mode (cursor on first line of the paragraph):

    !}fmt

  From command mode macro (cursor on first line of the paragraph):

    map #1 :.,/^$/!fmt^[}

  or (with command line options)

    map #1 :.,/^$/!fmt -l 0 -w 70^[}

  Note: The ^[ in this macro is created by typing CTRL-v followed
  by ESC.

  Note: The expression /^$/ matches empty lines.  Therefore, it is
  important to periodically remove trailing spaces that crop up
  from time to time -- usually they are the product of a cut and
  paste operation (see section 1.11).

1.7.1 Comments for C

  Minor, inline comments in the code body should be appended to the
  end of the line as follows:

    iIndex = 1; /* This is an inline comment. */

  Major comments in the code body should be formated as follows:

123456789012345678901234567890123456789012345678901234567890123456789012
         1         2         3         4         5         6         7
/*-
 ***********************************************************************
 *
 * This is a level one comment.
 *
 ***********************************************************************
 */

123456789012345678901234567890123456789012345678901234567890123456789012
         1         2         3         4         5         6         7
  /*-
   *********************************************************************
   *
   * This is a level two comment.
   *
   *********************************************************************
   */

123456789012345678901234567890123456789012345678901234567890123456789012
         1         2         3         4         5         6         7
    /*-
     *******************************************************************
     *
     * This is a level three comment.
     *
     *******************************************************************
     */

1.7.2 Comments for Perl

  Minor, inline comments in the code body should be appended to the
  end of the line as follows:

    $sIndex = 1; # This is an inline comment.

  Major comments in the code body should be formated as follows:

1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
######################################################################
#
# This is a level one comment.
#
######################################################################

1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
  ####################################################################
  #
  # This is a level two comment.
  #
  ####################################################################

1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
    ##################################################################
    #
    # This is a level three comment.
    #
    ##################################################################

1.7.3 Comments for Shell

  Minor, inline comments in the code body should be appended to the
  end of the line as follows:

    INDEX="1" # This is an inline comment.

  Major comments follow the same conventions as for Perl.

1.7.4 Comments for CVS

  Comments for CVS logs should always be formatted with fmt(1).  They
  also need to have any trailing spaces removed (see Trailing Spaces
  section).

  Generally, CVS commit messages should be written in the past tense
  (you are describing what you did) and in the first person with the
  subject implied.  For example, the message:

    I updated section 1.7.4 of the documentation.

  would be written as

    Updated section 1.7.4 of the documentation.

  Strive to express complete thoughts/sentences, and explain why you
  made the change -- people can see what you changed by doing a diff,
  but they won't know why you made the change unless you tell them.

  Always check punctuation, grammar, and spelling before committing.
  Use only a single space between sentences rather than two, which is
  typical for other forms of documentation.

  Avoid IRC speak, incomplete thoughts, and things like talking to the
  software.  Bear in mind that these messages are part of the
  project's official record, so it's worth the effort in to make them
  look professional.

  If your commit messages are consistently covering multiple,
  unrelated changes, you're probably attempting to commit too many
  things at one time.  A good rule of thumb is to make one commit per
  change -- even if the change is small.  The exception to this is
  multiple changes that are related.

1.8 Braces { }

  Always use braces, and always format them as follows:

  if (test == 1)
  {
    logic;
  }

  The following are examples of forms that that are not accepted.

  if (test == 1) {
    logic;
  }

  if (test == 1)
    logic;

1.9 Variables

1.9.1 Variable Names

  Variable names should be descriptive and be expressed in the form
  of an object (e.g., iCount, pcFilename).

  Variables should be initialized as they are declared.  One exception
  to this is the case where variable initialization would negatively
  impact performance.

  For example, using '{ 0 }' to initialize an array can have a
  significant impact on performance.  According to the 2nd edition of
  "The C Programming  Language" by Kernighan and Ritchie, an array
  initialized in this way will be zero filled when the number of
  initializers is less than the size of the array (section 4.9, page
  86).  In cases where the size of the array is large, the routine is
  called frequently, or a combination of both, this will likely be a
  performance drain.

  The use of global variables should be minimized, and unless there
  is a good reason, they should not be used at all.  That being
  said, the naming convention for globals is the same as for locals
  with one difference: all globals are to be prefixed with the
  letter 'g'.  For example:

    char *gpcFilename;

  In general, variables should be declared in alphabetical order.  The
  exception to this would be a case where variables need to be clumped
  together for a good reason.

1.9.1.1 Variable Names for C

  Specify the variable type in small letters.  Then, capitalize the
  first letter of each successive word (e.g., iTimeLimit).  If the
  variable name contains an acronym (e.g., SSL or URL), only the first
  letter of the acronym may be capitalized (e.g., Ssl or Url).

  Simple ints such as i, j, k, n, x, and y do not require the type
  specifier (i.e., iI, iJ, etc.) as that would make them overly
  cumbersome.  However their use is not encouraged either.  Simple
  chars can be declared as c, ac, or pc.

  Here are some example declarations:

  FILE          *pFile;
  char           acBuffer[SIZE];
  char          *pc;
  int            iTimeCounter;
  long           lContentLength;
  unsigned long  ulAddress;
  unsigned long long ullFileSize;

1.9.1.2 Variable Names for Perl

  Unless there is a good reason, all variables should be declared
  using my.  The first letter of the variable should be a lower
  case letter (a, h, o, s) that indicates the type (i.e., array,
  hash, object, or scalar).  Then, capitalize the first letter of
  each successive word.  If the variable name contains an acronym
  (e.g., SSL or URL), only the first letter of the acronym may be
  capitalized (e.g., Ssl or Url).

  Here are some example declarations:

  my @aName; # Array
  my %hName; # Hash
  my $oName; # Object
  my $sName; # Scalar

  All reference (i.e., pointer) variable names should be prefixed
  with the letter 'p'.  Continuing with the examples from above:

  my $paName = \@aName; # Array Reference
  my $phName = \%hName; # Hash Reference
  my $poName = \$oName; # Object Reference
  my $psName = \$sName; # Scalar Reference

1.9.1.3 Variable Names for Shell

  Unless there is a good reason, all variables should be treated as if
  they were declared using Perl's my operator.  Even though shell
  variables are global in scope, they should be handled and named as
  though their scope is limited to the enclosing routine, and the
  developer should assume that variables declared in the main body of
  the script are not visible inside any particular subroutine.  To
  underscore and reinforce this approach, variable names should be
  prefixed with "MY_" or "my_", and any external variables used by a
  given routine should be passed in as parameters.

  Braces should always be used to dereference shell variables.  In
  other words, always use

    ${MY_VARIABLE}

  instead of

    $MY_VARIABLE

  This convention makes the code easier to maintain, and it eliminates
  some potential pitfalls.  Consider the following example:

    MY_FILE="foo"
    mv $MY_FILE $MY_FILE2

  In the example above, it is not clear if the intent was to rename a
  file called "foo" to "foo2" or to the value held by the MY_FILE2
  variable.  The use of braces in this example would be as follows:

    MY_FILE="foo"
    mv ${MY_FILE} ${MY_FILE}2

  Note that braces also protect against the following potential
  pitfall.

    SomeRoutine()
    {
      MY_ARG_1=$1     # Note: Use ${1} instead.
      MY_ARG_2=$2     # Note: Use ${2} instead.
      MY_ARG_3=$3     # Note: Use ${3} instead.
      MY_ARG_4=$4     # Note: Use ${4} instead.
      MY_ARG_5=$5     # Note: Use ${5} instead.
      MY_ARG_6=$6     # Note: Use ${6} instead.
      MY_ARG_7=$7     # Note: Use ${7} instead.
      MY_ARG_8=$8     # Note: Use ${8} instead.
      MY_ARG_9=$9     # Note: Use ${9} instead.
      MY_ARG_10=$10   # Note: Use ${10} instead.
      echo ${MY_ARG_1} ${MY_ARG_2} ${MY_ARG_3} ${MY_ARG_4} ${MY_ARG_5} ${MY_ARG_6} ${MY_ARG_7} ${MY_ARG_8} ${MY_ARG_9} ${MY_ARG_10}
    }

  In the example above, the value of MY_ARG_10 will actually be:

    ${MY_ARG_1}0

  Thus if SomeRoutine() was invoked as follows:

    SomeRoutine a b c d e f g h i j

  The output would be:

    a b c d e f g h i a0

  which is probably not the result the caller would have expected.

1.10 Functions

  Function and subroutine names should be descriptive and be expressed
  in the form of an action (e.g., GetHostname, ConvertToHex).

  Capitalize the first letter of each word (e.g., ExampleRoutine).
  If one of the words in the name is an acronym (e.g., SSL), then
  capitalize the first letter of that word and force the remaining
  letters to lower case (e.g., ExampleSslRoutine).

  Additionally, these names should not be prone to name collisions.
  To help prevent that from happening, prefix each routine with the
  <name> of the project or a logical grouping to which it belongs.
  For example, suppose you had a routine for the WebJob project
  that you wanted to call GetProperties.  Under this naming convention,
  that routine should be called WebJobGetProperties.

  Function and subroutine names should always be called with the
  parentheses snuggled up to the name as follows:

    ExampleRoutine()

  but not like this

    ExampleRoutine ()

1.10.1 Function Declarations

  All functions and subroutines should have 2 blank lines above
  them.

1.10.1.1 Function Declarations for C

123456789012345678901234567890123456789012345678901234567890123456789012
         1         2         3         4         5         6         7
/*-
 ***********************************************************************
 *
 * ExampleRoutine1
 *
 ***********************************************************************
 */
void
ExampleRoutine1(char *pcName, char *pcError)
{
  <code>
}


/*-
 ***********************************************************************
 *
 * ExampleRoutine2
 *
 ***********************************************************************
 */
int
ExampleRoutine2(int iIndex, char *pcError)
{
  <code>
}


/*-
 ***********************************************************************
 *
 * ExampleRoutine3
 *
 ***********************************************************************
 */
char *
ExampleRoutine3(PROPERTIES *pcProperties, char *pcError)
{
  <code>
}

1.10.1.2 Function Declarations for Perl

  In general, don't pass anything but scalars to subroutines.  If
  you need to pass an array, hash, or object into a subroutine,
  pass it as a reference (i.e., \@, \%, or \$).

  Call subroutines like this:

    ExampleRoutine();

  but not like this:

    &ExampleRoutine;

1234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
######################################################################
#
# ExampleRoutine1
#
######################################################################

sub ExampleRoutine1
{
  my ($sScalar1, $paArray1, $phHash1, $poObject1) = @_;

  <code>
}

1.10.2 Function Prototypes

1.10.2.1 Function Prototypes for C

  C function prototypes should be specified in a local include file
  with the entire prototype being specified on a single line.

    void ExampleRoutine1(char *pcName, char *pcError);

1.10.2.2 Function Prototypes for Perl

  Perl function prototypes are not generally used by this project.

1.11 Whitespace

1.11.1 Trailing Spaces

  Before checking in any text-based files, make sure that there are
  no unwanted trailing spaces.  A quick way to do this in vi is as
  follows:

    :%s/  *$//gc;

  Here's a macro to do the same:

    map #3 :%s/  *$//gc^[

  Note: The ^[ in this macro is created by typing CTRL-v followed
  by ESC.

  Note: Trailing spaces should also be removed from CVS comments
  prior to the final commit.

1.11.2 Tabs

  No tabs are allowed.  The exceptions are the IFS variable in shell
  scripts and any tabs used by the program or script being coded.

1.11.3 Calls and Conditionals

  There should be no space between a function or subroutine call
  and its opening parenthesis.

    ExampleRoutine()

  There should be one space between a conditional and its opening
  parenthesis.

    if ()

    while ()

    switch ()

  Here are examples of forms that are not allowed:

    ExampleRoutine ()

    if()

1.11.4 Parentheses and Arguments

  There should be no space inside of parentheses except between
  arguments.  A single space should be used to separate arguments.

  Here are examples of the required form:

    if (iCount <= 3 || iCount >= 9)

    ExampleRoutine(pcName1, pcName2, pcName3);

  Here are examples of forms that are not allowed:

    if ( iCount <= 3 || iCount >= 9 )

    if (iCount<=3||iCount>=9)

    ExampleRoutine( pcName1, pcName2, pcName3 );

    ExampleRoutine(pcName1,pcName2,pcName3);

1.12 Usage

  All utilities in this project should output a usage statement and
  exit if they are executed with no arguments.  Naturally, there will
  be some exceptions to this rule, but they should be considered
  carefully and handled on a case-by-case basis.

1.12.1 Usage Exit Code

  All utilities in this project that exit due to a usage condition
  should return an exit code of 1.

1.12.2 Usage Statements

  Usage statements should adhere to the following general format:

    <utility> [optional-arguments] <required-arguments>

  where 'utility' is the given or basename of the executable.  The
  arguments for both 'optional-arguments' and 'required-arguments'
  should be grouped and listed in alphabetical order.  In other words,
  do not intermingle 'optional-arguments' with 'required-arguments'.

  Always gang optional options that act as flags (i.e., they have no
  argument) together at the beginning of the 'optional-arguments'
  grouping.

  All options within a particular grouping should be listed in
  alphabetical order from left to right.  If two options differ by
  case, order them lexically (i.e., upper case comes before lower
  case).  For example, use 'AaBbCc' rather than 'ABCabc'.

  Here is an example of the required form:

    tool [-Fq] [-H home-dir] -f {file|-} -t type

  Here is an example of that is not allowed:

    tool [-F] -f {file|-} [-H home-dir] [-q] -t type

1.13 Punctuation

  All code and written documentation should use proper punctuation.

1.13.1 Punctuation for Perl

  The following one-liner can be used to help identify statements in
  Perl scripts that may be missing trailing a ';' or ','.

    egrep -n '^[^#]*[^;#,]$' `find . -type f -print0 | xargs -0 file | egrep 'perl ' | sed 's/:.*//'` /dev/null | egrep -v '^[^:]+:[0-9]+:[ 	]*[][{}()]$'

  Note: The '[   ]' above contains a space and a tab.  Be careful when
  using this; you will likely have to enter ^V<tab> manually.

  Note: The above does not remove =pod/=cut text, so you will have to
  pass over those lines manually.

1.13.1.1 Semi-colons

  Any statement that can be terminated with a semi-colon should place
  the ';' such that it is snuggled up to the end of the code.

  Here are examples of the required form:

    my $sTemp = 0;

    if ($sTemp > 1)
    {
      print STDOUT "True\n";
    }

  Here are examples of forms that are not allowed:

    my $sTemp = 0 ;

    if ($sTemp > 1)
    {
      print STDOUT "True\n"
    }

1.13.1.2 Commas

  Any statement that uses a comma as a delimiter should place the ','
  such that it is snuggled up to the end of each list item.  The comma
  should then be followed by a single space or newline.

  To make code maintenance easier, arrays and hashes must append a
  comma to the last item in a list when that list is initialized
  vertically.

  Here are examples of the required form:

    my ($sScalar1, $paArray1, $phHash1, $poObject1) = @_;

    my @a =
    (
      "abc",
      "def",
      "ghi", <-- This comma is required unless there is a good reason why it can't be here.
    );

    foreach my $sItem (@aList, "jkl")
    {
      my @a = split(//, $sItem);
    }

  Here are examples of forms that are not allowed:

    my ($sScalar1,$paArray1,$phHash1,$poObject1) = @_;

    my @a =
    (
      "abc" ,
      "def" ,
      "ghi" ,
    );

    foreach my $sItem (@aList,"jkl")
    {
      my @a = split(//,$sItem);
    }

  Appending a comma to the last item in a list means that the list can
  be sorted with impunity.  Consider the following scenario:

  Before the sort:

    my @a =
    (
      "a",
      "d",
      "c",
      "b"
    );

  After the sort:

    my @a =
    (
      "a",
      "b"  <-- This will cause an error.
      "c",
      "d",
    );

  Appending a comma to the last item in a list also makes diffs easier
  to read.  For example, adding "c" to the following list:

    my @a =
    (
      "a",
      "b",
    );

  yields diff output like this:

    + "c",

  instead of diff output like this:

    - "b"
    + "b",
    + "c"

1.13.2 Punctuation for Shell

1.13.2.1 Semi-colons

  Any statement that involves command grouping should place one space
  on either side of the ';'.  This guideline exists primarily for code
  consistency and maintainability.

  Here are examples of the required form:

    date ; echo "WHO" ; who ; echo "LAST" ; last -5

    ( date ; echo "WHO" ; who ; echo "LAST" ; last -5 )

    { date ; echo "WHO" ; who ; echo "LAST" ; last -5 ; }

    if [ ${MY_VALUE} -eq 1 ] ; then
      ...
    fi

    for MY_VALUE in ${MY_LIST} ; do
      ...
    done

    while [ $# -gt 0 ] ; do
      ...
    done

  Here are examples of forms that are not allowed:

    date;echo "WHO";who;echo "LAST";last -5

    if [ ${MY_VALUE} -eq 1 ]; then
      ...
    fi

    for MY_VALUE in ${MY_LIST}; do
      ...
    done

1.13.2.2 Backslashes

  Unless there is a good reason, multi-line statements should place
  one space in front of the '\'.  Doing this helps to prevent
  accidental argument concatenation, which can happen when there is no
  leading space on a given continuation line.

  Here are examples of the required form:

    echo "This is supposed to be a long \
    statement."

    command \
      arg1 \
      arg2 \
      arg3 \
      arg4

  Here are examples of forms that are not allowed:

    echo "This is supposed to be a long\
    statement."

    command\
      arg1\
      arg2\
      arg3\
      arg4

1.14 Quotes

  All code should use quotes in a consistent manner under certain
  conditions.

1.14.1 Quotes for Perl

1.14.1.1 Variable Assignments

  All strings should be quoted as appropriate for the language.
  Generally, single and double quotes are preferred.  However, other
  types of quotes may be used as circumstances dictate.  The goal in
  those cases would be consistency (i.e., have a reason for using
  certain types of quotes and be able to articulate why).

1.14.1.2 Hash Keys

  Unless there is a good reason, all literal hash keys should be
  quoted using single quotes.  This guideline exists primarily for
  code consistency and maintainability.

  Here are examples of the required form:

    $h{'key'} = "value";
    %h = ('key' => "value");

  Here are examples of forms that are not allowed:

    $h{key} = "value";
    %h = (key => "value");

  Hash keys represented by a single variable do not need to be quoted
  as shown here.

    $h{$sKey} = "value";
    $h{$a[0]} = "value";

1.14.2 Quotes for Shell

1.14.2.1 Variable Assignments

  All variable assignments should be quoted using single, double, or
  back quotes as appropriate.

  Here are examples of the required form:

    MY_DATE=`date +%Y-%m-%d`
    MY_HASH='$1$XpC43uSh$z/p1q5793xYpkTOUG2jam0'
    MY_NAME="foo"
    MY_NULL=""
    MY_NUMBER="0"

  Here are examples of forms that are not allowed:

    MY_NAME=foo
    MY_NULL=
    MY_NUMBER=0

  Assignments based exclusively on a single existing variable do not
  need to be quoted.  However, assignments based on multiple variables
  or a single variable intermixed with literal values should be
  quoted.

  Here are examples of the required form:

    MY_FLAG=${1}
    MY_TEMP=${MY_FLAG}
    MY_SUFFIX=".${MY_TYPE}"
    MY_NAME="${MY_PREFIX}${MY_SUFFIX}"
    MY_FILE="${MY_DIR}/${MY_NAME}"

1.15 Constants, Enumerations, Macros, Structures, and Unions

  The names used in declarations for constants, enumerations, macros,
  structures, and unions should generally be more descriptive than
  they are terse.  When in doubt, lean towards being more descriptive.

1.15.1 Constant Declarations

1.15.1.1 Constant Declarations for C

  Constants should be declared as follows:

    #define <NAME> <VALUE>

  where <NAME> has the following format:

    <PREFIX>_<STRING>[_<STRING>]*

  <PREFIX> is a string derived from the encompassing application,
  library, or file, and <STRING> is a user-defined string.

  The purpose of the prefix is to group related declarations and
  prevent name collisions.

  Here's an example where the prefix is derived from the encompassing
  file (ssl.h):

    #define SSL_MAX_CHAIN_LENGTH 10

  Here's an example where the prefix is derived from the encompassing
  application (webjob):

    #define WEBJOB_TEMP_DIRECTORY "/tmp"

  Here's an example where the prefix is derived from the encompassing
  library (libxyz):

    #define XYZ_MAX_PATH 4096

1.15.2 Enumeration Declarations

1.15.2.1 Enumeration Declarations for C

  Enumerations should be declared as follows:

    typedef enum _<NAME>
    {
      <IDENTIFIER> [= <VALUE>],
      ...
    } <NAME>;

  where <NAME> and <IDENTIFIER> have the same name format as that used
  for a constant.

  Here's an example:

    typedef enum _WEBJOB_OPTION_IDS
    {
      WEBJOB_OPTION_FILE,
      WEBJOB_OPTION_HASH_TYPE,
      WEBJOB_OPTION_NO_UPLOAD,
      WEBJOB_OPTION_GET_TIME_LIMIT,
      WEBJOB_OPTION_PUT_TIME_LIMIT,
      WEBJOB_OPTION_RUN_TIME_LIMIT,
    } WEBJOB_OPTION_IDS;

1.15.3 Macro Declarations

1.15.3.1 Macro Declarations for C

  Macro declarations follow the same conventions as those used for
  constants.

  Here's an example:

    #define WEBJOB_ASSERT(condition) assert(condition)

1.15.4 Structure and Union Declarations

1.15.4.1 Structure and Union Declarations for C

  Structures and unions should be declared as follows:

    typedef struct _<NAME>
    {
      ...
    } <NAME>;

  or

    typedef union _<NAME>
    {
      ...
    } <NAME>;

  where <NAME> has the same format as that used for a constant.

  Here's an example where the <PREFIX> is derived from the
  encompassing file (ssl.h):

    typedef struct _SSL_PROPERTIES
    {
      char    *pcPublicCertFile;
      char    *pcPrivateKeyFile;
      char    *pcPassPhrase;
      char    *pcBundledCAsFile;
      char    *pcExpectedPeerCN;
      int      iMaxChainLength;
      int      iUseCertificate;
      int      iVerifyPeerCert;
      SSL_CTX *psslCTX;
    } SSL_PROPERTIES;

  Here's an example for a self-referential structure:

    typedef struct _HOOK_LIST
    {
      char               *pcExpression;
      struct _HOOK_LIST  *psNext;
    } HOOK_LIST;

1.16 Documentation

1.16.1 Man Pages

  Man pages should be written in Perl's POD format and converted to
  manual page format using pod2man.  Each man page must include all
  required sections and should include all recommended sections listed
  below.  Note that certain sections are required or recommended
  depending on context.

    NAME (required)
      Must provide the name of the tool and a single-line description
      of the tool with the two separated by a single dash character.

    SYNOPSIS (required)
      Must provide a brief synopsis of all invocation strategies of
      the tool.

    DESCRIPTION (required)
      Must provide description of the tool, its behavior, and uses.
      Should not duplicate any information provided in other sections,
      except as necessary; this includes option and operand names and
      formats, and file usage.  If the tool processes particularly
      complex data formats, provides numerous subcommands, or is a
      language processor, an EXTENDED DESCRIPTION section (see below)
      must be provided to document these features.

    OPTIONS (conditionally required)
      Required if the tool takes options.  Each option should be
      described on its own line and it should be noted what the
      default action is for each omitted option.

    OPERANDS (conditionally required)
      Required if the tool takes operands.  Each operand should be
      described on its own line and it should be noted what the
      default action is for each omitted optional operand.

    STDIN (conditionally required)
      Required if the tool can process data on its standard input.
      This may simply be a reference to the INPUT FILES section if
      data on the standard input is processed identically to input
      taken from other files.

    INPUT FILES (conditionally required)
      Required if the tool processes files.  Files read implicitly,
      such as configuration files, need not be listed here, but must
      then be listed in DESCRIPTION above.

    ENVIRONMENT VARIABLES (conditionally required)
      Required if the tool's behavior changes based on the value of
      any environment variable.

    ASYNCHRONOUS EVENTS (conditionally required)
      Required if the tool handles any asynchronous events (POSIX
      traditional or realtime signals on POSIX platforms, and any
      platform-specific asynchronous events) with any behavior other
      than the default for that system.  If the system's default
      behavior differs from any well-known standard, such actions must
      be documented here if known.

    STDOUT (conditionally required)
      Required if the tool produces output to its standard output that
      is designed to be readily consumed by other tools or if the tool
      can be instructed to use its standard output as an output file.
      In the latter case, this section may simply be a reference to
      OUTPUT FILES below.

    STDERR (conditionally required)
      Required if the tool produces output to its standard error that
      is designed to be readily consumed by other tools or if the tool
      can be instructed to use its standard output as an output file.
      In the latter case, this section may simply be a reference to
      OUTPUT FILES below.  Note that this section is not required if
      the only output produced corresponds to regular error messages.

    OUTPUT FILES (conditionally required)
      Required if the tool produces output files.

    EXTENDED DESCRIPTION (conditionally required)
      Required as noted in the DESCRIPTION section above.

    EXIT STATUS (required)
      Must list all exit status codes in whatever format is most
      preferred for the host operating system.  Any symbolic exit
      status codes must also be provided in numeric form unless such
      form is not generally used on the host operating system.

    CONSEQUENCES OF ERRORS (conditionally required)
      Required if the tool makes any changes to input or output files
      that are not reversed in case of an error.

    APPLICATION USAGE (optional)
      May give advice as to how the tool is best used.  Cavates with
      inputs that result in extremely suboptimal performance should be
      listed here.

    EXAMPLES (recommended)
      Should provide at least one example for each invocation strategy
      as listed in the SYNOPSIS section above.

    RATIONALE (optional)
      May provide informative documentation as to the reasoning behind
      implementation choices, including why certain features were
      included or omitted, and comparisons to other tools of similar
      features.

    FUTURE DIRECTIONS (optional)
      May provide information on planned future changes to the tool.

    SEE ALSO (recommended)
      Should provide a list of other manual pages and documentation
      related to this tool.

    HISTORY (optional)
      May provide a history of changes, including when major features
      were added or removed, and should note specifically when changes
      broke compatibility with earlier versions.

    CREDITS (required)
      Must provide names and contact information for the groups or
      individuals who produced the tool, as well as each individual's
      or group's role.  If there is a separate support or maintenance
      context, it must also be listed here.

    LICENSE (required)
      Any text required by the license must be included here.  If the
      license does not require any text to be included in the
      documentation, then a reference to the license must be included
      here.

  Refer to Section 1.4 (Utility Description Defaults) of "The Shell
  and Utilities volume of POSIX.1-2008" for additional guidelines:

    http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html

