#
# $XORP: xorp/devnotes/coding-style.txt,v 1.6 2007/05/23 12:12:33 pavlin Exp $
#

	Provisional XORP C++ coding style

This is a *provisional* attempt to lay down some rules that we can
adhere to and moan about. The style is only intended to apply to new
code, not code that we import.  Hopefully, the style is equidistant
from our default coding styles that all are equally peturbed.

- DOCTRINE

  Ignore any section of this document when doing so would enhance
  readability.  Feel free to edit someone else's code into agreement
  with these principles, or into agreement with your own variant of
  these principles.  Expect that your code may be likewise edited.

- FILE PROLOGUES

  Files should have a prologue containing the copyright, a description
  of what the file does, an RCS version id, and an RCS
  string/identifier in implementation files that ident(1) can use.

  We have a standard templates to work from:
     devnotes/template.hh
     devnotes/template.cc
     devnotes/template.h
     devnotes/template.c

- INDENTATION

  Use 4 spaces per indent level.  Indentation should generally follow
  "gnu".  The default emacs c/c++ style is gnu, can be set with
  M-x c-set-style gnu).

- BRACES

  Try to avoid gratuitous newlines between statements opening a brace
  and the opening brace. E.g., prefer:

	if (abc == 3) {
		/* XXX */
	}

  to:
	if (abc == 3)
	{
		/* XXX */
	}

  For the sake of readability, try to place white space either side of
  braces. E.g., prefer:
	bool foo() { return _some_value; }
  to:
	bool foo() {return some_value;}

- REFERENCE AND POINTER ANNOTATIONS

  Prefer:
	foo(int& x) and bar(int* y)
  to:
	foo(int &x) and bar(int *y)

  The former appears to be more widely used in C++ literature and so we go
  with this for the sake of consistency.

- TEMPORARY REFERENCES

  Temporary references can help make code more readable.  When used
  with containers to pointer types the resulting code can be more
  readable and efficient.

	static void process(const string& s);	    // Forward declaration

	static void
	process_long_names1(list<string*> names)
	{
	    list<string*>::const_iterator ci;
	    for (ci = names.begin(); ci != names.end(); ++ci) {
	        if ((*ci)->size() > 10) {	    // Direct use of iterator
		    process(*(*ci));
		}
	    }
	}

	static void
	process_long_names2(list<string*> names)
	{
	    list<string*>::const_iterator ci;
	    for (ci = names.begin(); ci != names.end(); ++ci) {
		const string& s = *(*ci);	    // Use of temporary ref
		if (s.size() > 10) {
		    process(s);
		}
	    }
	}

- COMMENTS

  Use // for comments.

  Avoid obvious comments inside routines. Any comments inside routines
  should be short -- one line, when possible. Prefer single blank
  lines for separating sections of code.

- API DOCUMENTATION (kdoc)

  All major routines should have a comment briefly describing what
  they do.  We use kdoc comments (similar to javadoc) to generate API
  overviews and programming documentation.

- TERMINAL WIDTH

  Assume the terminal is 80 characters wide.  Sure there'll be odd
  times when wraps cannot be avoided, but gratuitous wrapping will
  give you a "wide boy" reputation.

- CAPITALIZATION

	class Wrench {
	public:
	    Wrench() { ... };
	    ~Wrench() { ... };
	    apply_force();
	    ...
	private:
	    double _weight;
	};

  Note that the class's public interface comes first.

- UNDERSCORING

  Member variables should begin with an underscore.  Regular variables
  and function names should separate words with underscores.

  Double underscores should never be used, they are often used by the
  compiler during name munging.

- NAMES FOR MODIFIERS AND ACCESSORS.

  Often, a private member variable will have associated public member
  functions that get and/or set its value. If the variable is named
  "_xxx", name the getter function "xxx()" and the setter function
  "set_xxx()". The getter function should generally be const.

- STRING METHODS

  When necesary to have a string method, call it str().  In general, try
  to avoid adding operator string().

- BOOL METHODS

  In general, always avoid adding operator bool(), unless there is a
  strong reason for adding it.

- METHOD DEFINITIONS

  When defining C++ in implementation files place the return value
  and class/method declarations on separate lines. E.g.,

	const char*
	LuckyEightBall::speak() const
	{
	// blah blah
	}

- ABBREVIATIONS

  Should be avoided, especially in method names.

- INTEGER TYPES

  Use integer types defined in inttypes.h, these are POSIX compatible
  and portable.

- USE OF CONST

  Decorate member functions with "const" whenever appropriate for
  purposes of documentation. Member functions that do not alter an
  object's value should be "const". Sometimes, a member variable is
  altered by a function that does not conceptually change the object's
  value. Mark such member variables as "mutable" to enhance the
  applicability of "const".

- USE OF EXCEPTIONS AND STANDARD TEMPLATE LIBRARY

  Non-kernel modules should use exceptions and the standard template
  library where appropriate.

- USE OF AUTOCONF

  We will use GNU autoconf to improve portability. The "xorp_config.h"
  header file will define symbols specifying system properties that
  may differ between reasonable Unices. This file is included by
  "libxorp/xorp.h" which itself includes and defines a number of other
  useful header files and features. The first file included by any XORP
  source file should be "libxorp/xorp.h".
  However, if one of the included header files is the module-specific
  "foo_module.h" (required by "libxorp/xlog.h"), that file should
  be included before "libxorp/xorp.h".

- INCLUDE FILES

  Include files should be sorted into domain, each domain separated by
  a blank line:

	"foo_module.h"
	"libxorp/xorp.h"
	kernel includes
	sys includes
	net includes
	default include path includes
	XORP libraries includes
	local includes

  Don't sweat it too hard, however.

- SPACES AND PARENTHESES

  Binary operators should have spaces around them to ease
  decipherment.  Parentheses have to used when precedence dictates and
  can be used to reduce confusion, particularly with long
  expressions. Do not put spaces around parentheses.

  Keywords should likewise have spaces around them.  For example,
  `if (x)', not `if(x)'; and `return x', not `return(x)'.

- VARIABLE DECLARATIONS

  Place variable declarations at the beginning of the relevant
  scope. This includes placing declarations in the middle of
  functions, close to their first uses, when appropriate. Declare
  iteration variables inside the `for' statement when possible; this
  is most of the time. Declare a test variable inside the `if' test
  when possible; this happens comparatively rarely. Prefer multiple
  declarations when defining several variables that require
  initializers.

- PORTABILITY

  All IPv6-specific code should be "#ifdef HAVE_IPV6" :
  #ifdef HAVE_IPV6
	 ....
  #endif // HAVE_IPV6

  If there is only one line of code between #ifdef and #endif, then
  do not add the comment after "#endif".

