Prex Home > Document Index > Coding Standard

Prex Coding Standard

Version 1.0.1 2009/10/01

/*
 * Prex Coding Standard
 *
 * Based on the CSRG's KNF (Kernel Normal Form) and FreeBSD's style guide
 *
 *      @(#)style       1.14 (Berkeley) 4/28/95
 */

/*
 * 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.
 */

/* Don't use C-99 style "// ..." comments. */

/* Don't use DOS '\r\n' line feeds. */

/*
 * Attempt to wrap lines longer than 80 characters appropriately.
 * Comments should not be enclosed in large boxes drawn with asterisks
 * or other characters.
 */

/*
 * The copyright header should be a multi-line comment, with the first
 * line of the comment having a dash after the star like so:
 */

/*-
 * Copyright (c) 1984-2025 John Q. Public
 * All rights reserved.
 *
 * Long, boring license goes here, but redacted for brevity
 */

/* After any copyright header, there is a blank line. */

/*
 * Kernel include files come first.
 */
#include <sys/types.h>          /* Non-local includes in brackets. */

/*
 * Then there's a blank line, followed by the /usr include files.
 */
#include <stdio.h>

/*
 * Global pathnames are defined in /usr/include/paths.h.  Pathnames
 * local to the program go in pathnames.h in the local directory.
 */
#include <paths.h>

/* Then, there's a blank line, and the user include files. */
#include "pathnames.h"          /* Local includes in double quotes. */

/*
 * The names of ``unsafe'' macros (ones that have side effects), and
 * the names of macros for manifest constants, are all in uppercase.
 * The expansions of expression-like macros are either a single token
 * or have outer parentheses.  Put a single tab character between the
 * #define and the macro name.  If the macro encapsulates a compound
 * statement, enclose it in a do loop, so that it can safely be used
 * in 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.
 */
#define MACRO(x, y)                     \
        do {                            \
                variable = (x) + (y);   \
                (y) += 2;               \
        } while (0)

/* Enum types are capitalized. */
enum enumtype {
        ONE,
        TWO
} et;

/*
 * In declarations, do not put any whitespace between asterisks and
 * adjacent tokens, except for tokens that are identifiers related to
 * types.  (These identifiers are the names of basic types, type
 * qualifiers, and typedef-names other than the one being declared.)
 * Separate these identi- fiers from asterisks using a single space.
 */

/*
 * When declaring variables in structures, each one gets its own line.
 * Try to make the structure readable by aligning the member names
 * using either one or two tabs depending upon your judgment.  You
 * should use one tab only if it suffices to align at least 90% of the
 * member names.  Names following extremely long types should be
 * separated by a single space.
 *
 * 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.
 */
struct foo {
        struct foo      *next;          /* list of active foo */
        struct mumble   amumble;        /* comment for mumble */
        int             bar;            /* try to align the comments */
        struct verylongtypename *baz;   /* won't fit in 2 tabs */
};
struct foo *foohead;                    /* head of global foo list */

/*
 * Prototypes should not have variable names associated with the types.
 * Prototypes may have an extra space after a tab to enable function
 * names to line up:
 */
static char     *function(int, const char *);
static void      usage(void);

/* C99 uintN_t is preferred over u_intN_t. */
uint32_t zero;

/*
 * 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;

        /*
         * 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.
         */
        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 != '\0')
                                err("illegal number -- %s", optarg);
                        break;
                case '?':
                default:
                        usage();
                        /* NOTREACHED */
                }
        }
        argc -= optind;
        argv += optind;

        /*
         * Use a space after keywords (if, while, for, return, switch).
         * No braces are required for control statements with only a
         * single statement, unless it's a long statement.
         *
         * Forever loops are done with for's, not while's.
         */
        for (p = buf; *p != '\0'; ++p)
                ;       /* Do nothing */
        for (;;)
                stmt;

        /*
         * Parts of a for loop may be left empty.  Don't put
         * declarations inside blocks.
         */
        for (; cnt < 15; cnt++) {
                stmt1;
                stmt2;
        }

        /*
         * Indentation is an 8 character tab.  If you have to wrap a
         * long statement, put the operator at the end of the line.
         */
        while (cnt < 20 && this_variable_name_is_too_long &&
               ep != NULL)
                z = a + really + long + statment + that + needs +
                    two + lines + gets + indented + properly +
                    on + the + second + and + subsequent + lines;

        /* Do not add whitespace at the end of a line, */

        /*
         * Closing and opening braces go on the same line as the else.
         * Don't add braces that aren't necessary except in cases where
         * there are ambiguity or readability issues.
         */
        if (test) {
                /*
                 * I have a long comment here.
                 */
                stmt;
        } else if (bar) {
                stmt;
                stmt;
        } else
                stmt;

        /*
         * No spaces after function names.  Commas have a space after them.
         * No spaces after `(' or `[' or preceding `]' or `)' characters.
         */
         error = function(a1, a2);
         if (error != 0)
                   exit(error);

        /*
         * Unary operators don't require spaces, binary operators do.
         * Don't excessively use parenthesis, but they should be used if
         * statement is really confusing without them, such as:
         * a = b->c[0] + ~d == (e || f) || g && h ? i : j >> 1;
         */
        a = ((b->c[0] + ~d == (e || f)) || (g && h)) ? i : (j >> 1);
        k = !(l & FLAGS);

        /*
         * Exits should be 0 on success, and other value on failure.
         * Avoid obvious comments such as "Exit 0 on success."
         */
        exit(0);
}

/*
 * The function type should be on a line by itself preceding the
 * function.  The opening brace of the function body should be on a
 * line by itself.
 */
static char *
function(int a1, int a2, float fl, int a4)
{
        /*
         * When declaring variables in functions declare them sorted
         * by size; multiple ones per line are okay.
         *
         * DO NOT use function calls in initializers.
         */
        struct foo three, *four;
        double five;
        int *six, seven;
        char *nine, ten, eleven, twelve;

        /*
         * Casts and sizeof's are not followed by a space.  NULL is
         * any pointer type, and doesn't need to be cast, so use NULL
         * instead of (struct foo *)0 or (struct foo *)NULL.  Also,
         * test pointers against NULL, i.e. use:
         *
         *      (p = f()) == NULL
         * not:
         *      !(p = f())
         *
         * Don't use '!' for tests unless it's a boolean, e.g. use
         * "if (*p == '\0')", not "if (!*p)".
         *
         * Routines returning void * should not have their return
         * values cast to any pointer type.
         *
         * Values in return statements should NOT be enclosed in
         * parentheses.
         */
        if ((four = malloc(sizeof(struct foo))) == NULL)
                err(1, NULL);
        if ((six = (int *)overflow()) == NULL)
                errx(1, "Number overflowed.");
        return eight;
}

static void
usage()
{
        /* Insert an empty line if the function has no local variables. */

        /*
         * Use printf, not fputs/puts/putchar/whatever, it's faster
         * and usually cleaner, not to mention avoiding stupid bugs.
         *
         * 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 ('|') separates either/or
         * options/arguments, and multiple options/arguments which are
         * specified together are placed in a single set of braces.
         *
         * "usage: f [-ade] [-b b_arg] [-m m_arg] req1 req2 [opt1 [opt2]]\n"
         * "usage: f [-a | -b] [-c [-de] [-n number]]\n"
         */
        (void)fprintf(stderr, "usage: f [-ab]\n");
        exit(1);
}