Language
========

* No C/C++ header file may reference config.h.

* All C/C++ source files must include config.h before any other included file:
  #include <hre/config.h>

* All other included headers should come in alphabetical order after config.h
  to enable easy lookup and avoid duplicates. This also applies to file 
  listings in, for example, Makefile.am.

* Keep #include directives ordered like this:
    system headers
    external dependencies
    ltsmin headers

  Each block should be separated by a blank line.

* Always use #include <...>, never use #include "...".

* Ensure that all C/C++ source code compiles under "-W -Wall -Werror".

  Unused variables will cause warnings, and thus should be flagged
  explicitly at the end of a function, like this: 

    // ...
    return;
    (void)a; (void)b;

* Prefer "static const" over #define whenever possible.  Use enums for
  logically-connected groups of constants.

* Declare all functions local to a compilation unit as "static".

* Use asserts to document and enforce invariants.  Remember to
  #include <assert.h>.  Assert expressions must be free of function
  calls and side effects, e.g.: use "int max = f(); assert (i < max); i++;"
  instead of "assert (i++ < f());".

* Functions which can fail should return 0 on success, and a non-zero
  error code to indicate failure.  For functions which return pointers
  and have only a single failure mode, NULL can be returned to
  indicate failure.

* Boolean negation (!b) should not be used to test for NULL pointers
  or (non-)zero error codes.  Instead, use (ptr != NULL) or (ret != 0).

* Use size_t or ssize_t to represent counters.  They can be printf()ed
  with "%zu" or "%zd" directives.


Naming
======

* For identifiers generally follow the usual C conventions of
  lower-case letters and underscores, e.g., trc_get_edge_label.

* For identifiers which are part of a submodule, use a (short but
  mnemonic) unique prefix which distinguishes them from other
  submodules, e.g., "log_printf" (prefix "log_" for all logging
  related functions and structs).

* Ensure that exported identifiers do not clash with system or
  third-party code, e.g., by making them suitably long or using
  prefixes.

* For global variables use identifiers consisting of three or more
  letters, with the first letter capitalized.  For global constants,
  use identifiers in all upper-case.  For macros, use all upper-case,
  except if they replace a function (in which case they should follow
  function naming conventions).

* Avoid unnecessary and ambiguous abbreviations of identifiers (like
  "ex_program" for "exit_program"; a shorter identifier would be
  "die").  However, idiomatic abbreviations are allowed (e.g., "buf"
  for "buffer", "xlate" for "translate", etc.).

* For typedefs use names ending with "_t", e.g.,
  "typedef struct foo foo_t;"


Source Organization
===================

* External subsystems (e.g., libraries, parser generators) should be kept in
  separate sub-directories below the top-level directory.

* Subsystems should be kept in separate sub-directories below src/.


Style
=====

* No Tab (ASCII 9) maybe be introduced in any source file.  It is
  advisable to configure the editor to ensure this.

* Indentation is 4 spaces per level.

* Avoid more than 80 characters per line.

* Avoid long functions (> 100 lines of code) and deep nesting.
  Instead, break up code into smaller logical units; use meaningful
  names.

* Avoid writing functions with long parameter lists.  Avoid passing
  more than two logically-connected parameters separately.  Instead
  consider boxing them into a struct.

* Code layout for new files (or substantial changes to existing code)
  follows GNU Indent with the following options:

======================== ~/.indent.pro =========================
-orig -nut -i4 -bs -br -ce -cdw -ncdb -pcs -ncs -cd40 -c40 -di20
================================================================

  In particular, opening braces should be placed on the same line,
  with the exception of function definitions.  Note that the function
  name should be placed on the first column:

static int *
foo (int x, int y, int z)
{
    if (x < 0) {
        // statements
    } else if (x > 0) {
        // statements
    } else {
        // statements
    }

    switch (y) {
    case 0:
        // statements
    default:
        // statements
    }

    return NULL;
}

* To improve code readability, use whitespace between tokens.
