What Is Cosm?

Manifesto

Table of
Contents

Questions
& Answers

News

To Do List

Coding & CVS

Cosm API

Lists & IRC

Contacts
& Credits


[Cosm Logo]


Programmers Guide v0.53

Overview

The purpose of this document is to establish common programming methods for those developing code compatable with Cosm protocols.

Development Cycle

Since we use CVS the development cycle is continuous. Coders should make sure they are familiar with CVS and cosm-cvs.html.

Coordination

_Any_ questions at all, ask. Before implementing any additional low level functions inform me, so we can make sure there isn't any overlap. I intend to be familiar with every line of code, so if you need any "major" functionality let me know, someone else may already be working on it. Also, if you're going to do anything "neat" be sure and inform me first, just so more than one person knows what you're doing.

Use of Other Code and Libraries

All code must be original and your own writing, you can't cut-n-paste from _any_ other projects or code libraries due to license problems (and other code won't follow the Cosm standards anyway). I've made sure there are no license problems with the couple of libraries that are eventually needed, and even then they will be completely separated from the main code.

Simplicity

Simplicity and clarity in the code are more important than weird optimization tricks. Especially since all the real work is done in the cores. All code interfaces are designed to be as simple as possible.

Thread Safe Code

All Cosm routines must be fully thread safe. This is not optional. If you don't know how to use locks correctly please go read up, there are many sources on the net on using locks. Keep in mind also that 64 and 128bit data types may not be atomic.

Portability

Straight ANSI C + GNU Assembly. Period.
For numerous reasons of portability and readability Cosm will be written in straight ANSI C. The ASM optimizations should be done in GNU-ASM for portability to all OS variants of a given chip. C++ Is nice, but has caused a great deal of strange porting problems in the past requiring the addition of many #define and #ifdef statements. Pointers are of unknown length so care must be taken not to do pointer math. The non-portable types int/long etc. should only be used as return values for pass/fail/error functions.

Testing

The v3_TestModule() functions must test all the functions in a file, causing all cases to be taken within the functions and all outcomes and errors to be generated. Cosm will also use the "well tested, infrequent release" philosophy, not "rapid release, let the user debug it" one. All code should always be kept in a state where it can be compiled without errors/warnings. Never submit code that you can't compile. The v3_TestModule() code will also serve as the example code, so it must be complete and correct.

Comments

Comments, comments, comments. In general anything more complex then a for( ... ) loop should have a comment in the code every few lines. Function definitions should also be documented (in the header file) with the parameters, return values, and error conditions. Any { } block longer then ~30 (1/2 page) lines should have a comment at the closing }

Header Files

Header files for a given C file should contain all defines, structs, and function prototypes for the code. Functions should appear in the .c file in the same order they appear in the .h file, the 'helper' functions (v3_*) after main interface functions (v3*). Defines should be used liberally, and constants directly in the code where the meaning isn't obvious (read: everywhere) should not be used. Any other non-Cosm header files that are needed for the .c file should be included at the top of the .c, not in the .h which should only include it's own information. Only if a .h is needed for the .h to parse should it be included from the .h.

Headers also contain the programmer documentation for a function, what it does, parameters, and expected return values or errors. No one should ever have to find and then dig around .c files to be able to use a function, and so any documentation should be in the header. All things will eventually be documented in non-programmer language in other formats.

Version Control

Version numbers for any code or files must be incremented when any change is made. Problems caused by a non-incremented version number can be quite difficult to track. Luckily, CVS does a wonderful job of this. CVS also does a great job of tracking changes and history. Make sure your messages on commited code are descriptive. Do no use the top of a .c file for the history, it quickly takes over the entire file.

#ifdef Usage

System specific #ifdef for OS/CPU is only allowed in utility level libraries. The only #ifdefs in the main level of code should be for a 32/64 bit constant number definition. When doing any test for CPU/OS type, use globally defined OS_TYPE and CPU_TYPE to switch off of e.g. #if ( OS_TYPE == OS_MACOSX ) - this is more readable to people not familiar with each compilers/os/cpu, and so it is less likely to lead to confusion.

Naming Conventions

All names should make sense and be long enough for the code to be self documenting

v3
All Cosm variables, functions, structures, and defines start with either "v3_", "v3", "V3_", or "_V3_" during pre-release development. This prefix will change as the phases change to avoid any unintended use of legacy functions.

Source File Names
file.c and file.h should have the same base name

Functions
All functions should begin with a capital letter and each word within a function name should be capitalized, e.g. ReadConfig( char * filename );

Library Functions
All user level functions should begin with "v3", The module pneumonic, and each word within a function name should be capitalized, e.g. v3DFSSpace( u64 userid ); All low level functions should begin with "v3_" and be named in a similar manner e.g. v3_DFSSpace( ... );.

Local Variables
Loop variables can be one letter, e.g. u32 x, y, z; anything else should be descriptive and lower case "_" should be used between words in local variables. e.g. u64 word_count;

