aboutsummaryrefslogtreecommitdiffstats
path: root/notes
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2011-04-08 19:35:21 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2011-04-08 19:47:11 -0400
commit79d1ee686324b92036792986c733f733345c38fb (patch)
tree56f3e35298c59be57f7faab93f09089e10986c6f /notes
parent479601b98c888f863f54dc53b85c29893ae4a4e7 (diff)
downloadlibrambutan-79d1ee686324b92036792986c733f733345c38fb.tar.gz
librambutan-79d1ee686324b92036792986c733f733345c38fb.zip
Coding standard updates.
Added some content, converted document to .rst.
Diffstat (limited to 'notes')
-rw-r--r--notes/coding_standard.rst (renamed from notes/coding_standard.txt)264
1 files changed, 201 insertions, 63 deletions
diff --git a/notes/coding_standard.txt b/notes/coding_standard.rst
index 5b258f7..1deed03 100644
--- a/notes/coding_standard.txt
+++ b/notes/coding_standard.rst
@@ -13,11 +13,11 @@ not. You being lazy 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.
-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.
+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.
Vim customizations to do the same thing would be nice (hint, hint)!
@@ -28,8 +28,10 @@ License
source files for an example). Copyright should go either to you or
to LeafLabs, LLC.
+.. highlight:: scheme
+
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:
+ 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))
@@ -43,23 +45,23 @@ License
Whitespace/Indentation
----------------------
-- 4 space indents. [Set in .dir-locals.el]
+- 4 space indents. [Set in ``.dir-locals.el``]
- Unix newlines. [Some exceptions are currently grandfathered in;
these will go away in time.]
-- No tab characters. [Set in .dir-locals.el]
+- 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 this:
- http://github.com/mbolivar/code-fascism
+ http://github.com/mbolivar/code-fascism
- I hear tell you can get something similar in vim; ask around, I
+ I hear tell you can get something similar in Vim; ask around, I
guess.
- 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
+ is already done by ``c-require-final-newline`` in recent versions of
Emacs.]
- Exactly two newlines separate source paragraphs (you do separate
@@ -67,19 +69,152 @@ Whitespace/Indentation
- The first line in a function is non-blank.
-- Don't indent C code within a conditionally-compiled extern "C"
- block. Emacs does this by default, which can be very annoying; you
- can turn this behavior off with
+.. highlight:: cpp
- (defun c-mode-inextern-lang-hook ()
- (setcdr (assq 'inextern-lang c-offsets-alist) '-))
+- 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, except for the . and ->
+ operators. 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);
- (add-hook 'c-mode-hook c-mode-inextern-lang-hook)
+- 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
+
+.. highlight:: scheme
+
+ 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
--------
-- Multi-line comments are pretty flexible. Any of these is fine:
+.. highlight:: c++
+
+- Multi-line comments are pretty flexible. Any of these is fine::
/* Comment starts here.
* Continued lines have a '*' before them.
@@ -93,15 +228,16 @@ Comments
* You can also place a newline after the opening "/*".
*/
-- Doxygen comments are multi-line comments that begin with /** instead.
+- Doxygen comments are multi-line comments that begin with ``/**``
+ instead.
-- Single-line comments on the same line are // in C++. (That's OK in C
- as well).
+- Single-line comments on the same line are ``//`` in C++. (That's OK
+ in C as well).
-- Single-line comments on their own source line should be /* */ in C,
- but can also be // in C++. In Emacs, you can use M-;
- (comment-dwim), and it'll Do What You Mean. This isn't of great
- importance.
+- Single-line comments on their own source line should be ``/* */`` in
+ C, but can also be ``//`` in C++. (This isn't of great importance).
+ In Emacs, you can use M-; (comment-dwim), and it'll Do What You
+ Mean.
Braces
------
@@ -112,7 +248,7 @@ Braces
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:
+ parenthesis in that function's parameter list. Example::
void func(void) {
...
@@ -124,66 +260,64 @@ Naming conventions
There's always a fight about upper and lower case vs. underscores.
We'll handle this as follows.
-- First, Dont_Mix_Like_This, because It_Looks_Really_Ugly, ok?
+- 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:
+- 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.
+ 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 like I said, Dont_You_DareTryANYTHING_STUPID.
+- Classes: Pascal case. So ``ThisIsAClassName``, but ``thisIsNot``,
+ ``this_is_not``, and like I said,
+ ``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.
+- 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
+ 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.
+ ``PIN_MAP``, because it's the central Wirish data structure.
-- foo.h gets #ifdef'ed to _FOO_H_.
+- 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:
+ following the above rules. Examples::
+ // Good:
void usb_func() { ... }
-
void frob_usb_disc() { ... }
-
class SomethingUSB {
void usbInit();
void initUSB();
};
- DON'T do this:
-
+ // BAD:
class BadUsb { ... }; // say "GoodUSB" instead
-
void swizzle_USB_disc() { ... } // say "swizzle_usb_disc" instead
Documentation
-------------
-- You must document your code. At a bare minimum, this means Doxygen
- comments on every user-facing function and type. Additionally, you
- need to individually document the fields and enumerator values of
- structs and enums. See any register map type's definition for an
- example.
+- You **must** document your code. At a bare minimum, this means
+ Doxygen comments on every user-facing function and type.
+ Additionally, you need to individually document the fields and
+ enumerator values of ``struct``\ s and ``enum``\ s. See any
+ register map type's definition for an example.
- For libmaple proper, you don't need comments for each register bit
definition (for now).
@@ -206,14 +340,15 @@ Documentation
source file informing future maintainers about it, so they'll pay
extra attention when making changes.
-- For complicated peripherals, 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 libmaple/dac.h for an
- example.
+- When adding peripheral support, it would be nice if you put
+ longer-form comments into the /notes/ directory, with a comment in
+ the corresponding .h file referring to it. See /libmaple/dac.h for
+ an example.
- This lets us keep the source files relatively clean while still
- allowing new readers to have a starting point. These longer-form
- notes also have a habit of turning into user-facing documentation.
+ 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
+ user-facing documentation.
- For libmaple proper (the pure C library under libmaple/); the
convention is to document any user-facing function at the point where
@@ -227,6 +362,8 @@ General Formatting
- Keep it 80-column clean. That means Emacs says the largest column
number=79. You should turn on column number mode to help you out:
+.. highlight:: scheme
+
(column-number-mode 1)
You can get more help from lineker-mode:
@@ -265,11 +402,11 @@ Language Features and Compiler Extensions
- Explicitly approved C++ features:
- * Initializers that aren't constant; e.g. the gpio_dev* values in
- PIN_MAPs.
+ * Initializers that aren't constant; e.g. the ``gpio_dev*`` values
+ in a ``PIN_MAP``.
* Default arguments: e.g., the timeout argument defaulting to 0
- (meaning to wait forever) in waitForButtonPress().
+ (meaning to wait forever) in ``waitForButtonPress()``.
- Explicitly forbidden C++ features:
@@ -281,4 +418,5 @@ Language Features and Compiler Extensions
* Operator overloading: Never allowed when it's just for style.
Potentially allowed when you're implementing a class that models a
- mathematical structure, and you'd like to implement e.g. operator+().
+ mathematical structure, and you'd like to implement
+ e.g. ``operator+()``.