HelenOS C Coding Style Standard
The purpose of having a common coding style is to have a common language. The more consistent the coding style is, the easier it is for others to read your code.
Any source contribution to HelenOS must follow the C style rules described below. Even if you are working on a school assignment, we kindly ask you follow our coding style up front. It's a colossal waste of our resources having to update the coding style in order to merge your changes to our mainline.
This document is, by definition, incomplete. Even if you comply with all the below rules does not mean nobody will comment on your C style. Do try to emulate the style of existing/surrounding code.
Tool support
HelenOS uses the Ccheck tool (https://github.com/jxsvoboda/sycek) to find coding style issues. To run ccheck type make ccheck
. To let ccheck try and fix issues, type make ccheck-fix
. Ccheck is also run as part of make check
and as part of Travis CI on any commit pushed to HelenOS git repo on Github or to any pull request.
Ccheck can verify compliance with many (but not all) code style rules. Passing ccheck is a minimum requirement if a contribution is to be considered compliant with HelenOS coding standards.
Source file encoding
- Source files are encoded in UTF-8
- Only ASCII subset should be used, except for cases of internationalized string literals
- New lines are represented by the LF ('\n') character. Do not use CR + LF or CR.
Identifiers
- C identifiers should be written in lower case, words separated by underscore "_" (foo_bar)
- Types shall be suffixed with "_t"
- Preprocesor symbols shall be all-upper case (FOO_MACRO(), FOO_CONSTANT)
Names
- Use sensible, descriptive names.
- Only use English names (English words, intelligible abbreviations)
- Symbols with narrow scope (local variables) may have terse names (e.g. i)
- Symbols with wide scope must have reasonably unique and meaningful names
- Symbols with module scope or wider scope should follow the prefixing convention (e.g. fibril_create)
Indentation
- Use a single Tab character for indentation, except for line continuations.
- Tab width is considered to be 8 characters.
- A line continuation is indented exactly 4 spaces.
- Lines should not, in general, exceed 80 characters (tab counting as 8).
- Each statement shall be placed on a line on its own.
- Braces shall follow K&R Bracing Style
- For functions the opening brace should be at a new line
- In all other cases the opening brace should be at the same line as the previous token
- Blocks within braces shall be indented 1 tab to the right as compared to the enclosing braces
- Braces without any contents may be placed on the same line.
- Blocks containing a single line can omit braces
- For if…else statements both or neither of the T, F blocks must be delimited by braces
- Labels in functions and switch statements are not indented (i.e. indented one less tab than the other contents of the block)
Spacing
- All binary arithmetic, bitwise and assignment operators and the ternary conditional operator (? shall be surrounded by spaces
- The comma operator shall be followed by a space but not preceded
- All other operators shall not be used with spaces.
- For functions and function-like operators there should be no extra spaces around or inside parentheses (int foo(void), sizeof(bar_t))
- For control statements with parenteses there should be one space between the keyword and opening parenthesis (if (a == b))
- Return statements should omit parentheses, especially when the argument is simple (return 1;)
- Function-like operators (sizeof()) must never omit parentheses
- There should be no space after asterisk (in type declarations or when dereferencing) (int *foo(int *f), *f = *g[3])
Blank lines
- There should be newline at the end of every source file
- There should be one blank line between any two top-level declarations that include a { } body - functions, enums, structs
Comments
- In general, only /* */ comments are allowed.
//
comments can be used only to mark transitional code that needs further attention (e.g.//
FIXME,//
TODO, etc.). - Comments shall be written in gramatically correct English.
- Comments describing action should be written in infinitive tense (/* Create a new entry on the stack. */)
- Short comments need not be a complete sentence and need not end in '.' Such sentence fragments usually do not contain articles (/* Close callback connection */)
- Multiline comments begin with "*" on each inner line.
- The first line of a multiline comment must be just '/*' and the comment itself must start on the next line ('* Comment…')
- Use Doxygen style comments for documenting functions.
- All comments shall be placed above the line the comment describes, indented identically.
- Every source file, function, type shall have a comment that describes its purpose.
- Git commit messages must follow very similar rules
Header files
- Header guards should look like:
_LIBC_SYS_TIME_H
for libraries- [
LOCSRV_
]CATEGORY_H
for servers SHEET_H
for applications
- Function declarations should be marked extern
- Function declarations (same as forward static function declarations) should omit argument names
- Preferred order of #include directives is angle-bracketed, then quoted
- Second level of ordering is lexicographic
- Give an honest attempt at IWYU (include what you use)
- Each source module shall directly include the header file containing any symbol it uses
- Except if there is an 'interface' header file that is meant to be included instead
- Specifically, do not rely on an
$include "common.h"
to blanket-include all header files to all your source modules
License header and copyright messages
- All newly created (original) HelenOS source files (.c and .h) should be licensed under the 3-clause BSD license in the form:
/* * Copyright (c) 2013 John Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
- Copyright lines should always be in the form
* Copyright (c) <year> <Author's name>
Where <year> is the year the file was created by that person for new files. For modified files <year> is the year of last modification.
Miscellaneous
- Spaces instead of tabs should be used for vertical spacing (not indentation). This enables the code to look consistent regardless of the tab size.
- Copyright headers must follow the copyright rules.
- Do not use Yoda comparisons (e.g. NULL == ptr)