printf("this is going to be %s very long %s statement\n",
_______"a", "printf");
puts("This string got very far to the "
"left and wrapped. ANSI catenation "
"rules will turn this into one "
"long string.");
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.
Good:
/*
* Private variables.
*/
static int a /* Description of 'a'. */
static int b /* Description of 'b'. */
static char * c /* Description of 'c'. */
The following lint and lint-like comments should be used where appropriate:
/* ARGSUSED */
/* FALLTHROUGH */
/* NOTREACHED */
/* VARARGS */
.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.
/*
* 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 */
Operating-system-specific files should not be included by most modules.
Include UNIX "sys" .h files before ordinary C includes.
Bad:
if (i > 0) {
printf("yes\n"); i = 0; j = 0;
x = 4, y *= 2;
}
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.
Good:
static inline void
f(int i) {
/* whatever */
}
int
g(int i, /* other args here */
int last_argument)
{
return (i * i);
}
To suppress compiler warnings, unused function arguments are declared
using the UNUSED()
macro.
In the function body, local variable declarations are followed by any
REQUIRE()
s, UNUSED()
declarations, and other
code, in this order. These sections are separated by blank lines.
Generally speaking, when a control statement (if, for
or
while
) 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).
Good:
static void
f(int i) {
if (i > 0) {
printf("yes\n");
i = 0;
} else
printf("no\n");
}
Bad:
void f(int i)
{
if(i<0){i=0;printf("was negative\n");}
if (i > 0)
{
printf("yes\n");
i = 0;
}}
malloc(4 * sizeof(long))
.
printf
and its variants,
fputc
, fwrite
(when writing text),
fflush
,
memcpy
, memmove
, memset
,
strcpy
, strncpy
, and strcat
.
Certain functions return values or not depending on the operating
system or even compiler flags; these include
these include openlog
and srandom
.
The return value of these should not be used nor cast to (void).
All error conditions must be handled.
Mixing of error status and valid results within a single type should be avoided.
Good:
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;
}
Not so good:
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;
}
Bad (obviously for more than one reason ...):
(void) malloc(SMBUF);
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.
Good:
/* 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)) {
}
Bad:
/* Test if flag set. */
if (flags & FOO) {
}
/* Test if flag clear. */
if (! (flags & BAR)) {
}
Good:
char *c = NULL;
/* ... */
if (c == NULL) {
/* Do something. */
}
Good:
char *text;
/* text is initialized here. */
free(text);
text = NULL;
Good:
int i = 10;
/* ... */
if (i != 0) {
/* Do something. */
}
Bad:
int i = 10;
/* ... */
if (i) {
/* Do something. */
}
Good:
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) {
...
}
Bad:
return (success ? ISC_R_SUCESS : ISC_R_FAILURE);
Bad:
malloc(size = 20);
Ok:
fputc(c++, stdout);
isc_buffer_t /* typedef */
dns_name_setbuffer(name, buffer) /* function */
ISC_LIST_HEAD(list) /* macro */
isc_commandline_argument /* variable */
however, structures which are typedef'd generally have the name of the
typedef sans the final _t:
struct dns_rbtnode {
/* ... members ... */
}
Generally speaking macros are defined with all capital letters, but
this is not universally consistent (eg, numerous isc_buffer_{foo}
macros).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).
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.
UNEXPECTED_ERROR()
macro is obsolete and
should not be used in new code.Log messages do not start with a capital letter, nor do they end in a period.
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 "zone '%s' is lame"
.
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., isc_log_write(... "open: %s: %s", filename,
isc_result_totext(result));
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.
Perl 5 is assumed; Perl scripts do not need to work in Perl 4.
Perl source code should follow the conventions for C source code where applicable.