1
0
Fork 0
mirror of https://github.com/tailix/libclayer.git synced 2024-11-27 11:14:54 -05:00
libclayer/CONTRIBUTING.md
2022-12-25 13:00:20 +04:00

164 lines
4.9 KiB
Markdown

Common
------
* Add your name to [COPYING](/COPYING).
* Don't add your name to `AUTHORS` - it's for maintainers.
* Add copyright notice in the beginning of changed files except the headers.
* If you change the behavior (even just fix a bug) of **libkernaux** (stable) or
[libc](/libc), add a record to [ChangeLog](/ChangeLog).
Prohibitions:
* Don't commit binary files
* Don't commit configuration files of your editor or IDE
* Don't use encodings other than ASCII and UTF-8
* Don't use alphabets other than Latin
* Don't use languages other than English
* Don't use tabulations (I don't hate tabs, but people can not use them
properly)
* Don't leave trailing whitespaces
* Don't forget the newline character in the end of files
The following statements are recommendations, but highly encouraged:
* Write documentation
* Write tests
* Keep lines less than 80 characters long for better experience on split screen
### Things to review periodically
* `git grep -i fixme`
* `git grep -i todo`
* `git grep -i cppcheck-suppress`
* `git grep -i rubocop:disable`
### Programming mistakes
* Always check documentation, manuals and specifications
Avoid stupid errors with:
* Manual memory management
* `malloc` may return `NULL`
* Memory leak (forget to `free`)
* Use after `free`/`realloc`
* Double `free`/`realloc`
* `free`ing/`realloc`ating unallocated memory
* Changing the original pointer to the allocated memory (use `const`!)
* `NULL` pointers and `nil`/`None`/whatever objects
* Division by zero
* Pointer arithmetic - consider type size
* Type sizes (like `long` on 32-bit and 64-bit)
* Integer arithmetic overflow
* Bit shift
* Endianness (byte order)
* Data packing
* Data alignment
* Thread safety
* Undefined behavior
* Logical expressions (tautology, whatever)
* Checking for an error (return value, pointer argument, whatever)
* Use of not fully initialized data
* Not reading beyond a buffer, array or string
* The index of the last item, which is less than the buffer size
* Negative indices
* The terminating null character in a string
* Allowed values of arguments
* Possible values of parameters
* Operator precedence
* Default case in switch statements
* Braces (curly brackets) around code blocks
C language
----------
Use **cppcheck**.
* Name regular functions (*not methods*) and variables in lower snake case
(example: `foo_bar`).
* Name macros in upper snake case (example: `FOO_BAR`).
* Name types (*structures, unions, enumerations and type definitions*) in Pascal
case (example: `FooBar`).
* Name nested types in Pascal case and with the prefix of the surrounding type
in Pascal case, separate type names with underscores (example:
`FooBar_CarCdr`).
* Name methods (*functions that belong to a specific type*) in lower snake case
and with the prefix of the type name in Pascal case (example:
`FooBar_car_cdr`).
* Name public (*defined in the headers and exported as symbols*) regular
functions (*not methods*) and variables with the prefix `kernaux_` (example:
`kernaux_foo_bar`).
* Name public (*defined in the headers*) macros with the prefix `KERNAUX_`
(example: `KERNAUX_FOO_BAR`).
* Name public (*defined in the headers*) types with the prefix `KernAux_`
(example: `KernAux_FooBar`).
* Name public (*defined in the headers*) with the prefix `KernAux_` and with the
prefix of the surrounding type, separate type names with underscore (example:
`KernAux_FooBar_CarCdr`).
* Name public (*defined in the headers*) methods with the prefix `KernAux_` and
with the prefix of the type name (example: `KernAux_FooBar_car_cdr`).
* Use postfix `size` for a byte size.
* Use postfix `slen` for C string length without terminating `\0` character
(size - 1).
* Use postfix `count` for a number of elements in an array.
* Create `typedef`s with the names of related `struct`s. Use this name with a
prefix `struct` to declare the data itself, withoth the prefix to declare
a pointer or an array:
```c
typedef struct FooBar { int car; } *FooBar;
static struct FooBar FooBar_create();
static void FooBar FooBar_init(FooBar foobar);
static void FooBar_do_something(FooBar foobar);
// Initialize:
struct FooBar foobar = FooBar_create();
// or
struct FooBar foobar;
FooBar_init(&foobar);
// Use:
FooBar foobar_ptr = &foobar;
FooBar_do_something(&foobar);
```
```c
typedef struct FooBar { int car; } FooBar[1];
static struct FooBar FooBar_create();
static void FooBar FooBar_init(FooBar foobar);
static void FooBar_do_something(FooBar foobar);
// Initialize:
FooBar foobar = { FooBar_create() };
// or
FooBar foobar;
FooBar_init(foobar);
// Use:
FooBar_do_something(foobar);
```
* Mark variables and parameters with `const` if you don't plan to modify them
* Only omit braces (curly brackets) of a block if it's statement is placed on
the same line as conditional statement:
```c
// Good:
if (foo) return bar;
if (foo) {
return bar;
}
// Bad:
if (foo)
return bar;
```