wiki:Coding Conventions

The following conventions are the conventions decided by the core team and apply to all C/C++ code. If you want to contribute code to SHR, reading this article is a must.

Intro

The following conventions are a modified version of the great conventions used by the Linux kernel ( http://www.kernel.org/doc/Documentation/CodingStyle). Although the Linux kernel has a lot of well thought about great conventions, we felt there are some changes that must take place and that we don't agree with (although not many, they have to be stated). Because of the many similarities between the Linux and the SHR coding conventions quite a few of the examples shown here are actually taken from the document linked above. This document is only a summary of the Linux kernel coding style, and does not replace it, only adds to it. Therefore one should also read that before reading this one.

This coding convention can be achieved (mostly) using the following gnu indent command: "indent -nbad -bap -bbo -nbc -br -brs -cdw -nce -cs -l80 -lc80 -nlps -npcs -nprs -psl -saf -sai -saw -sc -nsob -nss -ut -npro -i8 -cli0 -ts8"

Please try as you can to make the code you submit compile with -Wall -Wextra, in the future they'll be probably added with the addition of -Werror. Compiler warnings can help preventing annoying bugs.

Indentation

  • Spaces are not allowed, tabs should be used instead.
  • A switch statement should be indented as follows:
    	switch (suffix) {
    	case 'G':
    	case 'g':
    		mem <<= 30;
    		break;
    	case 'M':
    	case 'm':
    		mem <<= 20;
    		break;
    	case 'K':
    	case 'k':
    		mem <<= 10;
    		/* fall through */
    	default:
    		break;
    	}
    
    
  • Avoid putting several statements in the same line, including if statements.

Breaking long lines and strings

  • Lines are 80 columns long and therefore statements longer than that should be broken into several lines. This is not necessary if the part exceeding the 80 columns mark doesn't include important information for understanding the code.

Placing braces and spaces

Braces

if, while, for, switch and etc

This applies to all non-function statement blocks:

if (x is true) {
	we do y
}

When writing single statement if/loops you should generally drop the braces, though there is one exception, nested ifs. In the case of nested ifs, the braces should be kept no matter what.

Rationale: Many python (and also non-python) programmers tend to write code like this:

if (cond1)
	if (cond 2)
		do1();
else
	do2();

And of course this is BAD because the else matches the second if, and not the first, therefore, when nesting ifs, never drop spaces.

Although the kernel coding conventions require the matching else statement to be in the same line of the ending brace of the if statement it matches, the SHR conventions require it to be in a line of it's one, like this:

if (x == y) {
	..
} 
else if (x > y) {
	...
} 
else {
	....
}

Rationale: This makes commenting the if/else sections easier, and cleaner.

do while

do {
	we do y
} while (condition);

Functions

Function's braces begin a new line.

int
function(int x)
{
	body of function
}

Structs

The struct's name should be on the same line as the ending bracket:

struct my_struct {
	int a;
} my_struct;

Spaces

  • So use a space after these keywords:

if, switch, case, for, do, while

  • but not with sizeof, typeof, alignof, or attribute. E.g.,

s = sizeof(struct file);

  • Do not add spaces around (inside) parenthesized expressions.
  • Use one space around (on each side of) most binary and ternary operators, such as any of these:

+ - < > * / % | & <= >= == != ? :

  • but no space after unary operators: & * + - ~ ! sizeof typeof alignof attribute defined
  • no space before/after the postfix/prefix increment & decrement unary operators: ++ --
  • no space around the '.' and "->" structure member operators.
  • Do not leave trailing white spaces at the ends of lines.
  • Leave an empty line at the end of every source file.

Naming

Variables

  • There's no need to choose over-descriptive names for local variables, num, chr and i do the job great. It is preferred to add a comment about the purpose of the variable near the declaration point of the function.
  • The above point does not mean you should call your variables 'asdf' or 'a1_tfa', as local variables should still be named according to their purpose and should be easy to write and understand.
  • Global variables should have descriptive names and words should be split by using an underscore, for example global_variable. Global variables should only be used when they are really needed.

Structs, enums and typedefs

They all should have names of the following form: DataType?.
Structs/enums that are meant to be typedefed should have the name of the typedef prefixed with an underscore '_'.

A typedef is used to *HIDE* data, therefore if you have a struct/enum that will forever stay a struct/enum, don't typedef it! You should *NEVER* access a field of a typedefed struct in your code, if you have, this must mean you shouldn't have typedefed in the first place!

Same goes for enums, enums are great, and should be used (they help readability) but they should not be typedefed unless necessary.

Read more about sturcts, enums and typedef in the kernel coding conventions.

Functions

Function names should be descriptive. Functions should be named like this: this_is_a_function(). Static functions can have abbreviations in their name, but global functions can not (unless REALLY obvious). Furthermore, global functions should have a very descriptive name that will help finding the function in the source code easily, for instance e17 does that perfectly. A function in evas, in the common engine that retrieves font kerning will be called: evas_common_font_kerning_get().

Additional info

  • Don't show-off your C-wizardry, complex C-experts tricks are easy to understand when you are a C expert (and even if you are, they are not always trivial), in order to NOT block new contributors and to make the code cleaner, you are politely asked to avoid complex and cryptic expert C expressions.
  • The function type and name should be on different lines, i.e:
    int
    some_function(int a)
    {
    	...
    }
    
  • When you write code that's not perfect or you think you spotted an error in someone else's code, please add /* FIXME: description */ to the code.

TODO

  • convert the existing source to conform with the conventions.
  • write vimrc/emacs/other editor profiles for the conventions.