diff doc/devel/style.txt @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children 12171da8943f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/devel/style.txt	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,216 @@
+Style guidelines for AnaGram source
+-----------------------------------
+
+Purpose:
+
+   These guidelines are *guidelines*, not commandments. Legibility and
+   maintainability are more important than mindless adherence to
+   regulations.
+
+   Note: patches that reindent or reformat will be rejected. Patches
+   whose only purpose is to reindent or reformat will be rejected
+   extra-fast. If you think a section of code needs reformatting,
+   write a message saying so and explain your reasoning. Illegibility
+   and violation of the principle of least surprise are good reasons.
+   Lack of strict conformance to these guidelines is not.
+
+   Note: some source files have DOS-style end of line (CR/LF) and
+   others have Unix-style end of line (just LF) - for the most part
+   this should be transparent. So leave things the way they are in
+   this regard.
+
+Basic layout guidelines, in order of decreasing generality:
+
+   - 2-space indent.
+   - Lines do not exceed 79 columns.
+   - Don't indent preprocessor directives.
+   - In a multi-line /* */ comment, the beginning and ending tokens
+     get their own lines, and all the stars should line up.
+   - Left braces go at the end of the line.
+   - Right braces get their own line.
+   - 'else' starts a new line.
+   - Use braces with if, else, while, do/while, and for.
+   - If violating the previous rule, always put the subordinate
+     statement on the same line.
+   - Violate said rule for conciseness only when:
+	- a single if (no else) has a very short conditional and a
+	  very short subordinate statement;
+	- a while statement ditto;
+	- or a for statement has no body.
+   - Never violate said rule for a do/while statement.
+   - Put the while part of a do/while statement on the same line as
+     the closing brace, to keep them from getting separated.
+   - Switch case labels should be indented two spaces, and code
+     indented two spaces further.
+   - Each switch case label should get its own line.
+   - Switch code should not be on the same line as a switch case.
+   - Condensed switches (one line total per case) should only be used
+     if all or nearly all the switch can be formatted thus and some
+     benefit to legibility accrues.
+   - Infinite loops should be written as "while (1)", not "for (;;)".
+
+Please do not:
+
+   - Misgroup tokens when declaring pointers. "char* s" is wrong. It
+     should be "char *s".
+   - Write your comparisons backwards. "if (0 == x)" is really
+     unnatural to read.
+   - Leave off the space after while, for, and if, or, conversely,
+     insert a space between a function name and its arguments. while,
+     for, and if are not functions.
+   - Use gratuitous parentheses with return to make it look like a
+     function call.
+
+
+Include files:
+
+   - Include files should be grouped in this order:
+	- standard C includes
+	- OS, compiler, or GUI-specific includes
+	- AG's own includes
+
+   - Within these groupings, headers should appear in alphabetical
+     order. (Why...? Why not?)
+
+   - Exceptions: any <sys/*.h> should come before other standard
+     headers. And if any <sys/*.h> are used, <sys/types.h> should come
+     first. Also, "pf.h" should be included after any standard headers.
+
+   - Further exceptions: AG's log header should come last, and should
+     be preceded by a commented-out "#define INCLUDE_LOGGING".
+     Examples abound.
+
+   - To the extent practical, don't use (even within AG_ON_UNIX)
+     header files that aren't standard or standardish Unix, or that
+     would require build-time tests in the configure script to make
+     work right.
+
+   - Each AG header file should be idempotent, that is, a source file
+     that just includes it should be compilable and its compilation
+     should not be affected by whether other headers have been
+     included or in what order.
+
+   - Each header should have an #ifndef guard in the standard form to
+     protect against repeated inclusion.
+
+   - Do not use the standard <assert.h> within AG - only use AG's own
+     "assert.h".
+
+
+ifdefs:
+
+   - Use #ifdef AG_ON_UNIX and #ifdef AG_ON_WINDOWS for
+     platform-specific code. Don't use compiler ifdefs for this;
+     in the long run compilers are more portable than you think.
+
+   - Don't use #ifndef AG_ON_UNIX or #ifndef AG_ON_WINDOWS, unless
+     it's to issue a #error.
+
+   - Don't use #if defined() in place of #ifdef.
+
+   - Do mark #endifs with the symbol from their matching #ifdef,
+     #ifndef, or #if, unless that directive is only a few lines above
+     and easily recognizable.
+
+   - Use compiler-specific ifdefs only where you have to. If possible,
+     abstract the construct out to minimize the amount of conditional
+     code.
+
+   - If a compiler doesn't have a well-known, safe, and/or easily
+     recognizable symbol to #ifdef on, adjust the makefiles to set
+     one when that compiler is used, rather than litter the code with
+     possibly flaky ifdefs.
+
+   - Don't use processor-specific ifdefs. Write portable code.
+
+
+C++ language restrictions:
+
+   - Do not use STL headers.
+
+   - Do not use << >> operators for I/O.
+
+   - Declare functions with no arguments as explicitly taking void,
+     like you would in C.
+
+   - Don't do wild things with templates.
+
+   - Don't do "for (int i=0; ...)" - we have a compiler that uses the
+     really old scoping semantics for this.
+
+   - Use your common sense. Neither the language nor compiler has any.
+
+
+Portability concerns:
+
+   - When using fopen, always use "b" with binary files. Don't use "t"
+     for text files, as this is nonstandard and at least one Windows
+     compiler's library objects to it.
+
+   - When using open(), always use either O_BINARY or O_TEXT.
+
+   - The proper type associated with strlen() and sizeof() is size_t.
+     Don't use "int" or "unsigned". The signed return value of Unix
+     read() and write() has type "ssize_t". Cast that back to size_t
+     after checking it for being an error return.
+
+   - When using printf, don't use the C99 %-specifier for size_t;
+     always cast size_t to unsigned long and print with %lu.
+
+   - Assume that time_t may be 64 bits wide, even on 32-bit platforms.
+     If you need to print one literally, use %lld and cast to long
+     long.
+
+   - Don't assume that all pointers are the same size, or that
+     pointers are the same size as either int or long.
+
+   - In the mainline AG code avoid using anything that might be
+     locale-dependent, as the user interface might have set some crazy
+     locale.
+
+   - Don't blindly slice filename strings using path separator
+     characters. Use appropriate functions instead. And avoid slicing
+     filename strings unless necessary.
+
+   - Always pull the name component out of a pathname before looking
+     for any filename suffix. Otherwise you lose on names like
+     "foo.d/bar".
+
+
+Robustness concerns:
+
+   - If you mean to fall through the bottom of a switch case (one that
+     has code) put /* FALLTHROUGH */ there.
+
+   - If you have virtual functions in a class, declare the destructor
+     virtual too.
+
+   - If you have functions in a class that are virtual because they're
+     declared that way by a base (ancestor) class, declare them
+     explicitly virtual yourself too.
+
+   - Don't define virtual functions inline, unless there's no other
+     practical place to put the definition.
+
+   - Use parentheses when mixing && and ||, or &, |, and ^, or in
+     other cases where operator precedence is easily confused.
+
+   - If you need an assignment inside a conditional, wrap the
+     assignment in parentheses and an explicit comparison. (Not just
+     extra parentheses.) But don't do this unless there's a reason for
+     it.
+
+   - If using qsort() from <stdlib.h>, be sure your compare function
+     only returns 0 for identical objects. If the objects aren't
+     identical, always pick *something* to distinguish by, so the sort
+     is deterministic.
+
+
+Idioms:
+
+   - YES:  if (!strcmp(a, b))
+     NO:   if (strcmp(a, b) == 0)
+
+   - YES:  if (strcmp(a, b) != 0)
+     NO:   if (strcmp(a, b))
+