The following guidelines were observed when writing the Services source
code. Note, however, that they were treated as guidelines, not rules, with
the cardinal rule being "readability first".
- Lines must not be longer than 79 columns.
- The basic indentation unit is four columns.
- Tab (ASCII \011) characters are not permitted
in source files; indents should always be done using using spaces
(\040). The source files distributed with Services
include settings for the Emacs and Vim editors that cause the Tab
key to insert spaces rather than a tab character.
- Only one statement is allowed per line. Statements
(including the empty statement ";") may not be written on
the same line as a control keyword (if, for, or
while).
- Spaces are placed between binary operators and their
operands, except for the member-reference operators "->"
and "."; spaces are not placed between unary operators and
their operands. However, spaces may be omitted around binary
operators when it would improve readability. Examples:
i = j * 2;
user->channelcount++;
result += i*60 + (j+59)/60;
- NULL, not 0, should always be used in
pointer comparisons. For character comparisons, 0 is
preferred to '\0', but the latter may also be used if it
does not go against the style of the surrounding code. Do not use
'\0' with variables declared as type int8 or
uint8, even though these types are usually equivalent to
char and unsigned char.
- The construct "!!expression" should not
be used. Use "expression != 0" (for characters or
integers) or "expression != NULL" (for pointers)
instead.
- Parentheses are required when && and
|| are used in the same expression to explicitly indicate
order of evaluation; do not rely on the default order of evaluation.
(Not using parentheses will generate a warning when using gcc
-Wall.)
- Parentheses following the control statements "if",
"for", and "while", as well as the macros
LIST_FOREACH, LIST_FOREACH_SAFE, and
ARRAY_FOREACH, are preceded by a space. Parentheses
following function or macro calls (other than the above) are not
preceded by a space. Example:
if (flag)
function();
- Spaces are placed after the comma of each parameter to a
function or macro; however, they may be omitted in function calls
which are themselves parameters to a function or macro, or when
including them would make the line exceed the length limit. Spaces
are also placed after (but not before) the semicolons in a
for statement. Spaces are not placed after the opening
parenthesis or before the closing parenthesis of a function/macro
call or control statement. Examples:
function(param1, param2);
function(param1, strchr(string,'/'), param3);
for (i = 0; i < count; i++) ...
- Opening braces of control statement blocks go on the
same line as the control statement (if, for,
etc.) associated with the block; function blocks and "naked blocks"
(those not associated with any control statement or function) have
the opening brace alone on a line, indented to the same level as
the surrounding code. Closing braces are indented to the same
level as the line containing the opening brace. Examples:
if (flag) {
/* indented code goes here */
...
}
int function(int param1, char *param2)
{
/* indented code goes here */
...
/* start of a naked block */
{
int foo;
...
}
}
- If an if statement is longer than one line, it
should be broken at logical operators (&& or ||);
the operator should be placed at the beginning of the next line,
and should be indented to show which term the operator belongs
with. The closing parenthesis for the if statement and
the subsequent open brace should be alone on a line, aligned with
the first line of the if statement. (Braces are required
in this case.) Conditions for for and while
statements should never span multiple lines, though a for
statement may be broken at the semicolons if necessary. Examples:
if (ok && (strcmp(option, "option-name-1") == 0
|| strcmp(option, "option-name-2") == 0)
) {
...
}
if (!init_first()
|| !init_second()
|| !init_third()
|| !init_fourth()
) {
/* This example outdents the || by three spaces to line
* up the terms. Such outdenting is acceptable if it
* makes the code easier to read and understand. */
...
}
for (exception = first_maskdata(MD_EXCEPTION); exception != NULL;
exception = next_maskdata(MD_EXCEPTION)
) {
...
}
- An else followed by an if is considered to be a
single keyword, "else if". The if part should
always be placed on the same line as and immediately following the
else; the else if should never be split up onto
two lines, nor should braces be used around the if block.
The exception to this is when the else and if
refer to two conceptually distinct sets of conditions, in which
case the if block should be enclosed by braces and
indented. Example:
res = check_password( /* ... */ );
if (res == 0) {
...
} else if (res == 1) {
/* "else if" on a single line */
...
} else {
if (user->ni != NULL) {
/* "if" condition is different from "else"
* condition, thus separate */
...
}
}
- Braces are always placed around the body of a control statement
(if, for, etc.). The two exceptions are
else followed by if, mentioned above, and
statements for which the body, as well as the bodies of any
else if or else statements for an if
statement, are all one statement in length and do not contain any
nested control statements; in this latter case, braces are optional
(but recommended if any of the statements span multiple lines).
Examples:
for (i = 0; i < count; i++)
function(i);
while (!done) {
/* Braces required because of the nested "if" */
if (do_stuff())
done = 1;
}
if (state == 0) {
a = b;
} else if (state == 1) {
/* Every if/else body gets braces because this body
* has two statements */
b += a;
a = 0;
} else {
state = 0;
}
- When using multiply-nested control statements, or a single control
statement which has a long block, the closing brace of the block
should be followed by a comment indicating what control statement
the block belongs to. This should usually be the content of the
control statement, but may be abbreviated as long as its meaning is
clear. If a long if block is followed by an else
clause, the else should likewise be documented. Examples:
while (i < count) {
...
} /* while (i < count) */
if (flag) {
...
} else { /* !flag */
...
} /* if (flag) */
for (node = first; node != NULL; node = node->next) {
...
} /* for all nodes */
- case and default labels for a switch
should be indented half of a normal indentation unit (two columns)
from the line containing the switch with which they are
associated; statements associated with a case should be indented a
full unit from the line containing the switch (half a unit
from the case). If a case requires its own block, such as
when it declares its own local variables, the opening brace is
placed after the colon on the case line. Example:
switch (variable) {
case 123: {
int foo;
...
break;
} /* case 123 */
default:
...
return -1;
}
- When a case in a switch block does not contain a
break (or return) statement and deliberately
"falls through" to the next case, a comment to this effect should
be made at the bottom of the case. Example:
switch (state) {
case 0:
...
/* fall through */
case 1:
...
break;
}
- Inline comments (comments placed to the right of a line of code)
should be aligned to start on the same column, when this does not
place too much space between the comment and the code or cause the
line to exceed 79 columns in length. Inline comments after
unusually long lines (such as long field declarations in
structures) should be placed alone on the following line, indented
the proper amount.
- The goto statement should not be used except in error
handling situations where it will help avoid multiple levels of
if nesting or other awkward code. Labels for
goto should be outdented half of an indentation unit
from the surrounding code (i.e., indented two columns less
than the surrounding code).