mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-12-30 23:48:09 +01:00
122c2021d3
things are explicitly stated now rather than being implied by example. Obtained from: Quite a few people over the last few weeks Reviewed by: core
463 lines
13 KiB
Groff
463 lines
13 KiB
Groff
.\" Copyright (c) 1995 FreeBSD Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL [your name] OR CONTRIBUTORS BE LIABLE
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.\" $Id: style.9,v 1.17 1997/04/09 19:03:14 mpp Exp $
|
|
.\"
|
|
.Dd December 14, 1995
|
|
.Dt STYLE 9
|
|
.Os FreeBSD
|
|
.Sh NAME
|
|
.Nm style
|
|
.Nd "Kernel source file style guide"
|
|
.Sh DESCRIPTION
|
|
This file specifies the preferred style for kernel source files in the
|
|
.Tn FreeBSD
|
|
source tree. It is also a guide for preferred user land code style.
|
|
.Bd -literal -offset 0i
|
|
/*
|
|
* Style guide for the FreeBSD KNF (Kernel Normal Form).
|
|
*/
|
|
|
|
/*
|
|
* 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.
|
|
Use of the __P macro in new code is discouraged, although modifications
|
|
to existing files should be consistent with that file's conventions.
|
|
.Pp
|
|
In general code can be considered
|
|
.Dq new code
|
|
when it makes up about 50% or more of the file[s] involved. This is enough
|
|
to break precedents in the existing code and use the current style guidelines.
|
|
.Pp
|
|
The kernel has a name associated with parameter types, e.g., in the kernel
|
|
use:
|
|
.Bd -literal -offset 0i
|
|
void function(int fd);
|
|
.Ed
|
|
.Pp
|
|
In header files visible to user land applications, prototypes that are
|
|
visible must use either protected names or no names with the types. It
|
|
is preferable to use protected names.
|
|
e.g., use:
|
|
.Bd -literal -offset 0i
|
|
void function(int);
|
|
.Ed
|
|
.Pp
|
|
or:
|
|
.Bd -literal -offset 0i
|
|
void function(int _fd);
|
|
.Ed
|
|
.Pp
|
|
Prototypes may have an extra space after a tab to enable function names
|
|
to line up:
|
|
.Bd -literal -offset 0i
|
|
static char *function(int _arg, const char *_arg2, struct foo *_arg3,
|
|
struct bar *_arg4);
|
|
static void usage(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(int argc, char *argv[])
|
|
{
|
|
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")) != -1)
|
|
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 (if, while, for, return, switch). No braces are
|
|
used for control statements with zero or only a single statement.
|
|
Forever loops are done with for's, not while's.
|
|
.Bd -literal -offset 0i
|
|
for (p = buf; *p != '\e0'; ++p)
|
|
; /* nothing */
|
|
for (;;)
|
|
stmt;
|
|
if (val != NULL)
|
|
val = realloc(val, newsize);
|
|
.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
|
|
Indentation is an 8 character tab.
|
|
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
|
|
Do not add whitespace at the end of a line, and only use tabs then spaces
|
|
to form the indentation. Do not use more spaces than a tab will produce
|
|
and do not use spaces in front of tabs.
|
|
.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. Commas have a space after them. No spaces
|
|
after
|
|
.Sq \&(
|
|
or
|
|
.Sq \&[
|
|
or preceding
|
|
.Sq \&]
|
|
or
|
|
.Sq \&)
|
|
characters.
|
|
.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(int a1, int a2, float fl, int a4)
|
|
{
|
|
.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.
|
|
DO NOT use function calls in initializers!
|
|
.Bd -literal -offset 0i
|
|
struct foo one, *two;
|
|
double three;
|
|
int *four, five;
|
|
char *six, seven, eight, nine, ten, eleven, twelve;
|
|
|
|
four = myfunction();
|
|
.Ed
|
|
.Pp
|
|
Do not declare functions inside other functions; ANSI C says that
|
|
such declarations have file scope regardless of the nesting of the
|
|
declaration. Hiding file declarations in what appears to be a local
|
|
scope is undesirable and will elicit complaints from a good compiler.
|
|
.Pp
|
|
Casts and sizeof's are not followed by a space. Note that
|
|
.Xr indent 1
|
|
does not understand this rule.
|
|
.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.)
|
|
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
|
|
Old-style function declarations look like this:
|
|
.Bd -literal -offset 0i
|
|
static char *
|
|
function(a1, a2, fl, a4)
|
|
int a1, a2; /* Declare ints, too, don't default them. */
|
|
float fl; /* Beware double vs. float prototype differences. */
|
|
int a4; /* List in order declared. */
|
|
{
|
|
.Ed
|
|
.Pp
|
|
Use ANSI function declarations unless you explicitly need K&R compatability.
|
|
.Pp
|
|
Variable numbers of arguments should look like this.
|
|
.Bd -literal -offset 0i
|
|
#include <stdarg.h>
|
|
|
|
void
|
|
vaf(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
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
|
|
New core kernel code should be reasonably compliant with the style guides.
|
|
The guidelines for third-party maintained modules and device drivers are more
|
|
relaxed but at a minimum should be internally consistant with their style.
|
|
.Pp
|
|
Stylistic changes (including whitespace changes) are hard on the source
|
|
repository and are to be avoided without good reason. Code that is
|
|
approximately KNF compliant in the repository must not diverge from
|
|
compliance.
|
|
.Sh SEE ALSO
|
|
.Xr indent 1 ,
|
|
.Xr err 3 ,
|
|
.Xr sysexits 3 ,
|
|
.Xr warn 3
|
|
.Sh HISTORY
|
|
This man page is largely based on the src/admin/style/style file from
|
|
the
|
|
.Tn BSD
|
|
4.4-Lite2 release, with updates to reflect the current practice and
|
|
desire of the
|
|
.Tn FreeBSD
|
|
project.
|