227052690b
disagrees with it personally :-), and fixed the misleading parts.
416 lines
11 KiB
Groff
416 lines
11 KiB
Groff
.Dd December 14, 1995
|
|
.Dt STYLE 9
|
|
.Os FreeBSD 2.2
|
|
.Sh NAME
|
|
.Nm style
|
|
.Nd "Kernel source file style guide"
|
|
.Sh DESCRIPTION
|
|
This file contains an example of the preferred style for kernel source
|
|
files in the FreeBSD source tree.
|
|
.Bd -literal -offset 0i
|
|
/*
|
|
* Style guide for the 4BSD KNF (Kernel Normal Form).
|
|
*
|
|
* @(#)style 1.14 (Berkeley) 4/28/95
|
|
*
|
|
* $Id: style.9,v 1.8 1996/06/13 19:52:42 wollman Exp $
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* VERY important single-line comments look like this.
|
|
*/
|
|
|
|
/* Most single-line comments look like this. */
|
|
|
|
/*
|
|
* Multi-line comments look like this. Make them real sentences. Fill
|
|
* them so they look like real paragraphs.
|
|
*/
|
|
.Ed
|
|
.Pp
|
|
Kernel include files come first; normally, you'll need <sys/types.h>
|
|
OR <sys/param.h>, but not both! <sys/types.h> includes <sys/cdefs.h>,
|
|
and it's okay to depend on that.
|
|
.Bd -literal -offset 0i
|
|
#include <sys/types.h> /* Non-local includes in brackets. */
|
|
.Ed
|
|
.Pp
|
|
If it's a network program, put the network include files next.
|
|
.Bd -literal -offset 0i
|
|
#include <net/if.h>
|
|
#include <net/if_dl.h>
|
|
#include <net/route.h>
|
|
#include <netinet/in.h>
|
|
#include <protocols/rwhod.h>
|
|
.Ed
|
|
.Pp
|
|
Then there's a blank line, followed by the /usr include files.
|
|
The /usr include files should be sorted!
|
|
.Bd -literal -offset 0i
|
|
#include <stdio.h>
|
|
.Ed
|
|
.Pp
|
|
Global pathnames are defined in /usr/include/paths.h. Pathnames local
|
|
to the program go in pathnames.h in the local directory.
|
|
.Bd -literal -offset 0i
|
|
#include <paths.h>
|
|
.Ed
|
|
.Pp
|
|
Then, there's a blank line, and the user include files.
|
|
.Bd -literal -offset 0i
|
|
#include "pathnames.h" /* Local includes in double quotes. */
|
|
.Ed
|
|
.Pp
|
|
Macros are capitalized, parenthesized, and should avoid side-effects.
|
|
If they are an inline expansion of a function, the function is defined
|
|
all in lowercase, the macro has the same name all in uppercase. If the
|
|
macro needs more than a single line, use braces. Right-justify the
|
|
backslashes, it makes it easier to read.
|
|
.Bd -literal -offset 0i
|
|
#define MACRO(x, y) { \e
|
|
variable = (x) + (y); \e
|
|
(y) += 2; \e
|
|
}
|
|
.Ed
|
|
.Pp
|
|
Enum types are capitalized.
|
|
.Bd -literal -offset 0i
|
|
enum enumtype { ONE, TWO } et;
|
|
.Ed
|
|
.Pp
|
|
When declaring variables in structures, declare them sorted by use, then
|
|
by size, and then by alphabetical order. The first category normally
|
|
doesn't apply, but there are exceptions. Each one gets its own line.
|
|
Put a tab after the first word, i.e. use
|
|
.Ql int^Ix;
|
|
and
|
|
.Ql struct^Ifoo *x; .
|
|
.Pp
|
|
Major structures should be declared at the top of the file in which they
|
|
are used, or in separate header files, if they are used in multiple
|
|
source files. Use of the structures should be by separate declarations
|
|
and should be "extern" if they are declared in a header file.
|
|
.Bd -literal -offset 0i
|
|
struct foo {
|
|
struct foo *next; /* List of active foo */
|
|
struct mumble amumble; /* Comment for mumble */
|
|
int bar;
|
|
};
|
|
struct foo *foohead; /* Head of global foo list */
|
|
|
|
/* Make the structure name match the typedef. */
|
|
typedef struct _bar {
|
|
int level;
|
|
} BAR;
|
|
.Ed
|
|
.Pp
|
|
All functions are prototyped somewhere.
|
|
.Pp
|
|
Function prototypes for private functions (i.e. functions not used
|
|
elsewhere) go at the top of the first source module. Functions
|
|
local to one source module should be declared
|
|
.Ql static .
|
|
.Pp
|
|
Functions used from other parts of the kernel are prototyped in the
|
|
relevant include file.
|
|
.Pp
|
|
Functions that are used locally in more than one module go into a
|
|
separate header file, e.g.
|
|
.Pa extern.h .
|
|
.Pp
|
|
Only use the __P macro from the include file <sys/cdefs.h> if the source
|
|
file in general is (to be) compilable with a K&R Old testament compiler.
|
|
.Pp
|
|
Only the kernel has a name associated with the types, i.e. in the kernel
|
|
use:
|
|
.Bd -literal -offset 0i
|
|
void function __P((int fd));
|
|
.Ed
|
|
.Pp
|
|
in user land use:
|
|
.Bd -literal -offset 0i
|
|
void function __P((int));
|
|
|
|
static char *function __P((int, const char *));
|
|
static void usage __P((void));
|
|
|
|
/*
|
|
* All major routines should have a comment briefly describing what
|
|
* they do. The comment before the "main" routine should describe
|
|
* what the program does.
|
|
*/
|
|
int
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
extern char *optarg;
|
|
extern int optind;
|
|
long num;
|
|
int ch;
|
|
char *ep;
|
|
|
|
.Ed
|
|
.Pp
|
|
For consistency, getopt should be used to parse options. Options
|
|
should be sorted in the getopt call and the switch statement, unless
|
|
parts of the switch cascade. Elements in a switch statement that
|
|
cascade should have a FALLTHROUGH comment. Numerical arguments
|
|
should be checked for accuracy. Code that cannot be reached should
|
|
have a NOTREACHED comment.
|
|
.Bd -literal -offset 0i
|
|
while ((ch = getopt(argc, argv, "abn")) != EOF)
|
|
switch (ch) { /* Indent the switch. */
|
|
case 'a': /* Don't indent the case. */
|
|
aflag = 1;
|
|
/* FALLTHROUGH */
|
|
case 'b':
|
|
bflag = 1;
|
|
break;
|
|
case 'n':
|
|
num = strtol(optarg, &ep, 10);
|
|
if (num <= 0 || *ep != '\e0')
|
|
err("illegal number -- %s", optarg);
|
|
break;
|
|
case '?':
|
|
default:
|
|
usage();
|
|
/* NOTREACHED */
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
.Ed
|
|
.Pp
|
|
Space after keywords (while, for, return, switch). No braces are
|
|
used for control statements with zero or only a single statement.
|
|
.Pp
|
|
Forever loops are done with for's, not while's.
|
|
.Bd -literal -offset 0i
|
|
for (p = buf; *p != '\e0'; ++p);
|
|
for (;;)
|
|
stmt;
|
|
|
|
.Ed
|
|
.Pp
|
|
Parts of a for loop may be left empty. Don't put declarations
|
|
inside blocks unless the routine is unusually complicated.
|
|
.Bd -literal -offset 0i
|
|
for (; cnt < 15; cnt++) {
|
|
stmt1;
|
|
stmt2;
|
|
}
|
|
.Ed
|
|
.Pp
|
|
Second level indents are four spaces.
|
|
.Bd -literal -offset 0i
|
|
while (cnt < 20)
|
|
z = a + really + long + statement + that + needs +
|
|
two lines + gets + indented + four + spaces +
|
|
on + the + second + and + subsequent + lines.
|
|
.Ed
|
|
.Pp
|
|
Closing and opening braces go on the same line as the else.
|
|
Don't add braces that aren't necessary.
|
|
.Bd -literal -offset 0i
|
|
if (test)
|
|
stmt;
|
|
else if (bar) {
|
|
stmt;
|
|
stmt;
|
|
} else
|
|
stmt;
|
|
.Ed
|
|
.Pp
|
|
No spaces after function names.
|
|
.Bd -literal -offset 0i
|
|
if (error = function(a1, a2))
|
|
exit(error);
|
|
.Ed
|
|
.Pp
|
|
Unary operators don't require spaces, binary operators do. Don't
|
|
use parenthesis unless they're required for precedence, or the
|
|
statement is really confusing without them.
|
|
.Bd -literal -offset 0i
|
|
a = b->c[0] + ~d == (e || f) || g && h ? i : j >> 1;
|
|
k = !(l & FLAGS);
|
|
.Ed
|
|
.Pp
|
|
Exits should be 0 on success, or according to the predefined
|
|
values in
|
|
.Xr sysexits 3 .
|
|
.Bd -literal -offset 0i
|
|
exit(EX_OK); /*
|
|
* Avoid obvious comments such as
|
|
* "Exit 0 on success."
|
|
*/
|
|
}
|
|
.Ed
|
|
.Pp
|
|
The function type should be on a line by itself
|
|
preceding the function.
|
|
.Bd -literal -offset 0i
|
|
static char *
|
|
function(a1, a2, fl, a4)
|
|
int a1, a2, a4; /* Declare ints, too, don't default them. */
|
|
float fl; /* List in order declared, as much as possible. */
|
|
{
|
|
.Ed
|
|
.Pp
|
|
When declaring variables in functions declare them sorted by size,
|
|
then in alphabetical order; multiple ones per line are okay.
|
|
Declaring functions inside functions is not recommendable, since their
|
|
linkage scope is always global. If a line overflows reuse the type
|
|
keyword.
|
|
.Pp
|
|
Be careful to not obfuscate the code by initializing variables in
|
|
the declarations. Use this feature only thoughtfully.
|
|
.Bd -literal -offset 0i
|
|
extern u_char one;
|
|
extern char two;
|
|
struct foo three, *four;
|
|
double five;
|
|
int *six, seven, eight();
|
|
char *nine, ten, eleven, twelve, thirteen, fourteen, fifteen;
|
|
char *overflow __P((void));
|
|
void *mymalloc __P((u_int));
|
|
.Ed
|
|
.Pp
|
|
Casts and sizeof's are not followed by a space.
|
|
.Pp
|
|
NULL is the preferred null pointer constant. Use NULL instead of
|
|
(type *)0 or (type *)NULL in contexts where the compiler knows the
|
|
type, e.g., in assignments. Use (type *)NULL in other contexts,
|
|
in particular for all function args. (Casting is essential for
|
|
varadic args and is necessary for other args if the function prototype
|
|
might not be in scope; since we pretend to support K&R compilers,
|
|
most prototypes might not be in scope.)
|
|
Test pointers
|
|
against NULL, e.g., use:
|
|
.Bd -literal -offset 0i
|
|
(p = f()) == NULL
|
|
.Ed
|
|
.Pp
|
|
not:
|
|
.Bd -literal -offset 0i
|
|
!(p = f())
|
|
.Ed
|
|
.Pp
|
|
Don't use '!' for tests unless it's a boolean, e.g. use
|
|
.Bd -literal -offset 0i
|
|
if (*p == '\e0')
|
|
.Ed
|
|
.Pp
|
|
not
|
|
.Bd -literal -offset 0i
|
|
if (!*p)
|
|
.Ed
|
|
.Pp
|
|
Routines returning void * should not have their return values cast
|
|
to any pointer type.
|
|
.Pp
|
|
Use
|
|
.Xr err 3
|
|
or
|
|
.Xr warn 3 ,
|
|
don't roll your own!
|
|
.Bd -literal -offset 0i
|
|
if ((four = malloc(sizeof(struct foo))) == NULL)
|
|
err(1, (char *)NULL);
|
|
if ((six = (int *)overflow()) == NULL)
|
|
errx(1, "Number overflowed.");
|
|
return (eight);
|
|
}
|
|
.Ed
|
|
.Pp
|
|
Don't use ANSI function declarations unless you absolutely have too,
|
|
i.e. you're declaring functions with variable numbers of arguments.
|
|
.Pp
|
|
ANSI function return values and braces look like regular functions.
|
|
.Bd -literal -offset 0i
|
|
int
|
|
function(int a1, int a2)
|
|
{
|
|
...
|
|
}
|
|
.Ed
|
|
.Pp
|
|
Variable numbers of arguments should look like this.
|
|
.Bd -literal -offset 0i
|
|
#if __STDC__
|
|
#include <stdarg.h>
|
|
#else
|
|
#include <varargs.h>
|
|
#endif
|
|
|
|
void
|
|
#if __STDC__
|
|
vaf(const char *fmt, ...)
|
|
#else
|
|
vaf(fmt, va_alist)
|
|
char *fmt;
|
|
va_dcl
|
|
#endif
|
|
{
|
|
va_list ap;
|
|
#if __STDC__
|
|
va_start(ap, fmt);
|
|
#else
|
|
va_start(ap);
|
|
#endif
|
|
STUFF;
|
|
|
|
va_end(ap); /* No return needed for void functions. */
|
|
}
|
|
|
|
static void
|
|
usage()
|
|
{
|
|
/* Insert an empty line if the function has no local variables. */
|
|
.Ed
|
|
.Pp
|
|
Use
|
|
.Xr printf 3 ,
|
|
not fputs/puts/putchar/whatever, it's faster and usually cleaner, not
|
|
to mention avoiding stupid bugs.
|
|
.Pp
|
|
Usage statements should look like the manual pages. Options w/o
|
|
operands come first, in alphabetical order inside a single set of
|
|
braces. Followed by options with operands, in alphabetical order,
|
|
each in braces. Followed by required arguments in the order they
|
|
are specified, followed by optional arguments in the order they
|
|
are specified. A bar
|
|
.Pq Sq \&|
|
|
separates either/or options/arguments,
|
|
and multiple options/arguments which are specified together are
|
|
placed in a single set of braces.
|
|
.Pp
|
|
.Bd -ragged -offset 0.3i
|
|
"usage: f [-ade] [-b b_arg] [-m m_arg] req1 req2 [opt1 [opt2]]\en"
|
|
"usage: f [-a | -b] [-c [-de] [-n number]]\en"
|
|
.Ed
|
|
.Bd -literal -offset 0i
|
|
(void)fprintf(stderr, "usage: f [-ab]\en");
|
|
exit(1);
|
|
}
|
|
.Ed
|
|
.Pp
|
|
Note that the policy regarding the usage of K&R versus ANSI function
|
|
definitions could not be commonly agreed to. While keeping the old
|
|
form is more consistent with the existing code base, sticking to it
|
|
defeats the migration to the more modern ANSI style. For new code,
|
|
chose what you feel is more important. However, when modifying
|
|
existing subsystems or files, stick with the style that is already
|
|
there.
|
|
.Sh SEE ALSO
|
|
.Xr err 3 ,
|
|
.Xr warn 3 ,
|
|
.Xr sysexits 3
|
|
.Sh HISTORY
|
|
This man page is largely based on the src/admin/style/style file from
|
|
the BSD 4.4-Lite2 release, with a few updates to reflect the current
|
|
practice and desire of the FreeBSD project.
|
|
|
|
|