====== Coding style guide ======
This style guide is meant to be loosely adhered to when writing libraries for the Wonderful ecosystem.
Note that this is very much a draft - I'm trying to codify what I learned from the past few years... please remain patient.
===== Naming =====
As everyone downstream will end up using the hardware libraries' API, consistency in naming is among the most important things to pay attention to. Formatting can be fixed for free; naming changes are expensive.
==== Global identifiers ====
Regarding cases:
* Global C function names are written with ''snake_case''. This allows easily distinguishing them from function names in more modern languages on top of the C API, which tend to use ''PascalCase'' or ''camelCase''.
* Global C/C++ macro definitions are written with ''UPPER_SNAKE_CASE''.
* One exception is for macros which serve the role of functions - the line between a ''static inline'' function and a macro can sometimes be very thin.
Regarding names:
* Global identifiers should be prefixed with the name of the library.
* For example, if you're working on ''libws'', a global function name should be ''ws_function(void)'', not ''function(void)''.
* Similarly, for ''libwsx'', the name is ''wsx_function(void)''; even if it also targets the ''ws'' platform, the library is different, so the prefix changes likewise.
* Following from that, categorizing functions should be done prefix-first, but beyond the category of the function, an operation should be written like a sentence.
* For example, ''ws_screen_fill_tiles'' is appropriate, not ''ws_screen_tiles_fill'' or ''ws_fill_screen_tiles''.
* Predicate functions should use the verb ''is''.
* For example, ''ws_system_is_color_active'', not ''ws_system_color_active''.
* Some macros can refer to a type; for readability and to distinguish it from function categories, these should be //suffixed//.
* For example, an I/O port will be referred to as ''WS_DISPLAY_BORDER_PORT'', and a mask for ''%%WS_DISPLAY_BORDER_COLOR(c)%%'' will be referred to as ''WS_DISPLAY_BORDER_COLOR_MASK''.
===== Code style =====
* Braces are always on the same line, and are separated with a space.
* If it doesn't otherwise hurt readability, using no braces for a single-line statement is fine.
void braces_on_the_same_line(int always) {
if (single_line)
no_braces_is_fine;
if (multi_line) {
braces_on_the_same_line(1);
braces_on_the_same_line(2);
}
}
* Pointers are declared with the asterisk ''*'' adjacent to the type name. ''const'' goes before the type name.
const void __far *return_pointer(void __far *my_pointer);
===== Documentation =====
Use [[https://www.doxygen.nl/manual/docblocks.html|Doxygen-compatible]] formatting for all user-facing documentation comments:
* Javadoc-style ''%%/** .. */%%'' blocks for documenting functions, types, macros and/or where larger comment blocks are warranted;
* For one-line comments, such as on enumerated types, ''%%///<%%'' can be used.
* When writing internal header macros/functions that are not meant for the library user, put such code between ''%%/// @cond INTERNAL%%'' and ''%%/// @endcond%%'' blocks.
===== Best practices =====
* Where the size of a variable matters, use ''stdint.h'' and ''stdbool.h'' types (''int16_t'', ''uint32_t'' etc). Where the size of a variable doesn't matter, use standard C types (''int'' and ''unsigned int'').
* For 8-bit platforms, rely on ''stdint.h'' types more often; ''int'' tends to be 16-bit on those platforms, which is slower to process than ''uint8_t''.
* For functions which return a "succeeded" flag, use ''bool''. For functions which return an error code, use ''int'' and return a non-negative value on success or a negative value on failure.
* Prefer ''static inline'' functions over preprocessor macros, where applicable.
===== Target-specific notes =====
==== wswan ====
* We're currently limited to GCC 6.3.0 on this platform; as such, the highest available standard is ''gnu11''.
* The cost of a function call is rather high (5 bytes and 18 cycles of overhead for argument-less functions on ''wswan/medium''), and LTO is not available; as such, using ''static inline'' functions in header files for simple port I/O wrappers and similar tasks is encouraged.
====== References ======
* [[https://www.kernel.org/doc/html/latest/process/coding-style.html|Linux kernel coding style]] - served as a source of inspiration