Coding Style for Kannel


Code formatting

	Don't make lines that are longer than 78 characters.
	
    	Follow the coding style defined by the astyle program:
	
	    	astyle --style=linux --pad=oper -m0 -s4

	Tabs are 8 characters. Indents are 4.
	
    	Example:

/*
 * This function doesn't do anything sensible. It just uses uses various
 * C constructs to show their layout.
 */
int foo(int bar)
{
    static int tab[2][12] = {
        { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
        { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
    };
    struct yow {
        int plim;
    } barbar;
    int i;

    assert(bar != 0);
    if (bar < 0) {
        for (i = 0; i > bar; --i) {
            while (global_variable < 0) {
                global_variable += i;
                printf("%d\n", i);
            }
        }
    } else {
        do {
            --bar;
            switch (bar % 3) {
            case 0:
                printf("0\n");
                break;
            case 1:
                printf("1\n");
                /*FALLTHROUGH*/
            case 2:
                printf("2\n");
                break;
            default:
                assert(0);        /* eeek! */
                abort();          /* die, stupid program, die */
            }
        } while (bar < 0
                 || global_variable == 42);
    }
    return bar;
}

	It is OK to deviate from this style, if it makes the code clearer.


Commenting

	Each source code file shall begin with a comment of the following
	format:
	
		/*
		 * filename - one-line summary
		 *
		 * A summary of the purpose of the file and a summary
		 * of the functions it exports. If the file is the main
		 * program, a short usage summary or a reference to the
		 * manual should be included.
		 */
	
	Each function should
	be preceded by a comment like the following:
	
		/*
		 * One-sentence summary of what the function does. More 
		 * detailed description of what the function does, including
		 * return value, purpose of each function, and a summary of
		 * who takes care of allocating and freeing memory of the
		 * arguments and return values.
		 */

	Similar comments for global variables, constants, and data types.

Error handling

	Typically, functions should have a return type of int and return
	-1 for errors, 0 for OK (or 0 for no input, positive for indicating
	number of input items read, or similar values). When returning a
	pointer, errors should be indicated with NULL.
	
	When a problem is noticed, the lowest level that notices it
	should log it using one of the log functions in log.h,
	and then return an indication of failure (unless it can handle
	the problem itself) to its caller. If the problem is associated
	with a system error, i.e., the global variable `errno' details
	the problem, it is the lowest level that should pass `errno'
	to the log message function. The callers should just report
	which operation failed, but not report a system error (i.e.,
	they should pass `0' to the log message functions). This way,
	an error causes several lines of output to the logs, and it
	essentially produces a stack dump. This helps diagnose the
	problem, since it becomes more clear which parts of the system
	were involved in the operation that failed.
	
	If you want to incorporate the name of the function in the
	output, use __func__, not __FUNCTION__. The former is part of
	the language starting with the 1999 version, and config.h takes
	care of defining it somehow for older compilers.
	
Memory allocation

	Never use malloc, calloc, realloc, or free. Use gw_malloc,
	gw_realloc, and gw_free instead.

	Do not allocate large arrays on the stack, because there
	are systems where the stack space per thread is quite limited.
	
	If you call a function and give it a pointer, and the function
	stores it somewhere for later use, and the caller still uses the
	pointed area for something, the called function should make sure
	it makes a copy of whatever the pointer points at.  This makes
	it easier for the caller to know when it can free the area.

Log messages

	The logging functions in log.h shall be used, not printf.

	Note that panic must never be used after the gateway has been
	started, except when an error really, really, REALLY cannot
	be handled and recovered from. For example, if memory allocations
	fail, there is little or nothing useful the gateway can do and
	therefore _for_the_gateway_ it is OK to panic. (This is not a
	general rule of software engineering, but it does apply to us.)
	You almost certainly want to discuss things on the devel list
	before adding a call to panic.
	
	Log messages shall consist of complete sentences: start with
	an upper case letter and end in a period (or other suitable
	punctuation character).

	Error messages (functions warning, error, panic) should indicate
	the operation that was being performed, and the (presumed)
	cause of the problem. For example:
	
		Reading configuration file smsgateway.conf: out of memory.
		System error 42: Not enough space.

		Couldn't read configuration file `smsgateway.conf'.
		System error 42: Not enough space.

	Informational messages (function info) probably shouldn't report
	system errors.

	Filenames should be given `quoted' so that it is clear what is
	and what is not part of the name. Similarly for other data that
	may need it.
	
	Open question: The name of the function or source code module
	isn't very informational for people just using the gateway,
	although they can be useful for debugging the gateway. People
	debugging the gateway would probably like the source file, line
	number, and possibly function name be reported systematically.
	What to do?

Log message at the `debug' level: naming convention for `place'

	The debug() function's first argument is called `place'. It tells
	the logical place where call is made from. This is not the same
	as the source file and line; those change too often for them to
	be useful. Instead, it is meant to identify the subsystem and
	subsubsystem (and, if necessary, subsubsubsystem). The following
	subsystems should be used:
	
		wap		WAP Box
		wap.wsp		WSP implementation
		wap.wsp.http	WSP implementation
		wap.wtp		WTP implementation
		wap.wtp.timer	WTP timers
                wap.wtp.tid     WTP tid validation
		wap.wml		WML encoder

		bb		Bearer box: misc stuff
		bb.udp		BB UDP sender/receiver
		bb.boxc		BB box connections
		bb.http		HTTP admin things
		bb.thread	Thread handling
		bb.sms		SMS related stuff
		bb.sms.cimd	CIMD implementation
		bb.sms.cimd2	CIMD 2 implementation
		bb.sms.emi	EMI/UCP implementation
		bb.sms.smpp	SMPP implementation
		bb.sms.sema	SEMA/SMS2000 implementation
		
		sms		SMS box
		
		gw		Misc stuff used by all boxes
		gw.msg		Inter-box messages

		gwlib		Library functions
		gwlib.http	HTTP implementation
		gwlib.octstr	Octet strings

		test		Test programs
		test.fakewap	
		test.udp_send

		util		Utility programs

	If you need more subsystems, please add them here as well.

	Debugging places can be set via '-D' (or --debug) command line
	option, with format like "wap.* bb.csdr" (see gwlib/log.h). Any 
	places need to be excluded from the set are marked with
	preceding '-', like "wap.* -wap.wsp.*"

Using integer types

	Avoid the uint32_t type, and similar types with other names, and
	try to live with:

		int (-32000 to 32000)
		long (-2 000 000 000 to 2 000 000 000)
		unsigned long (0 to 4 000 000 000)
		unsigned char (0 to 255)
	
	The ranges given are _minimum_ ranges. Do not assume that there
	ever exists an integer type of a specific size. If you think you
	need one of a specific size, think again. If that doesn't help,
	discuss things on devel@kannel.org.
	
	The exception to this is that it is probably safe to assume char
	is 8 bits. Do not assume a plain `char' type is signed or unsigned
	- always use unsigned chars. However, remember that it is almost
	always smarter to use an `int' for a char (and store non-negative
	values) instead of an unsigned char, because of the complicated
	type promotion rules in C, when dealing with a single character.
	When using an array ("string"), use unsigned char as the element
	type. However, remember to use Octstr whenever possible.
	
	Some library functions require the use of a specific integer type.
	In that case, use that.

#include directives

	When referring to header files that are not part of Kannel,
	use the <foo.h> syntax. When referring to header files that
	are part of Kannel, use the "foo.h" syntax. Since Kannel source
	code is spread over several directories, use the following
	rules to construct the actual filename:
	
		if foo.c includes foo.h and they are both in the
		same directory, use "foo.h"
		
		if foo.c includes, for example, gwlib.h, and foo.c is not
		in the same directory as gwlib.h, the path relative to
		the root of the Kannel source tree should be given, thus
		"gwlib/gwlib.h".

Header files

	When writing header files for Kannel, write them so that they
	include whatever other header files they need, rather than
	relying on the caller to do that. An exception can be made for
	header files that are not normally included directly by a
	source file, but bundled by another header file (such as gwlib.h).

	This will result in some header files being included multiple
	times by a source file. Deal with that by using this construct,
	where HEADERNAME is the filename of the header file:

		#ifndef HEADERNAME_H
		#define HEADERNAME_H

		... the body of the header file

		#endif

	If your code is not in gwlib, #include "gwlib/gwlib.h", but
	nothing else from gwlib.

Use of #if, #ifdef, etc

	Try to avoid using the various forms of #if for portability
	purposes. It's preferable to write the code so that it works
	everywhere, instead of having umpteen versions for different
	platforms. Only having a single version makes it easier to
	test and debug things, for example.
	
	Don't comment things out with #if (or any other way either).
	We use CVS, it is always possible to go back.
	
	Don't add new features and make them conditionally compiled.
	Either add them completely, or don't add them at all.

Typecasts

	Don't use them, unless you're really certain it's needed. Almost
	always when you think you need one, you are doing things that
	are too tricky and may become a portability problem in the future.
	
	A common exception are the braindead BSD socket functions: they
	have been designed so that typecasts are necessary. We try to
	make wrappers around such functions in gwlib, so that we have the
	cast only in one place.

Abstract data types, constructors and destructors

	Use abstract data types whenever it makes sense. Avoid defining
	structures that are used directly in several modules - this is
	a maintenance headache. Instead, define an abstract data type,
	Foo, and functions to manipulate that data type, e.g., to access
	various fields of Foo.
	
	This is sort of a castrated version of object oriented
	programming. It's a good thing.

    	Use the following naming convention:
	
    	    typedef struct Foo Foo; 	/* The abstract data type */

	    Foo *foo_create(void);  	/* Create a new Foo */
	    void foo_destroy(Foo *);	/* Destroy a Foo */
	    void foo_destroy_item(void *);
	    	    	    	    	/* Wrapper, for list_destroy use */

ChangeLog

	We use the file called `ChangeLog' to log changes, not CVS
	commit entries. CVS entries are not usable by people who don't
	have CVS access (e.g., they are off-line at the moment, which
	happens often for laptop users), and are also harder to browse
	than a single file.

	When writing an entry, please try to make sure the entry is at
	least somewhat understandable without referring to the actual
	patch it reflects. This helps immensely those who want to follow
	Kannel development without having to wade through millions of
	lines of patches per year.

CVS and tags

	We use CVS tags for releases. If the version number is X.Y.Z,
	then the corresponding tag is version_X_Y_Z. Stable branches
	are called stable_X_Y, where X.Y is the stable version that
	started the branch.  If you want to use tags for other things,
	use some other naming scheme. For private use, prefix tags with
	your CVS login name.

Initialization of automatic variables

	Try to avoid embedding initialization of automatic variables in
	their definitions, since they are easy to miss and this can lead
	to trouble. Also, it's too easy to mistakenly use an argument
	value before it has been checked with gw_assert.
