7.2 Style Guide


Like many engineering efforts, OpenSolaris enforces a coding style on contributed code, regardless of its source. This coding style is very similar to that used by the Linux kernel, BSD systems, and many other non-GNU projects (the GNU project uses its own unique coding style). This style is described in detail at http://opensolaris.org/os/community/onnv/, although some elements in the style guide are rather dated, especially as they relate to K&R C versus ANSI (now ISO) C. You also should examine the files in usr/src/prototypes; these provide examples of the correct general layout and style for most types of source files.

7.2.1 Automated Style Tools

Two tools for checking many elements of the coding style are available as part of the ON tools. These tools are cstyle(1) for verifying compliance of C code with most style guidelines, and hdrchk(1) for checking the style of C and C++ headers. Note that these tools are not perfect; there are style mistakes that cannot be caught by any reasonable tool, and others that cannot be caught by the particular implementations. Improving the accuracy and completeness of these tools is an ongoing task and enhancements of all kinds are welcome.

All headers are expected to pass 'hdrchk'. All C files and headers are expected to pass 'cstyle -P -p'. These tools produce no output and exit with status code 0 if the file(s) checked meet the style requirements.

7.2.2 =head3 Style Examples

A few common examples of bad style which are not currently caught by the tools include:

* Mixing declaration of initialized and uninitialized variables on the same line; for example:

int a, b = 16, c = -4, d;

Instead, uninitialized variables may be declared one or more per line, and each initialized variable should be declared on its own line:

int a, d;
int b = 16;
int c = -4;

or

int a;
int b = 16;
int c = -4;
int d;

* Inconsistent use of acceptable styles. In the above example, two acceptable ways to declare variables are presented. Good style dictates that whichever is used by used everywhere within a file; however, the tools do not check for such consistency.

* Incorrect placement and use of braces around if/else constructs. The heuristic test for this is not run by default, and is not completely reliable. For simplicity's sake, here is the correct format for if/else in which both alternatives are compound statements:

if (x != SOME_CONSTANT) {
	do_stuff();
	return (x);
} else {
	do_other_stuff();
	x = OTHER_CONSTANT;
}

If neither alternative is a compound statement, use:

if (x != SOME_CONSTANT)
	do_stuff();
else
	do_other_stuff();

Finally, if only one alternative is a compound statement, both alternatives should have braces, formatted as shown:

if (x != SOME_CONSTANT) {
	do_stuff();
	return (x);
} else {
	do_other_stuff();
}

Note the placement of braces; they should surround an "else" and only the closing brace should be on a line by itself.

* Use of comments associated with conditional compilation directives. It is good style to include trailing comments after #else and #endif directives describing the condition it references; for example:

#ifdef __FOO
...
#else	/* !__FOO */
...
#endif	/* !__FOO */

The style tools do not check for the presence, usefulness, or correctness of these trailing comments, but you should normally include them, especially if the intervening code blocks are lengthy or the tests are part of a complicated set of nested preprocessor conditionals.

* Incorrect guards in header files. Guard names should be derived from the header name, but hdrchk does not check this. For example, a header installed in <sys/scsi/foo_impl.h> should have a guard as follows:

#ifndef _SYS_SCSI_FOO_IMPL_H
#define _SYS_SCSI_FOO_IMPL_H
...
#endif /* _SYS_SCSI_FOO_IMPL_H */

However, hdrchk verifies neither the actual guard token name nor the comment following #endif.

* Comment style is only partially checked. For example, the correct style for block comments is:

/*
 * Some comment here.
 * More here.
 */

cstyle(1) can detect some common errors, such as enclosing the entire block comment in a box of asterisks or other characters. However, it cannot detect all such errors; for example:

/*
   Some comment here.
   We conserve asterisks even though it's harder to read.
   Our comment is nonconforming.
 */

Correct indentation of comments is also unchecked; block and single-line comments within functions should be indented at the same level as the code they document. Trailing comments should be aligned with other trailing comments in related code. None of these style guidelines is checked by the tools.

It probably goes without saying that the contents of comments aren't checked in any way. Please, be sure to follow the comment content guidelines in the style guide.

7.2.3 Non-Formatting Considerations

cstyle(1) and hdrchk(1) will, in addition to several code-formatting guidelines, verify compliance with SCCS keyword and copyright requirements. All files must be under SCCS control, and each must have a set of keywords near the top (see the prototypes for the exact order of file contents). In general, the keywords should have the following format in C files and headers:

@PRAGMA_IDENT_EXP@

Note that this string actually contains several embedded tabs; showing these tabs as \t, the keywords look like:

@PRAGMA_IDENT@

Files which are not C (or C++) implementations or headers should dispense with the "pragma" portion and just use #ident as follows:

@IDENT@

In addition, each file must contain a statement of copyright at the very top. The acceptable text and formats for these copyrights are shown in the example files in usr/src/prototypes. When a source file is significantly updated, the year or range of years in the copyright should be replaced with just the current year at the time of modification. Significant updates do not include formatting changes. However, if you prefer not to think about whether your change constitutes a significant update or if you don't trust your judgment, erring on the side of always updating the year is acceptable. Since the prototypes assume that Sun is always the sole copyright holder, you will need to change the copyright statement slightly; for example, if a file initially contains:

/*
 * Copyright (c) 1992-1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

you should replace this notice with:

/*
 * Copyright 2005 Sun Microsystems, Inc.
 * All rights reserved.  Use is subject to license terms.
 */

and, if you are a contributor not employed by Sun, you should also add:

/*
 * Copyright 2005 J. Random Hacker
 * All rights reserved.  Use is subject to license terms.
 */

or a similar statement of your copyright. Do not combine copyright notices, and do not remove the existing copyright notices unless specifically instructed to do so.

7.2.4 Integration Requirements

Before submitting any changes for code review prior to inclusion in OpenSolaris, you should self-review your code for stylistic correctness (as well as semantic correctness!). Running the cstyle(1) and/or hdrchk(1) tools is part of this process, but you should also be familiar with the entire style guide so that you will be able to use correct style even in elements that the tools do not check. All new code must be cstyle- and, if applicable, hdrchk-clean. If you are modifying existing code which does not conform to the style guide, your changes should be conformant, and at worst your changes should not increase the number of cstyle or hdrchk warnings.