..
#
# Critical Application Monitoring (CAM)
#
# SPDX-FileCopyrightText: Copyright 2023-2024 Arm Limited
# and/or its affiliates
#
# SPDX-License-Identifier: BSD-3-Clause
#
############
Coding Style
############
To maintain consistency within the CAM software source code a series of rules
and guidelines have been created; these form the project's coding style.
***********
Source Code
***********
Unicode
=======
The source code must use the UTF-8 encoding. Comments, documentation and strings
may use non-ASCII characters when required (e.g. Greek letters used for units).
License Headers
===============
All files must begin with a license header of the following form:
.. code-block:: text
Critical Application Monitoring (CAM)
SPDX-FileCopyrightText: Copyright Arm Limited
and/or its affiliates
SPDX-License-Identifier: BSD-3-Clause
Where '' is a list of years the file received updates. Contiguous years
may be written in the form of a hyphened range, example: '2019, 2021-2023'.
************
C Code Style
************
Clang Format
============
To aid in establishing a uniform style across the code-base, this project uses
Clang Format. When contributing patches, care should be taken to ensure that
code has been formatted according to the rules laid down in the .clang-format
file, and that deviations occur only where the tool is unable to format code
reasonably.
Braces
======
Conditional statements and iteration statements with a single line or
multiple lines of code must be surrounded by braces:
.. code-block:: c
if (condition) {
function_call(
long_variable_name_x,
long_variable_name_y,
long_variable_name_z);
}
This rule applies also to an if-else chain:
.. code-block:: c
if (condition) {
function_call(
long_variable_name_x,
long_variable_name_y,
long_variable_name_z);
} else {
function_call_b();
}
Empty loop statements must use `continue`:
.. code-block:: c
while (condition) {
continue;
}
Operators
=========
When using operators like `sizeof` and `alignof`, where possible use the
value-based version over the type-based version:
.. code-block:: c
int counter;
sizeof(counter); /* Preferred over sizeof(int) */
Operator Precedence
===================
Do not rely on the implicit precedence and associativity of operators. Use
parentheses to make precedence and associativity explicit:
.. code-block:: c
if ((a == 'a') || (x == 'x')) {
do_something();
}
Parentheses around a unary operator and its operand may be omitted:
.. code-block:: c
if (!a && *b) {
do_something();
}
Header Guards
=============
All headers must be wrapped with include guards to prevent accidental multiple
definitions of header contents. The definition name should be the upper-case
file name followed by ``_H``. An example for a file named ``cam_mm.h`` follows:
.. code-block:: c
#ifndef CAM_MM_H
#define CAM_MM_H
(...)
#endif /* CAM_MM_H */
Inclusion Policy
================
The closing ``endif`` statement should be followed directly by a single-line
comment which replicates the full guard name. In long files this helps to
clarify what is being closed.
Macros and Constants
====================
All macro and constant names must be written in upper-case to differentiate
them from functions and non-constants.
Logical groupings of constants should be defined as enumerations with a common
prefix, so that they can be used as parameter types and in constant expressions.
Enumerations that contain a "number of elements" value must use the ``_COUNT``
suffix, and the final enumeration value should include a comma.
.. code-block:: c
enum cam_msg_a2s_id {
CAM_MSG_A2S_ID_INIT = 1,
CAM_MSG_A2S_ID_START,
CAM_MSG_A2S_ID_STOP,
CAM_MSG_A2S_ID_EVENT,
CAM_MSG_A2S_ID_COUNT,
};
void cam_process_msg_id(enum cam_msg_a2s_id id)
{
(...)
}
Symbol Naming
=============
Function, variable, file name and type names must:
* Be written in lower-case
* Have compound words separated by underline characters (``_``)
Avoid using:
* Camel case syntax (e.g. ``criticalAppMonitor``)
* Hungarian notation, encoding types within names (e.g. ``int iSize``)
Loop Indices
============
It is acceptable to use the following common placeholder names for loop indices:
* ``i``
* ``j``
* ``k``
Types
=====
Avoid defining custom types with the ``typedef`` keyword except for opaque
types. Names defined with ``typedef`` must use the ``_t`` suffix.
Comments
========
To ensure a consistent look, the preferred style for single-line comments is to
use the C89 style of paired forward-slashes and asterisks, ending with no
punctuation:
.. code-block:: c
/* A short, single-line comment */
Multi-line comments should follow a similar style, and always end with
punctuation:
.. code-block:: c
/*
* This is a very, very, very, very long multi-line comment where each line
* starts with an asterisk and paragraphs ends with punctation.
*/
Doxygen comments follow only the second style, for consistency in the generated
documentation:
.. code-block:: c
/*!
* \brief Hello, World.
*/
Preprocessor `if 0` is preferred for commenting out blocks of code where it is
necessary to do so, as these can be nested (unlike multi-line comment blocks).
.. code-block:: c
void function_a(int x, int y)
{
(...)
}
#if 0
void function_b(int x, int y)
{
(...)
}
#endif
Prefer functions to function-like macros where possible. Avoid using the
``inline`` keyword, as inlining sites are better-determined by the compiler.
Initialization
==============
When literals require explicit literal initialization, avoid implicit casts by
using the proper integer literal suffix or initializer:
.. code-block:: c
void *p = NULL;
unsigned int u = 0u;
float f = 0.0f;
double d = 0.0;
char c = '\0';
Array and structure initialization should use designated initializers. These
allow elements to be initialized using array indices or structure field names
without a fixed ordering:
.. code-block:: c
uint32_t value_array[3] = {
[2] = 800,
[0] = 675,
};
struct cam_struct x = {
.name = "example",
.value = 100,
};
Doxygen Comments
================
**libcam** APIs are documented using Doxygen comments.
At a minimum:
* All functions and structures must have at least a ``brief`` tag
* All functions must document their parameters (if any) with the ``param`` tag
* Input parameters must use ``param[in]``
* Output parameters must use ``param[out]``
* Input/output parameters must use ``param[in, out]``
* All functions returning a value should use the ``return`` and, optionally, the
``retval`` tag to document their return value
* ``return`` should document what the *type* of the return value represents
* ``retval`` should document what *individual return values* represent
Alignment and indentation:
* Documentation must also obey the 80 column limit
* Multiple lines of documentation on an entry (e.g. details) must be indented
using the equivalent of two 4-space based tabs from the first column (see
example below)
Function documentation example:
.. code-block:: c
/*!
* \brief Retrieve the library version.
*
* \details This function retrieve the current of the library.
*
* \param[out] major Pointer to the major version number.
*
* \param[out] minor Pointer to the minor version number.
*
* \retval 0 The version is retrieved with success.
* \retval -1 Failed to retrieve the library version. The returned major and
* minor are invalid.
*/
int cam_version(unsigned int *major, unsigned int *minor);
Structure documentation example:
.. code-block:: c
/*!
* \brief A structure example.
*
* \details This is an example of a structure for the code style documentation.
*/
struct cam_structure {
/*!
* \brief Example field.
*/
unsigned int example;
};
******
Python
******
Python based tools must follow the `PEP8`_ specification. This is enforced
with the ``pycodestyle`` tool.
Python code must be linted with ``pylint``.
**********************
Sphinx-based Documents
**********************
Sphinx-based documents must use the following style.
Headings
========
The following headings style should be used:
.. code-block:: rst
########################
Heading 1 using overline
########################
************************
Heading 2 using overline
************************
Heading 3
=========
Heading 4
---------
Heading 5
^^^^^^^^^
Heading 6
"""""""""
Code blocks
===========
Use the ``code-block`` directive **and** specify the programming language. As
an example:
.. code-block:: rst
.. code-block:: python
import this
Alignment and Indentation
=========================
Documentation source must obey the 80 column limit.
The indentention must be 2-spaces.