Coding guidelines
Last update: 2004-12-18
Copyright © 2004 Salvatore Isaja
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included by reference.
Although I'm pretty against to "coding conventions", it seems to me reasonable to point out a few guidelines to uniform the FD32 source code appearance in order to make the code more easily readable and maintenable. Luca and I have been using most of them for a long time without any explicit agreement, but these informations may be useful to new contributors.
Pay attention to TAB characters
...as different editors handle them differently, for example using different TAB sizes, with unexpected indentation misalignments. Please use TAB characters only if the result is not corrupted when using different TAB sizes. For example, feel free to use them for indentation levels in your code, but use spaces if you want to align some text to something in the preceding line.
Use lower case file names
The CVS repository is hosted by a Linux server, where file names are
case sensitive. Also, most of us work on a Linux system. Having all names in lower case
makes it easier to handle them. Some exceptions could be Makefiles (with
capital first letter) and README.txt files (capital name), as such names are
displayed on top of a Linux directory listing.
If you use both DOS or Windows 9x/ME and Windows NT/2000/XP with a FAT file system pay attention to 8.3 names: the former display them in upper case, the latter in lower case.
Use the indentation and naming styles you like best
...if you write your source file from scratch or make big modifications to existing files. But if you edit or patch an existing file, please keep the original style, in order to keep a consistent aspect of the code.
Comment your code
Place a comment before each function, where you mention what the function performs, a description of input and output data (if not obvious) and possible return values. Also comment key parts of your code, as well as global variable definitions and data types declarations. Such comments are intended to help yourself and other developers to read, maintain or simply use properly your code.
Make a good use of predefined data types
Being FD32 a 32-bit operating system, built with a 32-bit compiler, int is
supposed to be a 32-bit signed integer, while unsigned is supposed
to be a 32-bit unsigned integer. If size does matter, use types defined in
hw-data.h, that are: BYTE,
WORD, DWORD and QWORD (or DWORDLONG)
for unsigned integers, and CHAR, SHORT,
LONG and LONGLONG (or INT64) for signed
integers.
Although char is usually signed, please use char only
if the sign does not matter, like for text strings. If the sign does matter,
use BYTE or CHAR instead. Use unsigned integers when
they do the work (for not negative values like indices). Finally, we are currently
considering to switch to ISO C99 types (int??_t and uint??_t from
stdint.h).
Be consistent with return values
Many FD32 functions return an int. A negative
value is considered to report an error condition, when the function is aborted.
Usually the successful completion of a function is reported by a return value
of zero. However if your function has to report more successful completion conditions,
use not negative values for them.
FD32 error codes (defined in errors.h) are negative
because they are or'ed with 0x80000000: in this way it is possible
to convert a FD32 32-bit negative error code to a DOS 16-bit positive error code
by casting the value to a WORD. We are currently considering to
switch to standard errno names and values.
Always check return values
When you call a function which can fail returning an error condition, always check the return value for error, and handle error conditions appropriately. This includes error propagation and safe abortion of your processing.
Use mnemonic names for constants and magic numbers
...declared with the #define directive, as they improve the code
readability and allow developers to work on a single point if maintenance on the
value is required. It is fairly standard to name those constants using only
CAPITAL_LETTERS.
Use enumerated types
If you have data that can assume only a limited range of values, including flags,
use an enum instead of a set of #defines.
Enumerated types allow the compiler to be smarter in checking what you are doing with
such values (for example, in a switch statement), possibly avoiding bugs.
Moreover enumerated types are visible as mnemonic names in a debugger.
Give to your symbols unique names
FD32 modules, drivers and native applications are dynamically linked with the
kernel at run time. In order to avoid polluting the global name space, prefix your global
symbols (function, variable and type names) with the name of the module you are developing.
For example, all FAT Driver's public functions have a "fat_"
prefix to avoid possible conflicting names in the global name space. It is common to
name public FD32 functions as fd32_<functionname> and
FD32 data types as fd32_<typename>_t. Feel free to use naming
convention you prefer for your internal functions, variables and types.
Define your internal symbols as static
If you don't need a symbol (function or variable name) to be
used outside a source file, declare it as static. Doing this lets you to use
shorter names, because the module prefix is not required, without polluting the
global name space. Also, don't put internal types declarations in public header
files.