Files
OpenCellular/firmware/ec/coding_style_guide
2018-10-01 09:56:42 -07:00

370 lines
10 KiB
Plaintext

OpenCellular Coding Style
=========================
We follow Linux Kernel coding style with following exceptions.
Exceptions:
----------
o 4-space indentation
o Typedef enums and structs
o indent case labels
switch (suffix) {
case 'G':
case 'g':
mem <<= 30;
break;
case 'M':
case 'm':
mem <<= 20;
break;
case 'K':
case 'k':
mem <<= 10;
/* fall through */
default:
break;
}
Additions:
---------
o Non-public functions (functions not exported in header for use by other
modules) should be static
o Unless absolutely necessary, global variables within a module should be static
o Avoid using forward declarations, just #include headers when possible
o Static variables of the form s_variableName
o Non-static functions of the form ModuleName_functionName()
o File names
o C and header files in same directory
o ModuleName.c/h
o All directory names should be lowercase, with underscores added as
needed to improve readability (e.g. my_complex_directory/Foo.h)
o Hex values are upper-case: 0xFB
o Unless size doesn't matter, use fixed-width types defined in <stdint.h>
(uint32_t, int8_t, etc.)
o Enums
o ALL_CAPS, start with enum name (within reason) for namespacing/readability
typedef enum SbdFlowControl {
SBD_FLOW_CONTROL_DISABLED = 0,
SBD_FLOW_CONTROL_HW = 3,
SBD_FLOW_CONTROL_SW = 4,
SBD_FLOW_CONTROL_ALL = 6
} SbdFlowControl;
typedef enum AtLineType {
AT_LINE_TYPE_RESPONSE = 0,
AT_LINE_TYPE_CMD_ECHO,
COUNT_AT_LINE_TYPE
} AtLineType;
o #includes should be in alphabetical order & logically separated:
/* Module header[s] */
/* stdlib headers */
/* TI includes */
/* OC includes */
o Wrap functions like this:
ReturnType ReallyLongFunctionName(Type par_name1, Type par_name2,
Type par_name3)
{
DoSomething();
...
}
ReturnType ReallyReallyReallyLongFunctionNameThatJustWillNotFit(
Type par_name1, /* double indent */
Type par_name2,
Type par_name3)
{
DoSomething(); /* regular indent */
...
}
o No spaces after end of line
o No blank lines at the end of file
o Each file should have description of what it does, which function it contains
etc.
o Each function should describe what operation it execute on the parameters and
what it returns. If there are any parameter overloaded, specify it clearly.
o No dead code.
o Function shouldn't be more than one page.
o Central exiting of function
o Use /* */ for comments. Multiple lines:
/*
*
*/
o MACROS are NOT to define functions. MACROS shouldn't effect control or effect
registers or changes the system states.
Sample Code:
-----------
ExampleModule.h
/*
* Copyright 2004-present Facebook. All Rights Reserved.
*
* See Canonical Style Documents at:
*
* TODO: reference style document
*
* Example header that demonstrates our current C style. The goal of this
* code, while nonsensical, is to show a visual example of as many of our
* style rules/guidelines as possible.
*
* Note the #include order: stdlib includes, TI includes, then OpenCellular
* includes in quotes (""). Each group should be in alphabetical order.
* Additionally, we only want to include the headers necessary for the
* interfaces/structs/enums in the header, everything else should be in the
* source file
*/
/* TODO: what do we want to do for #include guards? #pragma once doesn't have
* namespacing issues and is generally faster, but not guaranteed to be portable
*/
#ifndef EXAMPLEMODULE_H_
#define EXAMPLEMODULE_H_
/* stdlib includes */
#include <stdbool.h>
#include <stdint.h>
/* OC includes */
#include "some_project_folder/SomeDependency.h"
/*
* Initializes the module and stuff
*/
void ExampleModule_init(void);
/*
* Takes lots of arguments, but doesn't do much that's useful with them.
*
* @param count an integer input (by value)
* @param value an enum input (by value)
* @param name a string input (by const-ref)
* @param outVal output integer arg (by pointer)
*
* @return true if function succeeds, false otherwise
*/
bool ExampleModule_funcWithManyArgs(int64_t count,
EnumType value,
const char *name,
uint32_t *outVal);
/*
* Another useless function
*
* @param param1 first example integer (by value)
* @param param2 second example integer (by value)
* @param param3 third example integer (by const-ref)
*/
void ExampleModule_methodThatHasAReallyLongNameOhCrapImRunningOutOfSpace(
int param1,
bool param2,
const uint32_t *param3);
#endif /* EXAMPLEMODULE_H_ */
ExampleModule.c
/*
* Copyright 2004-present Facebook. All Rights Reserved.
*
* See additional comments in: ExampleModule.h
*
* Note the #include order: First our related .h file, then the same
* order as we'd do elsewhere (see ExampleModule.h).
*
* This file is formatted with clang-format -i
*/
#include "ExampleModule.h"
/* stdlib includes */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/* TI includes */
#include <driverlib/I2C.h>
#include <driverlib/UART.h>
/* OC includes */
#include "drivers/Power.h"
#include "drivers/Rf.h"
#include "helpers/Memory.h"
#include "helpers/Array.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef enum SampleState {
SAMPLE_STATE_INIT,
SAMPLE_STATE_RUN,
SAMPLE_STATE_IDK,
COUNT_SAMPLE_STATE
} SampleState;
typedef struct UselessConfig {
uint32_t someInt; /*!< Sample comment on member */
int8_t otherValue; /*!< This looks important */
SampleState state; /*!< All your base are belong to us */
struct UselessConfig *next; /*!< Pointer to next item in list */
} UselessConfig;
static SampleState s_myUselessConfig = {
.someInt = 5,
.state = SAMPLE_STATE_INIT
};
static SampleState s_simpleInitSample = { .otherValue = 2 };
static uint32_t s_someStaticVariable;
/* Array Initializer List Example */
static const uint32_t sampleTable[COUNT_SAMPLE_STATE] = {
[SAMPLE_STATE_INIT] = 6,
[SAMPLE_STATE_RUN] = 42,
[SAMPLE_STATE_IDK ] = 0xFACEB00C
};
static const uint8_t anotherArray[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
0x07, 0x08, 0x09, 0x0A, 0x0B };
/* TODO: How do we want to comment on functions? Having a full header block
* might be a bit overkill since we're planning on doing doxygen comments in
* the header. Some sort of comment to make it easier to see the beginning of
* new functions might be nice though. Not sure how we want to document static
* functions either - probably don't need to be as strict as for public
* functions
*/
void ExampleModule_init(void)
{
s_myUselessConfig.state = SAMPLE_STATE_RUN;
}
/*******************************************************************************
* This additional comment is not in the javadoc style, as it's supposed to
* describe more concrete implementation details. Any comments that may be
* useful to the class API "customer" (as opposed to someone who might modify
* this class) should instead be in JavaDoc style in ExampleCode.h.
******************************************************************************/
/* TODO: should this be MapLookup instead? */
static uint32_t mapLookup(SampleState state, bool uselessParam)
{
if (state < COUNT_SAMPLE_STATE) {
return sampleTable[state];
}
return -1;
}
const uin32_t ExampleModule_methodThatHasALongNameOhCrapImRunningOutOfSpace(
int param1,
bool param2,
const uint32_t *param3)
{
return;
}
/* TODO: not sure for sure how we want to do wrapping parameters. I'm on the
* fence between this style (FB & Google) vs. what I wrote above in the document
*/
bool ExampleModule_funcWithManyArgs(int64_t count,
EnumType value,
const char *name,
uint32_t *outVal)
{
/*
* The body of this function is used to demonstrate common code constructs
* so that the indentation, braces, and spacing styles for them are
* immediately apparent.
*/
/*
* This section demonstrates different kinds of if() blocks, including
* long/short if() blocks, complicated if() expressions, and validity
* checks on pointer/handle variables.
*/
if (count < 0) {
++count;
} else if (count == 0) {
--count;
} else {
count *= 2;
}
if (strlen(name) < 20 &&
!strcmp(name, "some string that I made up") &&
(count < 0 || count > 5)) {
*outVal += count;
}
if (name) {
count += strlen(name);
}
int64_t *realPtr = NULL;
if (!realPtr) {
realPtr = malloc(sizeof(*realPtr));
}
/* This section demonstrates looping constructs. */
for (int64_t i = 0; i < count; ++i) {
*outVal *= 2;
}
int i = 10;
while (i > 0) {
--i;
}
do {
++i;
} while (i <= 10);
/*
* This section demonstrates formatting for switch statments
*/
switch (s_myUselessConfig.state) {
case SAMPLE_STATE_INIT:
s_myUselessConfig.state = SAMPLE_STATE_RUN;
break;
case SAMPLE_STATE_RUN: {
uint32_t i = s_someStaticVariable - 1;
printf("Doing stuff %d", i);
break;
}
case SAMPLE_STATE_IDK:
default:
break;
}
/*
* This section demonstrates formatting for basic expressions, operators,
* and initializations.
*/
char s[] = "startValue";
size_t someSize = sizeof(*realPtr);
int val = count / 2;
count = (count + val) & ((val << 3) + count * val);
uint32_t *samplePtr = &s_someStaticVariable;
SampleState zeroInitializedStruct = {};
/* Multiple variables of same type */
/* TODO: allow multiple vars on one line? eg. int var1, var2, var3 */
int var1;
int *var2;
int *var3;
var1 = 2;
var2 = &var1;
var3 = var2;
return true;
}