vsta

Design
Login

=== VSTa Design Methodology ===

  * '''If you can put it in a library, put it in a library.'''
  * '''If you can put it in a server, put it in a server.'''
  * '''Only when you have tried and failed both of the above, put it in the kernel.'''

==== Coding Standards ====

Yes, we have coding standards. The ones described here apply to the
kernel, C library, utility library, and "core servers"--the ones you
will generally use to boot. A seperate coding standard exists for the
windowing system. If another distinct subsystem comes up, and you
write it from scratch, then you can apply your own coding standard to
that part.

I've tried to hone it down to just 10 rules. It seems like a lot, but
hopefully 5 of them will match your personal style anyway, so it isn't
as bad as it looks.

In case you're wondering, this wasn't my C style of choice either. But
I learned it at HP for their kernel, and had it heavily reinforced at
Sequent with their kernel gurus. So now I stick with it, accepting
Henry's observation that "standard is better than better", at least
for C styles.

==== Henry Spencer's Rules of C ====

Read this article. Believe it. The rest of this is just some
refinement of what he says. This doesn't count as one of the 10,
because you shouldn't be writing C until you have read this.

==== Comments ====

/*
 * function_name()
 *      One-liner (only) for the function
 *
 * Further discussion.  This is a good place to mention success/failure
 * values and so forth.
 *
 * A distinct thought, or perhaps a note about assumptions or limitations.
 */
struct foobar *
function_name(void)
{
    int x;

    /*
     * Describe a block of code, then write the block of code
     */
    for (x = 0; x %lt FOOBLAT; ++x) {
	something(x);
	...
    }
}


Do NOT use pretty blocks of stars. They make it hard to update the
comments. We all know what happens when comments are a pain to
update....

==== Conditionals ====

    if (condition) {
	...
    }

    if (condition1 || condition2) {
    } else {
    }

    if (foo && !bar) {
    } else if (bletch) {
    }

==== Loops ====

    for (x = 0; x < 20; ++x) {
    }


Do NOT use the open version:

    for (x = 0; x < 20; ++x)
	bar();

If you aren't tripped by it, somebody else will be instead.

==== Indentation ====

Do not use tabs in the actual data part. You may use tabs to space out
to the following comments. Trailing tabs before the closing */ just
make it hard to add further words. Yes, making the closing */'s on
lines match up is pretty, but we have art and museums for that.

    int foob;               /* Will count instances of foob */
    static char bar;        /*  ...the char matching foob */

==== Patching somebody's code ====

Do not go fiddle somebody's organization just because you think you
can make it prettier. It is especially bad form to fiddle the
indentation and layout, PLUS add some new stuff, then hand them back
the entire result. Now they have to dig through a bunch of indentation
changes while trying to find functional changes.

Don't change:

extern int x, y, z;

Into:

extern int x;
extern int y;
extern int w;
extern int z;

Such a change adds little, but fills our screens with diffs. If you
take over the file AND you add comments to each line, it might be
worth it. It sure would be easy to miss that "w" in there at the same
time, wouldn't it?

==== ANSI prototypes ====

Use ANSI prototypes where possible. The one major pain is anonymous
struct pointers. Imagine a header which uses an anonymous pointer
(i.e., they know the name of the struct they're pointing to, but they
don't know the definitions of the struct.) gcc will complain about
such a prototype:
extern void my_func(struct foob *);

unless he has already seen "struct foob" at level 0 (global).

The workaround of choice is to use STRUCT_REF in <sys/types.h>.

==== ANSI void * ====

Use ANSI void pointers when you're dealing with a generic pointer
value. Do NOT do math with such a pointer. Yes, GCC will happen to
treat it as a char *. If you're counting on this, cast it to (char *)
and then do the math.

==== C types ====

Use the basic C types for most work. If you have a struct pointer,
just name it as such. I want:

    struct foo {
	int field1;
	...
    };

...

    {
	struct foo *f;

	f = ...;
	f->field1 = bar;
    }

And not:

    typedef struct {
	int field1;
	...
    } foo_t;

    ...


C has good basic ways for naming types, and typedef's should not be
used to hide them. The exceptions are industry-recognized types like
"ushort" (unsigned short) and so forth.  Note that all identifiers
with "_t" suffixes are reserved by POSIX anyway.

==== #define's ====

A short #define can help encapsulate a simple operation or value into
a useful name. If you find that the number of "#define"'s is becoming
a large fraction of your header file (or even your code!) then back
off. Make it a function. Maybe it'll go slower... maybe GCC will
in-line it anyway.

==== Variable names ====

Use short variable names. A phone number is 7 digits because that's
the size of "name" the human mind can carry around easily. Keep your
variables in the same class of length. Long, descriptive variables
make code-reading cumbersome, as the mind continually must re-parse
the components of the variable name. Globals used across source files
will tend to be a little bit longer.