diff options
Diffstat (limited to 'source/libmaple/coding-standard.rst')
-rw-r--r-- | source/libmaple/coding-standard.rst | 422 |
1 files changed, 0 insertions, 422 deletions
diff --git a/source/libmaple/coding-standard.rst b/source/libmaple/coding-standard.rst deleted file mode 100644 index 9ed56cc..0000000 --- a/source/libmaple/coding-standard.rst +++ /dev/null @@ -1,422 +0,0 @@ -.. _libmaple-coding-standard: - -Coding Standard -=============== - -This page documents the coding standard for :ref:`libmaple`. It's -intended as a guide for how you should structure any code you would -like included into the LeafLabs releases of libmaple. - -LeafLabs team members are required to follow these when producing new -code. Community contributors to libmaple are strongly encouraged to -do so; following these rules will greatly increase the probability -that your patches will be folded in. - -In general, follow this guide unless there's a very good reason not -to. Laziness doesn't count as a good reason. Most, if not all, of -these decisions are entirely arbitrary, but it's important for -readability that we be consistent. (If you notice an inconsistency, -you should fix it). - -Note that the file ``.dir-locals.el`` in the libmaple root directory -already ensures that many of these standards are followed by default -in Emacs (but not on Windows, where it would need to be named -``_dir_locals.el``, and no way, man). There's also some elisp -scattered about this file which will provide you additional help. - -Configuration for other editors (vim, etc.) would be nice! - -.. contents:: Contents - :local: - -License -------- - -.. highlight:: scheme - -Put an MIT license at the beginning of the file (look at any of our -source files for an example). Copyright should go either to you or to -LeafLabs, LLC. - -Emacs: if you don't like seeing the license, you should use elide-head -(which will hide it for you). You can use the following:: - - (require 'elide-head) - (setq programming-mode-hooks '(c-mode-hook c++-mode-hook)) - (add-to-list 'elide-head-headers-to-hide - '("The MIT License" . "DEALINGS IN\n [*] THE SOFTWARE")) - (add-to-list 'elide-head-headers-to-hide - '("The MIT License" . "DEALINGS IN THE\n...SOFTWARE")) - (dolist (hook programming-mode-hooks) - (add-hook hook (lambda () (elide-head)))) - -Whitespace ----------- - -TextMate users may find `this bundle -<https://github.com/glennr/uber-glory-tmbundle>`_ useful for -automatically converting tabs to spaces and removing trailing -whitespace at save time. - -- 4 space indents (set in ``.dir-locals.el``). - -- Unix newlines. - -- No tab characters (set in ``.dir-locals.el``). - -- No trailing whitespace. For help getting this (and no tab - characters) done automatically in Emacs, you can use - `code-fascism.el <https://github.com/mbolivar/code-fascism>`_. - -- Files end in exactly one newline. The presence of a newline at EOF - is already done by ``c-require-final-newline`` in recent versions of - Emacs. - -- Exactly two newlines separate source paragraphs (you do separate - your code into paragraphs, don't you?). - -- The first line in a function is non-blank. - -.. highlight:: cpp - -- Exactly one space after ``if``, ``else``, ``for``, and ``while``, - before the following ``{`` or ``(``. One space before ``else``, - after the preceding ``}``. For example:: - - // This is good; we like this: - if (foo) { - while (quux) { - bar(); - } - } else { - baz(); - } - - // THIS IS BAD! DON'T DO THIS: - if(foo){ - while(quux){ - bar(); - } - }else{ - baz(); - } - -- Exactly one space in between binary arithmetic, logical, and - comparison operators and their operands. Examples:: - - // This is good: - int x = a + b * (c - d); - if (x != 0 && a > 7) { - SerialUSB.println(x); - } - - // THIS IS BAD! - int x = a+b*(c-d); - if (x!=0 && a>7) { - SerialUSB.println(x); - } - - // This is good: - uint32 adc_data = ADC1_BASE->DR; - SerialUSB.println(adc_data); - - // THIS IS BAD! - uint32 adc_data = ADC1_BASE -> DR; - SerialUSB . println(adc_data); - -- No space between a unary operator and its operand. Examples:: - - // Good: - x++; - - // BAD! - x ++; - - // Good: - y = -x; - - // BAD! - y = - x; - -- If you need to break up a long line: - - * Prefer to break up long expressions after a binary operator. Example:: - - // Good: - if (some_really_long_conditional_wow_this_really_goes_on_forever || - maybe_something_else_could_happen_too) { - ... - } - - // BAD! - if (some_really_long_conditional_wow_this_really_goes_on_forever - || maybe_something_else_could_happen_too) { - ... - } - - * When breaking up a function's arguments over multiple lines, align - the arguments on subsequent lines with the first argument. - Example:: - - // Good: - return_type value_i_got = function_with_a_really_long_name(argument1, - argument2, - argument3); - - // BAD! - return_type value_i_got = function_with_a_really_long_name(argument1, - argument2, - argument3); - - // BAD! - return_type value_i_got = function_with_a_really_long_name(argument1, - argument2, - argument3); - -- In function invocations, no space in between the function name and - the opening parenthesis. Example:: - - // Good: - SerialUSB.println("Hello, world!"); - - // BAD! - SerialUSB.println ("Hello, world!"); - -- Don't indent C code within a conditionally-compiled ``extern "C"`` - block. Example:: - - // Good: - #ifdef __cplusplus - extern "C"{ - #endif - - void some_c_function(void); - - #ifdef __cplusplus - } // extern "C" - #endif - - // BAD! - #ifdef __cplusplus - extern "C"{ - #endif - - void some_c_function(void); - - #ifdef __cplusplus - } // extern "C" - #endif - - Emacs does the "bad" behavior by default, which can be very - annoying. You can turn this off with :: - - (defun c-mode-inextern-lang-hook () - (setcdr (assq 'inextern-lang c-offsets-alist) '-)) - (add-hook 'c-mode-hook c-mode-inextern-lang-hook) - -Comments --------- - -.. highlight:: c++ - -- Multi-line comments are pretty flexible. Any of these is fine:: - - /* Comment starts here. - * Continued lines have a '*' before them. - * The comment can end after the last line. - */ - - /* Comment starts here. - * The comment can end on the same line. */ - - /* - * You can also place a newline after the opening "/*". - */ - -- Doxygen comments are multi-line comments that begin with ``/**`` - instead. - -- Single-line comments are up to you. - -Braces ------- - -- Mostly `1TBS - <http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS>`_. The - only difference is that the opening brace of a function's definition - occurs exactly one space character after the closing parenthesis in - that function's parameter list. Example:: - - void func(void) { - ... - } - -Naming conventions ------------------- - -We'll handle the usual casing/underscore debate as follows. - -- First, ``Dont_Mix_Like_This``, because ``It_Looks_Really_Ugly``, ok? - [There's been some debate about this, and some exceptions are - already grandfathered in, so in order to settle it, let's call this - a "recommendation" instead of "requirement".] - -- Variables: Use underscores to separate words in C identifiers:: - - int some_example_name; - - User-facing C++ variables should be camel cased - (``thisIsAnExample``, ``boardPWMPins``, etc.), for consistency with - the Arduino style. It's probably a good idea for you to case - non-user facing C++ variables in the C style; this will help - disambiguate what's part of the Wirish API and what's not. - -- Classes: Pascal case. So ``ThisIsAClassName``, but ``thisIsNot``, - ``this_is_not``, and ``Dont_You_DareTryANYTHING_STUPID``. - -- Functions: C functions are all lowercase, and words are separated by - underscores. C++ method names are camel cased. - -- Structs: Usually like variables (``adc_dev``, ``adc_reg_map``, - etc.), but it's not crucial. Don't feel obliged to put ``_t`` at - the end of the type name; we don't. - -- Macros and constants: all caps, separated by underscores. C++ - variables with the ``const`` qualifier generally aren't considered - "constants" for the purposes of this rule; i.e., they are cased - according to the rules for variables. We make an exception for - ``PIN_MAP``, because it's the central Wirish data structure. - -- foo.h gets ``#ifdef``\ 'ed to ``_FOO_H_``. - -- Acronyms: The case of letters in an acronym is determined by the - case of the first letter in the acronym, which is determined by - following the above rules. Examples:: - - // Good: - void usb_func() { ... } - void frob_usb_disc() { ... } - class SomethingUSB { - void usbInit(); - void initUSB(); - }; - - // BAD: - class BadUsb { ... }; // say "GoodUSB" instead - void swizzle_USB_disc() { ... } // say "swizzle_usb_disc" instead - -Documentation -------------- - -- Doxygen comments on every user-facing function and type. - Additionally, individually document the fields and enumerator values - of nontrivial user-facing structs and enums. See any register map - type's definition for an example. - -- For libmaple proper, you don't need comments for each register bit - definition, since that's just repeating information better obtained - by reading ST RM0008. - -- Doxygen comments generally only belong on types, functions, - etc. that are part of the public user-facing API. - - This essentially means that if what you're writing is going to be - documented under http://leaflabs.com/docs/ (i.e., if there's `Sphinx - documentation <http://sphinx.pocoo.org/>`_ for it in the - `leaflabs-docs <https://github.com/leaflabs/leaflabs-docs>`_ - repository), then you need to write Doxygen comments. Further, - those Sphinx docs should use Breathe to pull the Doxygen out. (For - more information on this, see the `leaflabs-docs README - <https://raw.github.com/leaflabs/leaflabs-docs/master/README>`_). - - Because Breathe isn't totally mature yet, you won't always be able - to do this. In these cases, document the code "manually" using the - Sphinx `C and C++ domains - <http://sphinx.pocoo.org/domains.html#the-c-domain>`_. This should - be avoided if at all possible, since it creates a maintenance burden - of documenting things in two places at once, and makes it easier for - documentation to go stale. - - If you do have to document something manually, put a comment in the - source file informing future maintainers about it, so they'll pay - extra attention when making changes. - -- When adding peripheral support, it would be nice if you put - longer-form comments into the libmaple ``notes/`` directory, with a - comment in the corresponding .h file referring to it. See the - :ref:`dac.h <libmaple-dac>` source for an example. - - This lets us keep the source files relatively free of "introductory" - material, while allowing new readers a convenient starting point. - These longer-form notes also have a habit of turning into official, - user-facing documentation (or `wiki <http://wiki.leaflabs.com>`_ - pages). - -- **For libmaple proper**, the convention is to document any - user-facing function at the point where it is defined. In - particular, this means you should document an externally-linked - function defined in a .c file in that .c file, not in the header - file where it is declared to the user. - - **For Wirish**, the convention is to put the documentation in the - header file where the function is declared. - -General Formatting ------------------- - -.. highlight:: scheme - -- Keep it 80-column clean. - - Emacs users: this means that the largest column number is 79. You - should turn on column number mode to help you out:: - - (column-number-mode 1) - - You can get more help from `lineker-mode - <http://www.helsinki.fi/~sjpaavol/programs/lineker.el>`_. Just put - lineker.el somewhere in your load-path, and:: - - (require 'lineker) - (dolist (hook '(c-mode-hook c++-mode-hook)) - (add-hook hook (lambda () (lineker-mode 1)))) - -.. highlight:: cpp - -Language Features ------------------ - -In libmaple proper, aim for C99 compatibility. Some GCC extensions -are OK, but `don't get crazy <http://www.youtube.com/watch?v=jZkdcYlOn5M>`_. - -Explicitly approved GCC extensions: - - * `asm volatile <http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html>`_ - - * `Nested functions <http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html>`_ - -In Wirish, generally be very conservative when using C++ features that -aren't part of C. We are forced to use C++ for Arduino compatibility -(and the general Arduino style of conflating objects and libraries), -but it's an angry beast, and we don't want to provoke it. **The -mantra is "C with classes"**. - -Explicitly approved C++ features: - - * Initializers that aren't constant; e.g. the ``gpio_dev*`` values - in a ``PIN_MAP``. - - * Default arguments: e.g., the timeout argument in - :ref:`lang-waitforbuttonpress`. - -Explicitly forbidden C++ features: - - * Templates - -Conditionally allowed C++ features: - - * Operator overloading: Never allowed when it's just for style. - Probably fine when you're implementing a class that models a - mathematical structure, and you'd like to implement - e.g. ``operator+()``. - |