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 (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 #include /* 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 #include #include /* TI includes */ #include #include /* 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; }