Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document the new coding style #69

Merged
140 changes: 69 additions & 71 deletions kb/development/mbedtls-coding-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,102 +8,101 @@ This document describes Mbed TLS preferences for code formatting, naming convent

## Code Formatting

Mbed TLS source code files use 4 spaces for indentation, **not tabs**, with a preferred maximum line length of 80 characters.
### K&R

Every code statement should be on its own line.
Mbed TLS generally follows the style of *The C Programming Language*, Second Edition, 1988, by Brian Kernighan and Dennis Ritchie (“K&R2”). The main deviations are:

**Avoid statements like this:**
```c
if( a == 1 ) { b = 1; do_function( b ); }
if( a == 1 ) do_function( a );
```
* Indentation is 4 spaces (like K&R2, not 5 spaces like K&R1). Do not use tabs.
* `case` is indented one level further than `switch`.
* The body of `if`, `for` or `while` must be on a separate line and surrounded with braces, even if it's a single statement.

### Space placement
### Indentation

Mbed TLS uses a non-standard space placement throughout the code, where there is no space between a function name and all parentheses are separated by one space from their content:
```c
if( ( ret = demo_function( a, b, c ) ) != 0 )
```
The same applies to function definitions:
```c
int demo_function( int a, const unsigned char *value, size_t len )
```
There are a few exceptions to this rule. This includes the preprocessor directive `defined` and casts, as well as arguments for function-like macros:
```c
#if defined(MBEDTLS_HAVE_TIME)
timestamp = (uint32_t) time( NULL );
```
Mbed TLS source code files use 4 spaces for indentation, **not tabs**, with a preferred maximum line length of 80 characters.

### Braces placement and block declaration
`case` is indented one level further than `switch`.

Braces (curly brackets) should be located on a line by themselves at the indentation level of the original block:
```c
if( val >= 1 )
{
if( val == 1 )
{
/* code block here */
}
else
{
/* alternate code block */
}
}
```
In case a block is only single source code line, the braces can be omitted if the block initiator is only a single line:
```c
if( val >= 1 )
a = 2;
switch (x) {
case 0:
zero();
break;
...
}
```
But not if it is a multi-line initiator:

Labels are indented at the same level as the enclosing block.
```c
if( val >= 1 &&
this_big_statement_deserved_its_own_line == another_big_part )
{
a = 2;
int f()
{
...code...
if (ret != 0) {
goto exit;
}
...code...
exit:
...cleanup...
return ret;
}
```

### Related lines: Multi-line formatting and indentation
Every code statement should be on its own line, except in `for` loop headers.

Multiple related source code lines should be formatted to be easily readable:
```c
#define GET_UINT32_LE( n, b, i ) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
### Space placement

if( my_super_var == second_super_var &&
this_check_will_do != the_other_value )
Put a space in the following places:

do_function( ctx, this_is_a_value, value_b,
the_special_var );
* Around binary operators: `(x + y) * z`
* After a comma: `f(x, y)`
* Before the asterisk in a pointer type: `int *p`
* Between `if`, `switch`, `while`, `for` and the opening parenthesis: `if (f(x))`
* Outside curly braces: `do { ... } while (!done)`, `struct mystruct s = { 0 }`
* Inside the curly braces around initializers: `int a[] = { 1, 2, 3 };`

void this_is_a_function( context_struct *ctx, size_t length,
unsigned char *result );
```
Do not put a space in the following places:

### Extra parentheses for `return` and `sizeof`
* After the function or macro name in a function or macro call: `f(x, y)`
* Inside parentheses: `if (f(sizeof(int), (int) y))`
* Inside square brackets: `a[i + 1]`
* Before a comma: `f(x, y)`
* After a unary operator: `if (!condition)`, `++x`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* After a unary operator: `if (!condition)`, `++x`
* After a prefix unary operator: `if (!condition)`, `++x`

* Before a unary operator: `x++`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Before a unary operator: `x++`
* Before a postfix unary operator: `x++`

* Between an array and the following opening bracket: `int a[2]; a[i]`
mpg marked this conversation as resolved.
Show resolved Hide resolved
* Around field access symbols: `s.a`, `p->a`
* After the asterisk in a pointer type: `int *p`
* Between the asterisks double pointers types or derefences: `char **p`, `x + **p`

Within Mbed TLS return statements use parentheses to contain their value:
### Use of parentheses

`sizeof` expressions always use parentheses even when it is not necessary (when taking the size of an object):
```c
return( 0 );
memset(buf, 0, sizeof(buf));
```
Similarly, sizeof expressions always use parentheses even when it is not necessary (when taking the size of an object):

### Braces placement and block declaration

Braces are mandatory in control statements such as `if`, `while`, `for`, even when the content is a simple statement.
Opening braces (curly brackets) are on the same line as the control statement.

Closing braces are aligned with the control statement or opening brace. They are generally alone on their line, except when followed by `else` or by the `while` of a `do ... while` statement.

```c
memset( buf, 0, sizeof( buf ) );
do {
x += f();
if (x == 0) {
continue;
}
x += g();
} while (condition);
mpg marked this conversation as resolved.
Show resolved Hide resolved
```

### Formatting of lists

When a function or macro call doesn't fit on a single line, put one argument per line or a sensible grouping per line. For example, in the snippet below, `input_buffer` and `input_size` are on a line of their own even though the call could fit on two lines instead of three if they were separated:
```c
function_with_a_very_long_name( parameter1, parameter2,
input_buffer, input_size,
output_buffer, output_size );
function_with_a_very_long_name(parameter1, parameter2,
input_buffer, input_size,
output_buffer, output_size);
```

Lists of items other than function arguments should generally have one item per line. Exceptions:
Expand All @@ -113,8 +112,7 @@ Lists of items other than function arguments should generally have one item per

In lists of items such array initializers and enum definitions, do include the optional comma after the last element. This simplifies merging, reordering, etc.
```c
typedef enum foo
{
typedef enum foo {
FOO_1,
FOO_2, // <- do put a comma here
}
Expand Down