mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 18:19:42 +00:00
561 lines
17 KiB
HTML
561 lines
17 KiB
HTML
<!--
|
|
- Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
-
|
|
- This Source Code Form is subject to the terms of the Mozilla Public
|
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
-
|
|
- See the COPYRIGHT file distributed with this work for additional
|
|
- information regarding copyright ownership.
|
|
-->
|
|
|
|
<!-- $Id: coding.html,v 1.22 2007/06/19 23:47:13 tbox Exp $ -->
|
|
|
|
<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>Vertical Whitespace</H4>
|
|
Vertical whitespace is also encouraged for improved code legibility by
|
|
grouping closely related statements and then separating them with a
|
|
single empty line. There should not, however, be more than one empty
|
|
adjacent line anywhere.
|
|
|
|
<H4>Line Length</H4>
|
|
Lines should not be longer than 79 characters, even if it requires
|
|
violating the indentation rules to do so. Since ANSI is assumed, the
|
|
best way to deal with strings that extend past column 79 is to break
|
|
them into two or more sections separated from each other by a newline
|
|
and indentation:
|
|
|
|
<PRE><CODE>
|
|
puts("This string got very far to the "
|
|
"left and wrapped. ANSI catenation "
|
|
"rules will turn this into one "
|
|
"long string.");
|
|
</CODE></PRE>
|
|
|
|
<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 if 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. Note that <isc/lang.h> should be included by any public
|
|
header file to get the ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS
|
|
macros used so the correct name-mangling happens for function
|
|
declarations when C++ programs include the file. <isc/lang.h> should
|
|
be included for private header files or for public files that do not
|
|
declare any functions.<P>
|
|
<PRE><CODE>
|
|
/*
|
|
* Copyright (C) 1996-2016 Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#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. */
|
|
#include <isc/lang.h>
|
|
|
|
/***
|
|
*** Types
|
|
***/
|
|
|
|
/* (Type definitions here.) */
|
|
|
|
/***
|
|
*** Functions
|
|
***/
|
|
ISC_LANG_BEGINDECLS
|
|
/* (Function declarations here, with full prototypes.) */
|
|
ISC_LANG_ENDDECLS
|
|
|
|
#endif /* ISC_WHATEVER_H */
|
|
|
|
</CODE></PRE>
|
|
|
|
<H3>C Source</H3>
|
|
<H4>Including Interfaces (.h files)</H4>
|
|
The first file to be included in a C source file must be config.h.
|
|
The config.h file must never be included by any public header file
|
|
(that is, any header file that will be installed by "make install").
|
|
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. The comma operator
|
|
should not be used to form compound statements.<P>
|
|
Bad:<P>
|
|
<PRE><CODE>
|
|
if (i > 0) {
|
|
printf("yes\n"); i = 0; j = 0;
|
|
x = 4, y *= 2;
|
|
}
|
|
</CODE></PRE>
|
|
<H4>Functions</H4>
|
|
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>
|
|
<PRE><CODE>
|
|
static inline void
|
|
f(int i) {
|
|
/* whatever */
|
|
}
|
|
|
|
int
|
|
g(int i, /* other args here */
|
|
int last_argument)
|
|
{
|
|
return (i * i);
|
|
}
|
|
</CODE></PRE>
|
|
|
|
To suppress compiler warnings, unused function arguments are declared
|
|
using the <CODE>UNUSED()</CODE> macro.<P>
|
|
|
|
In the function body, local variable declarations are followed by any
|
|
<CODE>REQUIRE()</CODE>s, <CODE>UNUSED()</CODE> declarations, and other
|
|
code, in this order. These sections are separated by blank lines.<P>
|
|
|
|
<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>
|
|
|
|
Generally speaking, when a control statement (<CODE>if, for</CODE> or
|
|
<CODE>while</CODE>) has only a single action associated with it, then no
|
|
bracing is used around the statement. Exceptions include when the
|
|
compiler would complain about an ambiguous else clause, or when extra
|
|
bracing improves the readability (a judgement call biased toward not
|
|
having the braces).<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 after the "sizeof" operator name, and also
|
|
parenthesize its argument, as in <CODE>malloc(4 * sizeof(long))</CODE>.
|
|
<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.
|
|
<LI>Do not put a space after a cast.
|
|
</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, except for <CODE>printf</CODE> and its variants,
|
|
<CODE>fputc</CODE>, <CODE>fwrite</CODE> (when writing text),
|
|
<CODE>fflush</CODE>,
|
|
<CODE>memcpy</CODE>, <CODE>memmove</CODE>, <CODE>memset</CODE>,
|
|
<CODE>strcpy</CODE>, <CODE>strncpy</CODE>, and <CODE>strcat</CODE>.
|
|
<P>
|
|
|
|
Certain functions return values or not depending on the operating
|
|
system or even compiler flags; these include
|
|
these include <CODE>openlog</CODE> and <CODE>srandom</CODE>.
|
|
The return value of these should not be used nor cast to (void).
|
|
<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. When it is necessary, there
|
|
should be no space between the cast and what is being cast.<P>
|
|
|
|
Bad (obviously for more than one reason ...):
|
|
<PRE><CODE>
|
|
(void) malloc(SMBUF);
|
|
</CODE></PRE>
|
|
|
|
<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>
|
|
|
|
When a function is designed to return results to the caller by
|
|
assigning to caller variables through pointer arguments, it should
|
|
perform the assignment only if it succeeds and leave the variables
|
|
unmodified if it fails.<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 initialized 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>
|
|
|
|
<H4>The Ternary Operator</H4>
|
|
The ?: operator should mostly be avoided. It is tolerated when
|
|
deciding what value to pass as a parameter to a function, such as
|
|
frequently happens with printf, and also when a simple (non-compound)
|
|
value is being used in assignment or as part of a calculation.
|
|
In particular, using the ternary operator to specify a return value is
|
|
verboten.<P>
|
|
|
|
Good:
|
|
<PRE><CODE>
|
|
printf("%c is%s a number.\n", c, isdigit(c) ? "" " NOT");
|
|
l = (l1 < l2) ? l1 : l2;
|
|
if (gp.length + (go < 16384 ? 2 : 3) >= name->length) {
|
|
...
|
|
}
|
|
</CODE></PRE>
|
|
|
|
Bad:
|
|
<PRE><CODE>
|
|
return (success ? ISC_R_SUCESS : ISC_R_FAILURE);
|
|
</CODE></PRE>
|
|
|
|
<H4>Assignment in Parameters</H4>
|
|
Variables should not have their values assigned or changed when being
|
|
passed as parameters, except perhaps for the increment and decrement
|
|
operators.<P>
|
|
|
|
Bad:
|
|
<PRE><CODE>
|
|
malloc(size = 20);
|
|
</CODE></PRE>
|
|
|
|
Ok:
|
|
<PRE><CODE>
|
|
fputc(c++, stdout);
|
|
</CODE></PRE>
|
|
|
|
<H3>Namespace</H3>
|
|
<H4>Public Interfaces</H4>
|
|
All public interfaces to functions, macros, typedefs, and
|
|
variables provided by the library, should use names of the form
|
|
{library}_{module}_{what}, such as:
|
|
<PRE><CODE>
|
|
isc_buffer_t /* typedef */
|
|
dns_name_setbuffer(name, buffer) /* function */
|
|
ISC_LIST_HEAD(list) /* macro */
|
|
isc_commandline_argument /* variable */
|
|
</CODE></PRE>
|
|
however, structures which are typedef'd generally have the name of the
|
|
typedef sans the final _t:
|
|
<PRE><CODE>
|
|
struct dns_rbtnode {
|
|
/* ... members ... */
|
|
}
|
|
</CODE></PRE>
|
|
Generally speaking macros are defined with all capital letters, but
|
|
this is not universally consistent (eg, numerous isc_buffer_{foo}
|
|
macros).<P>
|
|
The {module} and {what} segments of the name do not have underscores
|
|
separating natural word elements, as demonstrated in
|
|
isc_commandline_argument and dns_name_setbuffer above. The {module}
|
|
part is usually the same as the basename of the source file, but
|
|
sometimes other {module} interfaces appear within one file, such as
|
|
dns_label_* interfaces in lib/dns/name.c. However, in the public
|
|
libraries the file name must be the same as some module interface
|
|
provided by the file; e.g., dns_rbt_* interfaces would not be declared
|
|
in a file named redblack.c (in lieu of any other dns_redblack_*
|
|
interfaces in the file).<P>
|
|
|
|
The one notable exception to this naming rule is the interfaces
|
|
provided by <isc/util.h>. There's a large caveat associated with the
|
|
public description of this file that it is hazardous to use because it
|
|
pollutes the general namespace.<P>
|
|
|
|
<H4>Shared Private Interfaces</H4>
|
|
When a module provides an interface for internal use by other modules
|
|
in the library, it should use the same naming convention
|
|
described for the public interfaces, except {library} and {module}
|
|
are separated by a double-underscore. This indicates that the name is
|
|
internal, its API is not as formal as the public API, and thus it
|
|
might change without any sort of notice.
|
|
|
|
<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>
|
|
|
|
<H3>Log messages</H3>
|
|
|
|
Error and warning messages should be logged through the logging
|
|
system. Debugging printfs may be used during development, but
|
|
must be removed when the debugging is finished. The
|
|
<CODE>UNEXPECTED_ERROR()</CODE> macro is obsolete and
|
|
should not be used in new code.<P>
|
|
|
|
Log messages do not start with a capital letter, nor do they end
|
|
in a period.<P>
|
|
|
|
When variable text such as a file name or domain name occurs
|
|
as part of an English phrase, it should be enclosed in single
|
|
quotes, as in <CODE>"zone '%s' is lame"</CODE>.<P>
|
|
|
|
When the variable text forms a separate phrase, such as when it
|
|
separated from the rest of the message by a colon, it can be left
|
|
unquoted. E.g., <CODE>isc_log_write(... "open: %s: %s", filename,
|
|
isc_result_totext(result));</CODE><P>
|
|
|
|
Function names, line numbers, memory addresses, and other references
|
|
to program internals may be used in debugging messages and in
|
|
messages to report programming errors detected at runtime.
|
|
They may not be used in messages that indicate errors in the
|
|
program's inputs or operation.<P>
|
|
|
|
<H2>Perl source code</H2>
|
|
|
|
Perl must not be required for building, installing, or using the BIND 9
|
|
name server. It may be used for things like test scripts and optional
|
|
server add-on components.<P>
|
|
|
|
Perl 5 is assumed; Perl scripts do not need to work in Perl 4.<P>
|
|
|
|
Perl source code should follow the conventions for C source code
|
|
where applicable.<P>
|
|
|
|
|
|
|