..
 #
 # Critical Application Monitoring (CAM)
 #
 # SPDX-FileCopyrightText: <text>Copyright 2023-2024 Arm Limited
 # and/or its affiliates <open-source-office@arm.com></text>
 #
 # 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: <text>Copyright <years> Arm Limited
  and/or its affiliates <open-source-office@arm.com></text>
  SPDX-License-Identifier: BSD-3-Clause

Where '<years>' 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.