Conventions and coding-style guidelines for Genode
Documentation and naming of files
We use the GOSH syntax https://codeberg.org/genodelabs/gosh for documentation and
README files.
We encourage that each directory contains a file called README that briefly
explains what the directory is about.
File names
All normal file names are lowercase. Filenames should be chosen to be
expressive. Someone who explores your files for the first time might not
understand what mbi.cc means but multiboot_info.cc would ring a bell. If a
file name contains multiple words, use the _ to separate them (instead of
miscmath.h, use misc_math.h).
Coding style
Things to avoid
Please avoid using pre-processor macros. C++ provides language
features for almost any case, for which a C programmer uses
macros.
- Defining constants
-
Use enum instead of #define
enum { MAX_COLORS = 3 };
enum {
COLOR_RED = 1,
COLOR_BLUE = 2,
COLOR_GREEN = 3
};
- Meta programming
-
Use templates instead of pre-processor macros. In contrast to macros,
templates are type-safe and fit well with the implementation syntax.
- Conditional-code inclusion
-
Please avoid C-hacker style #ifdef CONFIG_PLATFROM - #endif
constructs. Instead, factor-out the encapsulated code into a
separate file and introduce a proper function interface.
The build process should then be used to select the appropriate
platform-specific files at compile time. Keep platform dependent
code as small as possible. Never pollute existing generic code
with platform-specific code.
Header of each file
/*
* \brief Short description of the file
* \author Original author
* \date Creation date
*
* Some more detailed description. This is optional.
*/
Identifiers
-
The first character of class names are uppercase, any other characters are
lowercase.
-
Function and variable names are lower case.
-
Multi_word_identifiers use underline to separate words.
-
CONSTANTS and template arguments are upper case.
-
Private and protected members of a class begin with an _-character.
-
Accessor methods are named after their corresponding attributes:
/**
* Request private member variable
*/
int value() const { return _value; }
/**
* Set the private member variable
*/
void value(int value) { _value = value; }
-
Accessors that return a boolean value do not carry an is_ prefix. E.g.,
a method for requesting the validity of an object should be named
valid(), not is_valid().
Indentation and alignment
-
Use one tab per indentation step. Do not mix tabs and spaces!
-
Use no tabs except at the beginning of a line.
-
Use spaces for the alignment of continuation lines such as function
arguments that span multiple lines. The alignment spaces of such lines
should start after the (tab-indented) indentation level. For example:
{
<tab>function_with_many_arguments(arg1,
<tab><--- spaces for aligment --->arg2,
...
}
-
Remove trailing spaces at the end of lines
This way, each developer can set his preferred tab size in his editor
and the source code always looks good.
Hint: In VIM, use the set list and set listchars commands to make tabs
and spaces visible.
-
If class initializers span multiple lines, put the colon on a separate
line and indent the initializers using one tab. For example:
Complicated_machinery(Material &material, Deadline deadline)
:
<tab>_material(material),
<tab>_deadline(deadline),
<tab>...
{
...
}
-
Preferably place statements that alter the control flow - such as
break, continue, or return - at the beginning of a separate line,
followed by vertical space (a blank line or the closing brace of the
surrounding scope).
if (early_return_possible)
return;
Variable declarations
-
When declaring a reference or a pointer, don't leave a space between the
the & or * characters and the variable name. In C++, the role as a
reference or pointer belongs to the variable, not the type. The following
(exaggerated) formatting is misleading because it suggests a symmetry
between x and y.
int i = 0;
int & x = i,
y = i;
i++;
After incrementing, x is 1 but y is 0 still.
The following formatting leaves less room for wrong interpretations.
int i = 0;
int &x = i,
y = i;
-
As a general rule in C++, qualifiers like const, volatile, and mutable
refer to the preceding text. E.g, char * const is an immutable pointer
that points to a mutable buffer. In contrast, char const * is a mutable
pointer that points to an immutable buffer.
Only in the special case where const is the first word,
it refers to the word after it. Don't use this special case. Consistently
put qualifiers to the right: const char * should be char const *.
Switch statements
Switch-statement blocks should be indented as follows:
switch (color) {
case BLUE:
<tab>break;
case GREEN:
<tab>{
<tab><tab>int declaration_required;
<tab><tab>...
<tab>}
default:
}
Please note that the case labels have the same indentation
level as the switch statement. This avoids a two-level
indentation-change at the end of the switch block that
would occur otherwise.
Vertical whitespaces
In header files:
In implementation files:
Braces
-
Braces after class, struct and function names are placed at a new line:
class Foo
{
public:
void method(void)
{
...
}
};
except for one-line functions.
-
All other occurrences of open braces (for if, while, do, for,
namespace, enum etc.) are at the end of a line:
if (flag) {
..
} else {
..
}
-
One-line functions should be written on a single line as long as the line
length does not exceed approximately 80 characters.
Typically, this applies for accessor functions.
If slightly more space than one line is needed, indent as follows:
int heavy_computation(int a, int lot, int of, int args) {
return a + lot + of + args; }
Comments
Function/method header
Each public or protected (but no private) method in a header-file should be
prepended by a header as follows:
/**
* Short description
*
* \param a meaning of parameter a
* \param b meaning of parameter b
* \param c,d meaning of parameters c and d
*
* \throw Exception_type meaning of the exception
*
* \return meaning of return value
*
* More detailed information about the function. This is optional.
*/
Descriptions of parameters and return values should be lower-case and brief.
More elaborative descriptions can be documented in the text area below.
In implementation files, only local and private functions should feature
function headers.
Single-line comments
/* use this syntax for single line comments */
A single-line comment should be prepended by an empty line.
Single-line comments should be short - no complete sentences. Use lower-case.
C++-style comments (//) should only be used for temporarily commenting-out
code. Such commented-out garbage is easy to grep and there are handy
vim-macros available for creating and removing such comments.
Variable descriptions
Use the same syntax as for single-line comments. Insert two or more
spaces before your comment starts.
int size; /* in kilobytes */
Multi-line comments
Multi-line comments are more detailed descriptions in the form of
sentences.
A multi-line comment should be enclosed by empty lines.
/*
* This is some tricky
* algorithm that works
* as follows:
* ...
*/
The first and last line of a multi-line comment contain no words.
Source-code blocks
For structuring your source code, you can entitle the different
parts of a file like this:
<- two empty lines
/********************
** Event handlers **
********************/
<- one empty line
Note the two stars at the left and right. There are two of them to
make the visible width of the border match its height (typically,
characters are ca. twice as high as wide).
A source-code block header represents a headline for the following
code. To couple this headline with the following code closer than
with previous code, leave two empty lines above and one empty line
below the source-code block header.
Order of public, protected, and private blocks
For consistency reasons, use the following class layout:
class Sandstein
{
private:
...
protected:
...
public:
};
Typically, the private section contains member variables that are used
by public accessor functions below. In this common case, we only reference
symbols that are defined above as it is done when programming plain C.
Leave one empty line (or a line that contains only a brace) above and below
a private, protected, or public label. This also applies when the
label is followed by a source-code block header.
Naming of Genode services
Service names as announced via the parent()->announce() function follow
the following convention:
Core's services, which are the most fundamental base services are written
completely upper case. Each developer should be aware of the meaning of the
used acronyms such as RAM, RM, ROM. All other service names should be
descriptive names rather than acronyms. Service names should contain only
letters, numbers, and underline characters. The first character must
always be an uppercase letter, all other characters are lowercase.