Sophie

Sophie

distrib > Mageia > 1 > i586 > by-pkgid > a46a385b8ffc2eea333e6d5af2f8e004 > files > 32

deadwood-3.0.02-1.mga1.i586.rpm

Here are some coding style guidelines for the Deadwood code base:

* Use the dw_str library for all string operations.  This protects
  us from buffer overflows.

* Functions that create a string object should have an error catcher at
  the end that destroys any strings created inside the function.  *Do not*
  use "return foo;" in a function with an error cather, instead use
  "ret = foo; goto catch_function_name;".  This ensures that any allocated
  strings are destroyed.

  There are certain cases where the string destructor is not so simple.  For
  example, a string may be declared in one function, and allocated in another
  function called by the first function.  If this is done, when the
  string is allocated in the sub-function, make a note of where the 
  destructor for the string is, and make sure the string is destroyed.

  I understand that goto is considered bad style in some circles.  It is
  necessary here to make up for C's lack of error catching (if only C had
  try/catch/throw).

* Whenever a string is to be destroyed, make sure the string has a non-0
  value.  Once a string is destoryed, set the string to have a 0 value.  
  This stops double-free()s and freeing of null pointers.

* Any indexed writes, such as a[b] = c or *(a + b) = c need to have
  some kind of bounds checking.  This protects us from buffer overflows.

* Arrays and strings should always be at least one character longer than
  you think you will need for the array.  This protects us from off-by-one
  errors.

* Any resource created: File pointers, sockets, etc. needs a destructor.  
  File pointers are usually destroyed after reading the file, or if there
  is an error reading a file.  Sockets are destroyed after using the 
  socket (or never in case of the sockets that bind to ports).  Etc.

* A single function should not, unless there is a compelling reason, be
  longer than 52 lines.  The thinking is this: If we keep individual 
  functions small, then the code will be easier to follow and debug.

  Should a function be 52 lines or longer, please state why in the comments
  before the function.  The size of a function does not include any comments
  before the function describing the function.

  (When finishing up the recursion, I started ignoring this particular 
  rule.  Functions are still fairly short and should be easy to follow.)

* All functions should be documented with at least a brief comment.  If you
  are not a native English speaker, please let me know, and I will correct
  any grammatical errors in your comments.

* Code should be written using an environment where each tab stop is eight
  spaces long.  A single line of code should never be wider than 80 columns
  (yes, this is a throwback to ancient history when there existed text
  terminals with 80 columns per line).  If you find yourself nesting more
  deeply, consider putting the deeply nested code in a sub-function.

* All variables should be decalred at the beginning of a function.  All
  variables should have some initial value, usually 0.  This is not true for
  all variable types; complicated structures do not need to be initialized
  in the variable declaration at the top.  However, all integers and pointers
  must be initalized; pointers must be initialized with a value of 0.

* Complicated data structures should be initialized with either a small
  function, or a #define init_structure(a) a.element1 = 0; a.element2=0;
  form.  This way, if we add a new element to the structure, we only need
  to change the one initalizer.

* All "for"s, "if"s, "while"s, etc. should use bracing, even if we are
  only looking at one statement.

* condition ? true : false constructs should not be used unless there is
  a compelling reason to use them.  Please state the compelling reason to 
  use the x?t:f form in the comments around the code in question.

* When using code that needs an integer with a given size, it is best to 
  use the C99 forms supported in the <stdint.h> header file:

	uint8_t for unsigned 8-bit numbers
	int8_t for signed 8-bit numbers
	uint16_t for unsigned 16-bit numbers
	int16_t for signed 16-bit numbers
	uint32_t for unsigned 32-bit numbers
	int32_t for signed 32-bit numbers
	uint64_t for unsigned 64-bit numbers
	int64_t for signed 64-bit numbers

* Likewise, an "int" without a size specified should still work if a given
  compiler's "int" is a 16-bit number (-32768 to 32767)

* malloc() system calls (and dw_new() calls) must have their return value
  checked.  If the return value is 0, do something appropriate, like telling
  the user the program could not allocate memory and exiting.

* All code that uses sockets needs to be written in a manner that works in
  both Windows and *NIX.  See the SOCKET.CODING.STYLE document for all
  of the details.

* All variables used inside a function must be declared at the beginning
  of the function.  Since we have a "functions are 52 lines or shorter"
  rule, this should not be too difficult to do.  The reason for this:
  It makes code audits easier.

* All code needs to be written in an endian-neutral manner.  For example,
  instead of:
	
	uint16_t foo;
	foo = (uint16_t *)(some_string);

  Use something like:

	uint16_t foo;
	if(some_string_size + 1 > some_string_maximum_size) {
		ret = -1;
		goto catch_this_functions_name;
	}
	foo = (*(some_string + 1) & 0xff) | ((*some_string & 0xff00) >> 16);

* Bracing looks like this:

int foo() {
	int a = 0;
	for(a = 0; a < 100; a++) {
		if(a < 50) {
			printf("A is only %d\n",a);
		} else if(a < 75) {
			printf("A is %d\n",a);
		} else {
			printf("A is now %d\n",a);
		}
	}
}

* #ifdef and other conditional compiling macros must, in the corresponding
  #endif, have, in comments, the name of the "define" needed to compile the
  code in question.  For example:

#ifdef FOO
	foo_bug_workaround();
#endif /* FOO */

* There are not to be potential infinite loops.  while(1) and for(;;)
  constructs are not allowed, unless it is the program's main loop.

  In DwSocket.c and DwTcpSocket.c, the for(;;) is the program's main loop

  while(1) constructs are not used; always use for(;;) for the program's main
  loop

  while loops must be written in such a way that a counter increments and
  the while loop will eventually terminate if the counter goes over a 
  reasonable value.  

  This is to stop bugs like the bug that caused some Microsoft Zunes to
  freeze on December 31, 2008