1999-02-09 01:09:47 +00:00
|
|
|
<H2>C Language</H2>
|
|
|
|
|
|
|
|
An ANSI standard C compiler and library are assumed. Feel free to use any
|
|
|
|
ANSI C feature.<P>
|
|
|
|
|
|
|
|
<H2>Warnings</H2>
|
|
|
|
Given a reasonable set of things to warn about (e.g. -W -Wall for gcc), the
|
|
|
|
goal is to compile with no warnings.
|
|
|
|
|
|
|
|
<H2>C Source Code</H2>
|
|
|
|
|
|
|
|
<H3>Copyright</H3>
|
|
|
|
|
|
|
|
All source files should have a copyright. The copyright year(s)
|
|
|
|
should be kept current. The files and the copyright year(s) should be
|
|
|
|
listed in util/copyrights.<P>
|
|
|
|
|
|
|
|
<H3>Line Formatting</H3>
|
|
|
|
<H4>Indentation</H4>
|
|
|
|
Use tabs. Spaces are only allowed when needed to line up a continued
|
|
|
|
expression. In the following example, spaces used for indentation are
|
|
|
|
indicated with "_":
|
|
|
|
<PRE><CODE>
|
|
|
|
printf("this is going to be %s very long %s statement\n",
|
|
|
|
_______"a", "printf");
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H4>Line Length</H4> Lines should not be longer than 80 characters,
|
|
|
|
even if it requires violating the indentation rules to do so.
|
|
|
|
|
|
|
|
<H3>Comments</H3>
|
|
|
|
Comments should be used anytime they improve the readability of the code.<P>
|
|
|
|
|
|
|
|
Comments may be single-line or multiline. A single-line comment should be
|
|
|
|
at the end of the line of there is other text on the line, and should start
|
|
|
|
in the same column as other nearby end-of-line comments. The comment
|
|
|
|
should be at the same indentation level as the text it is referring to.
|
|
|
|
Multiline comments should start with "/*" on a line by itself. Subsequent
|
|
|
|
lines should have " *" lined-up with the "*" above. The end of the comment
|
|
|
|
should be " */" on a line by itself, again with the "*" lined-up with the
|
|
|
|
one above. Comments should start with a capital letter and end with a
|
|
|
|
period.<P>
|
|
|
|
Good:<P>
|
|
|
|
<PRE><CODE>
|
|
|
|
/*
|
|
|
|
* Private variables.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int a /* Description of 'a'. */
|
|
|
|
static int b /* Description of 'b'. */
|
|
|
|
static char * c /* Description of 'c'. */
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
The following lint and lint-like comments should be used where appropriate:
|
|
|
|
<PRE><CODE>
|
|
|
|
/* ARGSUSED */
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
/* NOTREACHED */
|
|
|
|
/* VARARGS */
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H3>.h files</H3>
|
|
|
|
.h files should not rely on other files having been included. .h
|
|
|
|
files should prevent multiple inclusion. The OS is assumed to prevent
|
|
|
|
multiple inclusion of its .h files.<P>
|
|
|
|
.h files that define modules should have a structure like the following:<P>
|
|
|
|
<PRE><CODE>
|
|
|
|
/*
|
|
|
|
* Copyright (C) 1998 Internet Software Consortium.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
|
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
|
|
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ISC_WHATEVER_H
|
|
|
|
#define ISC_WHATEVER_H 1
|
|
|
|
|
|
|
|
/*****
|
|
|
|
***** Module Info
|
|
|
|
*****/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* <Module name here>
|
|
|
|
*
|
|
|
|
* <One line description here>
|
|
|
|
*
|
|
|
|
* <Extended description and notes here>
|
|
|
|
*
|
|
|
|
* MP:
|
|
|
|
* <Information about multiprocessing considerations here, e.g. locking
|
|
|
|
* requirements>
|
|
|
|
*
|
|
|
|
* Reliability:
|
|
|
|
* <Any reliability concerns should be mentioned here>
|
|
|
|
*
|
|
|
|
* Resources:
|
|
|
|
* <A rough guide to how resources are used by this module>
|
|
|
|
*
|
|
|
|
* Security:
|
|
|
|
* <Any security issues are discussed here>
|
|
|
|
*
|
|
|
|
* Standards:
|
|
|
|
* <Any standards relevant to the module are listed here>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/***
|
|
|
|
*** Imports
|
|
|
|
***/
|
|
|
|
|
|
|
|
/* <#includes here> */
|
|
|
|
|
|
|
|
/***
|
|
|
|
*** Types
|
|
|
|
***/
|
|
|
|
|
|
|
|
/* <Type definitions here> */
|
|
|
|
|
|
|
|
/***
|
|
|
|
*** Functions
|
|
|
|
***/
|
|
|
|
|
|
|
|
#endif /* ISC_WHATEVER_H */
|
|
|
|
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H3>C Source</H3>
|
|
|
|
<H4>Including Interfaces (.h files)</H4>
|
|
|
|
The first file to be included must be config.h.
|
|
|
|
Try to include only necessary files, not everything under the
|
|
|
|
sun.<P>
|
|
|
|
Operating-system-specific files should not be included by most modules.<P>
|
|
|
|
Include UNIX "sys" .h files before ordinary C includes.<P>
|
|
|
|
|
|
|
|
<H4>Statements</H4>
|
|
|
|
There should be at most one statement per line.<P>
|
|
|
|
Bad:<P>
|
|
|
|
<PRE><CODE>
|
|
|
|
if (i > 0) {
|
|
|
|
printf("yes\n"); i = 0; j = 0;
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
1999-04-22 12:27:55 +00:00
|
|
|
<H4>Functions</H4>
|
1999-02-09 01:09:47 +00:00
|
|
|
The use of ANSI C function prototypes is required.<P>
|
|
|
|
The return type of the function should be listed on a line by itself when
|
|
|
|
specifying the implementation of the function. The opening curly brace should
|
|
|
|
occur on the same line as the argument list, unless the argument list is
|
|
|
|
more than one line long.<P>
|
|
|
|
Good:<P>
|
1999-11-02 04:08:34 +00:00
|
|
|
<PRE><CODE>
|
1999-02-09 01:09:47 +00:00
|
|
|
static inline void
|
|
|
|
f(int i) {
|
|
|
|
/* whatever */
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
g(int i, /* other args here */
|
|
|
|
int last_argument)
|
|
|
|
{
|
|
|
|
return (i * i);
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H4>Curly Braces</H4> Curly Braces do not get their own indentation.
|
|
|
|
An opening brace does not start a new line. The statements enclosed
|
|
|
|
by the braces should not be on the same line as the opening or closing
|
|
|
|
brace. A closing brace should be the only thing on the line, unless
|
|
|
|
it's part of an else clause.<P>
|
|
|
|
Good:<P>
|
|
|
|
<PRE><CODE>
|
|
|
|
static void
|
|
|
|
f(int i) {
|
|
|
|
if (i > 0) {
|
|
|
|
printf("yes\n");
|
|
|
|
i = 0;
|
|
|
|
} else
|
|
|
|
printf("no\n");
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
Bad:<P>
|
|
|
|
<PRE><CODE>
|
|
|
|
void f(int i)
|
|
|
|
{
|
|
|
|
if(i<0){i=0;printf("was negative\n");}
|
|
|
|
if (i > 0)
|
|
|
|
{
|
|
|
|
printf("yes\n");
|
|
|
|
i = 0;
|
|
|
|
}}
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H4>Spaces</H4>
|
|
|
|
<UL>
|
|
|
|
<LI>Do put a space between operators like '+', '==', etc.
|
|
|
|
<LI>Do put a space after ','.
|
|
|
|
<LI>Do put a space after ';' in a 'for' statement.
|
|
|
|
<LI>Do put a space after 'return', and also parenthesize the return value.
|
|
|
|
</UL>
|
|
|
|
<UL>
|
|
|
|
<LI>Do not put a space between a variable or function name and '(' or '['.
|
|
|
|
<LI>Do not put a space immediately after a '(' or immediately before a ')',
|
|
|
|
unless it improves readability. The same goes for '[' and ']'.
|
|
|
|
<LI>Do not put a space before '++' or '--' when used in
|
|
|
|
post-increment/decrement mode, or after them when used in
|
|
|
|
pre-increment/decrement mode.
|
|
|
|
<LI>Do not put a space before ';' when terminating a statement or in a 'for'
|
|
|
|
statement.
|
|
|
|
<LI>Do not put a space after '*' when used to dereference a pointer, or on
|
|
|
|
either side of '->'.
|
|
|
|
<LI>Do not put a space after '~'.
|
|
|
|
<LI>The '|' operator may either have a space on both sides or it may have no
|
|
|
|
spaces.
|
|
|
|
</UL>
|
|
|
|
|
|
|
|
<H4>Return Values</H4>
|
|
|
|
If a function returns a value, it should be cast to (void) if you don't
|
|
|
|
care what the value is. (Exception for <CODE>printf()</CODE>?)<P>
|
|
|
|
|
|
|
|
All error conditions must be handled.<P>
|
|
|
|
|
|
|
|
Mixing of error status and valid results within a single type should be
|
|
|
|
avoided.<P>
|
|
|
|
Good:
|
|
|
|
<PRE><CODE>
|
|
|
|
os_descriptor_t s;
|
|
|
|
os_result_t result;
|
|
|
|
|
|
|
|
result = os_socket_create(AF_INET, SOCK_STREAM, 0, &s);
|
|
|
|
if (result != OS_R_SUCCESS) {
|
|
|
|
/* Do something about the error. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
Not so good:
|
|
|
|
<PRE><CODE>
|
|
|
|
int s;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Obviously using interfaces like socket() (below) is allowed
|
|
|
|
* since otherwise you couldn't call operating system routines; the
|
|
|
|
* point is not to write more interfaces like them.
|
|
|
|
*/
|
|
|
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (s < 0) {
|
|
|
|
/* Do something about the error using errno. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H4>Integral Types</H4>
|
|
|
|
Careful thought should be given to whether an integral type should be
|
|
|
|
signed or unsigned, and to whether a specific size is required. "int"
|
|
|
|
should be used for generic variables (e.g. iteration counters, array
|
|
|
|
subscripts). Other than for generic variables, if a negative value isn't
|
|
|
|
meaningful, the variable should be unsigned. Assignments and
|
|
|
|
comparisons between signed and unsigned integers should be avoided;
|
|
|
|
suppressing the warnings with casts is not desireable.<P>
|
|
|
|
|
|
|
|
<H4>Casting</H4>
|
|
|
|
Casting should be avoided when possible.<P>
|
|
|
|
|
|
|
|
<H4>Clear Success or Failure</H4>
|
|
|
|
A function should report success or failure, and do so accurately. It
|
|
|
|
should never fail silently. Use of Design by Contract can help here.<P>
|
|
|
|
|
|
|
|
<H4>Testing Bits</H4>
|
|
|
|
Bit testing should be as follows:<P>
|
|
|
|
Good:
|
|
|
|
<PRE><CODE>
|
|
|
|
/* Test if flag set. */
|
|
|
|
if ((flags & FOO) != 0) {
|
|
|
|
|
|
|
|
}
|
|
|
|
/* Test if flag clear. */
|
|
|
|
if ((flags & BAR) == 0) {
|
|
|
|
|
|
|
|
}
|
|
|
|
/* Test if both flags set. */
|
|
|
|
if ((flags & (FOO|BAR)) == (FOO|BAR)) {
|
|
|
|
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
Bad:
|
|
|
|
<PRE><CODE>
|
|
|
|
/* Test if flag set. */
|
|
|
|
if (flags & FOO) {
|
|
|
|
|
|
|
|
}
|
|
|
|
/* Test if flag clear. */
|
|
|
|
if (! (flags & BAR)) {
|
|
|
|
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H4>Pointers</H4>
|
|
|
|
<H5>Null Pointer</H5>
|
|
|
|
The null pointer value should be referred to with "NULL", not with "0".
|
|
|
|
Testing to see whether a pointer is NULL should be explicit.<P>
|
|
|
|
Good:
|
|
|
|
<PRE><CODE>
|
|
|
|
char *c = NULL;
|
|
|
|
|
|
|
|
/* ... */
|
|
|
|
|
|
|
|
if (c == NULL) {
|
|
|
|
/* Do something. */
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H5>Invalidating Pointers</H5>
|
|
|
|
When the data a pointer points to has been freed, or is otherwise no longer
|
|
|
|
valid, the pointer should be set to NULL unless the pointer is part of a
|
|
|
|
structure which is itself going to be freed immediately.<P>
|
|
|
|
Good:
|
|
|
|
<PRE><CODE>
|
|
|
|
char *text;
|
|
|
|
|
|
|
|
/* text is initalized here. */
|
|
|
|
|
|
|
|
free(text);
|
|
|
|
text = NULL;
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H4>Testing for Zero or Non-zero</H4>
|
|
|
|
Explicit testing against zero is required for numeric, non-boolean variables.
|
|
|
|
<P>
|
|
|
|
Good:
|
|
|
|
<PRE><CODE>
|
|
|
|
int i = 10;
|
|
|
|
|
|
|
|
/* ... */
|
|
|
|
|
|
|
|
if (i != 0) {
|
|
|
|
/* Do something. */
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
Bad:
|
|
|
|
<PRE><CODE>
|
|
|
|
int i = 10;
|
|
|
|
|
|
|
|
/* ... */
|
|
|
|
|
|
|
|
if (i) {
|
|
|
|
/* Do something. */
|
|
|
|
}
|
|
|
|
</CODE></PRE>
|
|
|
|
|
|
|
|
<H3>Initialization</H3>
|
|
|
|
When an object is allocated from the heap, all fields in the object must be
|
|
|
|
initialized.<P>
|
|
|
|
|
|
|
|
<H3>Dead Code Pruning</H3>
|
|
|
|
Source which becomes obsolete should be removed, not just disabled with
|
|
|
|
#if 0 ... #endif.<P>
|