OpenOCD
C Style Guide

This page contains guidelines for writing new C source code for the OpenOCD project.

Formatting Guide

  • remove any trailing white space at the end of lines.
  • use TAB characters for indentation; do NOT use spaces.
  • displayed TAB width is 4 characters.
  • use Unix line endings ('\n'); do NOT use DOS endings ('\r\n')
  • limit adjacent empty lines to at most two (2).
  • remove any trailing empty lines at the end of source files
  • do not "comment out" code from the tree nor put it within a block
    #if 0
    ...
    #endif
    otherwise it would never be checked at compile time and when new patches get merged it could be not compilable anymore. Code that is not fully working nor ready for submission should instead be removed entirely (git can retrieve the old version). For exceptional cases that require keeping some unused code, let the compiler check it by putting it in a block
    if (false) {
    /* explain why this code should be kept here */
    ...
    }
  • in a switch statement align the switch with the case label
    switch (dev_id) {
    case 0x0123:
    size = 0x10000;
    break;
    case 0x0412:
    size = 0x20000;
    break;
    default:
    size = 0x40000;
    break;
    }
    size_t size
    Size of the control block search area.
    Definition: rtt/rtt.c:30
  • in an if / then / else statement, if only one of the conditions require curly brackets due to multi-statement block, put the curly brackets also to the other condition
    if (x > 0)
    a = 12 + x;
    else
    a = 24;
    if (x > 0) {
    a = 12 + x;
    } else {
    a = 24;
    x = 0;
    }
  • on if statements where the condition is split among multiple lines, increase the indentation of the condition to prevent it to match to the indentation of the then block due to length of 'if (' being same of the TAB width of 4 characters. Use:
    if (CMD_ARGC < 3
    || CMD_ARGC > 8)
    #define ERROR_COMMAND_SYNTAX_ERROR
    Definition: command.h:402
    #define CMD_ARGC
    Use this macro to access the number of arguments for the command being handled, rather than accessing...
    Definition: command.h:151
    instead of:

Finally, try to avoid lines of code that are longer than 72-80 columns:

  • long lines frequently indicate other style problems:
    • insufficient use of static functions, macros, or temporary variables
    • poor flow-control structure; "inverted" logical tests
  • a few lines may be wider than this limit (typically format strings), but:
    • all C compilers will concatenate series of string constants.
    • all long string constants should be split across multiple lines.
    • do never exceed 120 columns.

Naming Rules

  • most identifiers must use lower-case letters (and digits) only.
    • macros and enumerators must use upper-case letters (and digits) only.
    • OpenOCD identifiers should NEVER use MixedCaps, aka CamelCase.
  • typedef names must end with the '_t' suffix.
    • This should be reserved for types that should be passed by value.
    • Do not mix the typedef keyword with struct.
  • use underline characters between consecutive words in identifiers (e.g. more_than_one_word).

Include Guards

Every header file should have a unique include guard to prevent multiple inclusion. To guarantee uniqueness, an include guard should be based on the filename and the full path in the project source tree.

For the header file src/helper/jim-nvp.h, the include guard would look like this:

#ifndef OPENOCD_HELPER_JIM_NVP_H
#define OPENOCD_HELPER_JIM_NVP_H
/* Your code here. */
#endif /* OPENOCD_HELPER_JIM_NVP_H */

C99 Rules

  • inline functions
  • // comments – in new code, prefer these for single-line comments
  • trailing comma allowed in enum declarations
  • designated initializers ( .field = value )
  • variables declarations should occur at the point of first use
  • new block scopes for selection and iteration statements
  • use malloc() to create dynamic arrays. Do not use alloca or variable length arrays on the stack. non-MMU hosts(uClinux) and pthreads require modest and predictable stack usage.

Type Guidelines

  • use native types (int or unsigned int ) if the type is not important
    • if size matters, use the types from <stdint.h> or <inttypes.h>:
      • int8_t, int16_t, int32_t, or int64_t: signed types of specified size
      • uint8_t, uint16_t, uint32_t, or uint64_t: unsigned types of specified size
      • use the associated printf and scanf formatting strings for these types (e.g. PRId8, PRIx16, SCNu8, ...)
    • do NOT redefine uN types from "types.h"
    • use type target_addr_t for target's address values
    • prefer type unsigned int to type unsigned

Functions

  • static inline functions should be preferred over macros:
    /* do NOT define macro-like functions like this... */
    #define CUBE(x) ((x) * (x) * (x))
    /* instead, define the same expression using a C99 inline function */
    static inline int cube(int x) { return x * x * x; }
  • Functions should be declared static unless required by other modules
    • define static functions before first usage to avoid forward declarations.
  • Functions should have no space between its name and its parameter list:
    int f(int x1, int x2)
    {
    ...
    int y = f(x1, x2 - x1);
    ...
    }
  • Separate assignment and logical test statements. In other words, you should write statements like the following:
    // separate statements should be preferred
    result = foo();
    if (result != ERROR_OK)
    ...
    #define ERROR_OK
    Definition: log.h:164
    More directly, do not combine these kinds of statements:
    // Combined statements should be avoided
    if ((result = foo()) != ERROR_OK)
    return result;
  • Do not compare bool values with true or false but use the value directly
    if (!is_enabled)
    ...
  • Avoid comparing pointers with NULL
    buf = malloc(buf_size);
    if (!buf) {
    LOG_ERROR("Out of memory");
    return ERROR_FAIL;
    }
    #define ERROR_FAIL
    Definition: log.h:170
    #define LOG_ERROR(expr ...)
    Definition: log.h:132

Logging

Logging is intended to provide human-readable information to users. Do not confuse logging with the output of commands. The latter is intended for the result of a command and should be able to be processed by Tcl scripts.

  • Use one of the following functions to generate log messages, never use printf() or similar functions.
    • Use LOG_ERROR() to provide information in case an operation failed in an unrecoverable way. For example, if necessary memory cannot be allocated.
    • Use LOG_WARNING() to inform the user of about an unexpected behavior that can be handled and the intended operation is still be performed. For example, in case a command is deprecated but is nevertheless executed.
    • Use LOG_INFO() to provide insightful or necessary information to the user. For example, features or capabilities of a discovered target.
    • Use LOG_DEBUG() to provide information for troubleshooting. For example, detailed information which makes it easier to debug a specific operation. Try to avoid flooding the log with frequently generated messages. For example, do not use LOG_DEBUG() in operations used for polling the target. Use LOG_DEBUG_IO() for such frequent messages.
    • Use LOG_DEBUG_IO() to provide I/O related information for troubleshooting. For example, details about the communication between OpenOCD and a debug adapter.
  • If the log message is related to a target, use the corresponding LOG_TARGET_xxx() functions.
  • Do not use a period or exclamation mark at the end of a message.