diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1999-08-19 08:12:12 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1999-08-19 08:12:12 +0000 |
commit | 31bef4da8b16646d3365f7fdeefa43b5e79f4b82 (patch) | |
tree | 0108937563aeeffc0a57b0ad43aaadf7302691d5 /share/man/man9/style.9 | |
parent | d6e3aa3875f277e063cd9238f2decc060491b3a1 (diff) |
From FreeBSD with changes from /usr/share/misc/style
Diffstat (limited to 'share/man/man9/style.9')
-rw-r--r-- | share/man/man9/style.9 | 527 |
1 files changed, 527 insertions, 0 deletions
diff --git a/share/man/man9/style.9 b/share/man/man9/style.9 new file mode 100644 index 00000000000..1ee279dc50a --- /dev/null +++ b/share/man/man9/style.9 @@ -0,0 +1,527 @@ +.\" 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. +.\" +.\" $OpenBSD: style.9,v 1.1 1999/08/19 08:12:11 millert Exp $ +.\" +.Dd August 19, 1999 +.Dt STYLE 9 +.Os +.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 OpenBSD +source tree. It is also a guide for preferred user land code style. +These guidelines should be followed for for all new code. +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. +.Bd -literal -offset 0i +/* + * Style guide for the OpenBSD 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 (i.e. sys/*.h) 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 +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. In, user land, +functions local to one source module should be declared +.Ql static . +This should not be done in kernel land since it makes it impossible +to use the kernel debugger. +.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 +When declaring a prototype, use the __P macro from the include file +<sys/cdefs.h>. Only the kernel has a name associated with the types, +i.e. in the kernel use: +.Bd -literal -offset 0i +void function __P((int a)); +.Ed +in user land use: +.Bd -literal -offset 0i +void function __P((int)); +.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 __P((int, const char *)); +static void usage __P((void)); +.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. +If the macro encapsulates a compound statement, enclose it in a +.Dq Li do +loop, +so that it can safely be used in +.Dq Li if +statements. +Any final statement-terminating semicolon should be +supplied by the macro invocation rather than the macro, to make parsing easier +for pretty-printers and editors. +.Bd -literal -offset 0i +#define MACRO(x, y) do { \e + variable = (x) + (y); \e + (y) += 2; \e +} while (0) +.Ed +.Pp +Enumeration values are all uppercase. +.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 */ +.Ed +.Pp +Use +.Xr queue 3 +macros rather than rolling your own lists, whenever possible. Thus, +the previous example would be better written: +.Bd -literal -offset 0i +#include <sys/queue.h> +struct foo { + LIST_ENTRY(foo) link; /* Queue macro glue for foo lists */ + struct mumble amumble; /* Comment for mumble */ + int bar; +}; +LIST_HEAD(, foo) foohead; /* Head of global foo list */ +.Ed +.Pp +Avoid using typedefs for structure types. This makes it impossible +for applications to use pointers to such a structure opaquely, which +is both possible and beneficial when using an ordinary struct tag. +When convention requires a typedef, make its name match the struct +tag. Avoid typedefs ending in +.Dq Li \&_t , +except as specified in Standard C or by +.Tn POSIX . +.Bd -literal -offset 0i +/* Make the structure name match the typedef. */ +typedef struct _bar { + int level; +} BAR; +.Ed +.Pp +.Bd -literal -offset 0i +/* + * 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') { + warnx("illegal number, -n argument -- %s", + optarg); + usage(); + } + 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 unless that +statement is more than a single line in which case they are permitted. +Forever loops are done with for's, not while's. +.Bd -literal -offset 0i + for (p = buf; *p != '\e0'; ++p) + ; /* nothing */ + for (;;) + stmt; + for (;;) { + z = a + really + long + statement + that + needs + + two lines + gets + indented + four + spaces + + on + the + second + and + subsequent + lines; + } + for (;;) { + if (cond) + 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 +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 +followed by 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. +Braces that aren't necessary may be left out, unless they cause +a compiler warning. +.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 parentheses unless they're required for precedence, the statement +is confusing without them, or the compiler generates a waring without +them. Remember that other people may be confused more easily than you. +Do YOU understand the following? +.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. Old +style function declarations can go on the same line. ANSI style +function declarations should go in the include file "extern.h". +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 +variadic 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 +Don't use ANSI function declarations unless you absolutely have to, +i.e. you're declaring functions with variable numbers of arguments. +.Pp +ANSI function declarations look like this: +.Bd -literal -offset 0i +void +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() +{ + extern char *__progname; /* from crt0.o */ +.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 +.Pp +The +.Li __progname +string, should be used instead of hard-coding the program name. +.Bd -literal -offset 0i + (void)fprintf(stderr, "usage: %s [-ab]\en", __progname); + 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 consistent 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. +.Pp +Whenever possible, code should be run through a code checker +(e.g., "gcc -Wall" or lint(1)) and produce minimal warnings. + +.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 OpenBSD +project. |