Global Variables
Don't even think about it. No global variables exist in Cosm (well, just 2). No, no, no, and no. P.S. No. Users will need them in cores and modules however, so they aren't evil.

Structures
Structures should be named in all upper case with _'s e.g. struct v3_PACKET_HEADER {...}; Structure members should be lower case as per Local Variables. Note that Cosm structures start with v3_ and not V3_ which is the distinction between structs and a defines.

Defines
Defines are in all upper case as per C standard e.g.
#define V3_FOO 30

Macros
Macros are in all upper case beginning with "_V3_" e.g.
#define _V3_BAR( x ) run_bar( x ); return;

Code Style

Liberal Spacing
DontCrunchTheCodeAllTogether( void ); e.g. for( i = 0 ; i < 42 ; i += 3 ) Each statement should be on it's own line. Statements that are long should be wrapped to the next line at the 78th column or less so that printing is possible. Any logic more then one line (for, while, if-else) should use a set of { } for clarity. funtions( x ) and macros( 3 ) do not have a space between the function name and firt paren. Typecasts (ascii *) also do not have the extra spaces to that they can be distinguished from parameters.

Indenting
2 spaces for every level of logic, and 2 additional spaces when a line is wrapped. Tabs should never be used, as they are editor dependant.

Width
Keep everything within the standard 78 columns, wrap lines when needed. Some of the code will need to be printed, snail-mailed, or OCR'd into other countries. There is one important exception to this, in the html documentation for functions the width of example code must be 70 columns or less, due how man pages are displayed.

Example:

-- blah.h --

#ifndef V3_BLAH_H
#define V3_BLAH_H

/* include everything we need */

#include "cputypes.h"
#include "cosmio.h"

#define V3_FOO_ERROR -3

s32 v3_TestBlah( void );

#endif

-- blah.c --

#include "blah.h"

s32 v3_TestBlah( void )
{
  s32 error;

  /*
    run all tests
    this is a multi-line comment
  */

  if ( /* test fails */ )
  {
    error = V3_FOO_ERROR;
  }
  else /* this is the else format */
  {
    error = V3_PASS;
  }

  /* foo failed - this is single line comment */
  return( error );
}

int v3Blah( void )
{
  u64 apple;
  s32 e;

  /* use the macro to set apple */
  _V3_SET64( apple, 01234567, 89ABCDEF )

  v3PrintA( (ascii *) "A is for Apple = 0x%016Y\n", apple );

  if ( foo = v3_TestBlah() );
  {
    v3PrintA( (ascii *) "Test Blah Failed = %i\n", foo );
    return( V3_FAIL );
  }

  return( V3_PASS );
}

General Conventions

Return Values
When a pass/fail needs to be returned, zero should be pass, nonzero a failure. V3_PASS and V3_FAIL exist for this reason, so use them. This is so that all code can be of the general form

if ( ( error = test() ) != V3_PASS )
{
  /* deal with the problem and recover */
}

When pointers are returned, NULL is failure, anything else should be a considered valid.

if ( ( pointer = test() ) == NULL )
{
  /* deal with the problem and recover */
}

When return( ... ) is used, always use the ()'s.

int, char, short
int, char, short etc. are not used in the APIs. All parameters are of the universal cputypes.h formats. int can be used internally (with care) for any temp variables, for/while loops, system calls, etc.

Parameter order
When a function takes parameters, they should be (destination, source) similar to ( a = b ).

Additional keywords (for syntax highlighting):
u8 u16 u32 u64 u128 s8 s16 s32 s64 s128 f32 f64 ascii unicode

Credit Where Credit is Due
A master CREDITS(.txt) file will be maintained where a list of names of the people that made a significant contribution to writing the code. People will be divided into categories as implementers, porters, and miscellaneous.

Common Pitfalls

Error Code Checking
All function error codes must be checked and acted on accordingly.

Network Buffers and Memory Overruns
Buffer overrun and bad memory allocation should always be checked for.

Use of Uncleared Structs
Structures need to be either v3MemeAlloc'd or v3MemSet to zero before use. Structures on the local stack will have random values when the function is entered.

Pointer Math
Never cast a pointer to a u32 or u64 to do pointer math. You do not know if the pointers will be 32 or 64bits wide on the destination chip, and there is no good reason to do pointer math outside of the ASM tweaked (and therefore CPU specific) cores.

NULL Pointers
Check for NULL pointers before all operations. Be especially careful of library functions i.e. memcpy() as many machines have libraries that have problems with NULLs.

Typecasting
Most things should be typecast normally, like (ascii *) stings. However, s64, u64, s128, and u128 cannot be typecast because they are structures on some systems.

Memory Leaks
Always Make sure any memory allocation has a matching memory free.

by Adam L. Beberg

© Copyright Adam L. Beberg 1999. All rights reserved. Cosm (tm) is a trademark of Adam L. Beberg. Any use of the information presented here is subject to the terms in the Cosm License.
Document last modified: Jan 15, 2000