====== 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