Coding Style Guide
Written by:Rick Caudill
Last Updated:Dec 19, 2004


This document explains the coding style that is to be used in Syllable. This document should be followed when you submit any new code to the core components of the OS, including the kernel, appserver, and the various API libraries that are part of the core distribution.

This document is not finished and will change as the code base gets bigger.

Applications that will not be in the base distribution do not have to follow these guidelines. However, it is recommended that application developers follows these guidelines so that all Syllable code is reasonably similar.


All variable names and struct/class members should be constructed from one or more type prefixes, followed by a mixed-case descriptive name. The only exception to this rule is counter variables and other iterators typically used in loops.

Rationale: The prefixes are a great help when reading others' code (and your own a few moments after it is written). It also makes it easier to search for members and variables since they tend to be more unique.

Counter variables and other iterators don't have to follow the coding standards. It is legal to write:

 1 for ( int i = 0 ; i < 16 ; ++i )
 2 {
 3    DoStuff();
 4 }

Type prefixes:

  • n - Any integer type (char, short int, long, long long)
  • v - Floating-point types (float, double, long double)
  • s - Structures
  • c - Classes
  • e - Enums
  • u - Unions
  • h - Handles (variables that are never de-referenced, like file descriptors and message ports)
  • f - Functions (only used in conjunction with the p prefix to build function pointers)

Qualifier prefixes:

  • p - Pointer to
  • a - Array of

And, no rule without exceptions:

  • z - Zero-terminated string

All variables should be prefixed with one of the type prefixesl. Examples:

 1 int nSize;
 2 float vScale;
 3 struct stat sStat;
 4 Rect cBoundary;

If the variable is a pointer or an array, the type prefix should be preixed with a qualifier:

 1 int anSizes[256];
 2 float* pvScale;
 3 struct stat* psStat;
 4 Rect acRectangles[16];

In addition to the type prefix(es), all class members should be prefixed with m_ to distinguish them from local variables in member functions. Structure members should normally be prefixed with an abbreviation of the structure name. This is not required, but since many structures have matching member names, and structure members often match other variable names, it is much easier to search for a structure member if it has a prefix.

Global variables and module variables should have a g_ prefix. Global variables should (for obvious reasons) be very rare, especially in C++ where there often are better solutions (like singleton classes).

Member functions should have mixed-case names, while global function names should be all lower-case with words separated by underscores. Example:

 1 int g_my_global_stat_function( void );

Defines, macros, and enum items should have uppercase-only names with words separated by underscores. Example:

 1 #define G_MY_PI_VALUE 3.14159

Indentation and Tab Size

We have come up with a good solution for indentation and tab size. Indentation of anything is one tab in size, and the tab size is whatever you want to make it.

Example Using Tabs
 1 if ( a == 2 )
 2 {
 3    printf( "a is 2\n" );  //one tab over
 4 }
 6 if ( a != 2 )
 7 {
 8    printf( "a is not 2\n" );  //one tab over
 9    printf( "it might be 3\n" );  // one tab over
11    if ( a != 3 )
12       printf( "No, not 3 either\n" );  // two tabs over
13 }


Code blocks start on a new line, and align with the beginning of the statement above. The only exception to this rule is a single statement when a code block is not required. See the above code listing for examples.


Brackets should be at the same indentation level as the switch statement. Each case label should be one indentation level deeper than the switch statement. The code for each case should be one indentation level deeper than the case label. Example:

Example of Switch/Case
 1 switch( nAction )
 2 {
 3    case CRASH_AND_BURN:
 4       SetFire();
 5       Crash();
 6       break;
 7    default:
 8       printf( "Unknown command: %d\n", nAction );
 9       break;
10 }


There should NOT be any spaces between a function name and the opening parenthesis for the function parameter. For other constructs like for/while, switch/case, if, etc., you may include a space if desired.


Just keep in mind that the API documentation is generated with Doxygen. Write comments so that as much documentation can be automatically extracted.

Code Cleanliness

There is no standard for code cleanliness yet, but we suggest you use either GNU Indent or Artistic Style to clean up your code.

Header Files

The standard format for inclusion safeuards is: __F_(DIRECTORY FILE IS LOCATED IN)_(FILENAME)_H__


  • __F_GUI_WINDOW_H__ would be the inclusion guard for /include/gui/window.h
  • __F_STORAGE_FSNODE_H__ would be the inclusion guard for /include/storage/fsnode.h
  • __F_CODEVIEW_CODEVIEW_H__ would be the inclusion guard for /include/codeview/codeview.h


As Syllable gets bigger and includes more and more classes, changes to those classes will inevitably break binary compatibility. Here are a couple of guidelines that we have come up with in our Sysiphean fight against this inevitability. Hey, every little bit helps.

All classes should have a separate class for private members, like so:

Example class using Private Member Class
 1 class Window : public os::Looper
 2 {
 3 public:
 4    Window( const std::string& cTitle );
 5    ~Window();
 6 private:
 7    class Private;
 8    Private* m;
 9 };
11 class Window::Private
12 {
13 public:
14    Private()
15    {
16       m_cTitle = "";
17    }
19    std::string m_cTitle; // Holds the title name of the window
20 };
22 Window::Window( const std::string& cTitle ) : os::Looper()
23 {
24    m = new Private;
25    m->m_cTitle = cTitle;
26 }
28 Window::~Window()
29 {
30    // Do not forget to delete the private class.
31    delete m;
32 }

The above is not real code for the Window class.

All classes should have five to ten extra virtual functions, even if they are all empty, so that adding a virtual function won't break compatibility. When you want to add another virtual method, start with the highest reserved method, and rename it to whatever you want. This way, you and everyone else will know that you added a new virtual method.

Empty virtual functions should be named using the form: __(class abbreviation)_reserved(number)__


 1 class Window : public os::Looper
 2 {
 3 public:
 4    Window( const std::string& );
 5    virtual void __WI_reserved1__();
 6    virtual void __WI_reserved2__();
 7    virtual void __WI_reserved3__();
 8    virtual void __WI_reserved4__();
 9    virtual void __WI_reserved5__();
10    virtual void __WI_reserved6__();
11    virtual void __WI_reserved7__();
12    virtual void __WI_reserved8__();
13    virtual void __WI_reserved9__();
14    virtual void __WI_reserved10__();
15 };

Other/Miscellaneous Stuff

Using the keyword const is taught early on in C++ programming classes. It is important because it tells the programmer that the const data cannot change. Declaring something constant is usually up to the programmer, but the rule of thumb is that if the data shouldn't be changed, then it should be declared constant. Examples:

 1 const float PI = 3.14159
 2 void SetTitle( const std::string& cTitle );
 3 bool GetSelected() const;

GCC 3.0 came with a more strict and more standard-like standard namespace, so here are a couple of rules that you have to follow.

You can declare the standard namespace completely:

 1 using namespace std;

You can declare the parts of the namespace you need:

 1 using std::cin;
 2 using std::cout;
 3 using std::string;
 4 using std::endl;

You can put std:: in front of anything you need:

 1 std::cout << "Hello World" << std::endl;
 2 std::string cString = "Hello World";
 3 std::vector < std::string > tList;


All questions, comments, or problems with this document can be e-mailed to the Syllable Development List.