I.3   C Coding Conventions

These conventions are divided into the following categories:

I.3.1   C Module Layout

A module is any unit of code that resides in a single source file. The conventions in this section define the standard module heading that must come at the beginning of every source module following the standard file heading. The module heading consists of the blocks described below; the blocks should be separated by one or more blank lines.

After the modification history and before the first function or executable code of the module, the following sections are included in the following order, if appropriate:

The format of these blocks is shown in the following example (which also includes the file heading specified earlier).

Example I-2:  C File and Module Headings

/* fooLib.c - foo subroutine library */ 
 
/* Copyright 1984-1995 Wind River Systems, Inc. */ 
 
/* 
modification history 
-------------------- 
02a,15sep92,nfs  added defines MAX_FOOS and MIN_FATS. 
01b,15feb86,dnw  added routines fooGet() and fooPut(); 
                 added check for invalid index in fooFind(). 
01a,10feb86,dnw  written. 
*/ 
 
/* 
DESCRIPTION 
This module is an example of the Wind River Systems C coding conventions. 
... 
INCLUDE FILES: fooLib.h 
*/ 
 
/* includes */ 
 
#include "vxWorks.h"  
#include "fooLib.h"  
 
/* defines */ 
 
#define MAX_FOOS        112  /* max # of foo entries */ 
#define MIN_FATS        2     * min # of FAT copies */ 
 
/* typedefs */ 
 
typedef struct fooMsg       /* FOO_MSG */ 
    { 
    VOIDFUNCPTR func;        /* pointer to function to invoke */ 
    int arg [FOO_MAX_ARGS];  /* args for function */ 
    } FOO_MSG; 
 
/* globals */ 
 
char *    pGlobalFoo;        /* global foo table */ 
 
/* locals */ 
 
LOCAL int numFoosLost;       /* count of foos lost */ 
 
/* forward declarations */ 
 
LOCAL int     fooMat (list * aList, int fooBar, BOOL doFoo); 
FOO_MSG       fooNext (void); 
STATUS        fooPut (FOO_MSG inPar);  

I.3.2   C Subroutine Layout

The following conventions define the standard layout for every subroutine.

Each subroutine is preceded by a C comment heading consisting of documentation that includes the following blocks. There should be no blank lines in the heading, but each block should be separated with a line containing a single asterisk (*) in the first column.

RETURNS: N/A
Mention only true returns in this section--not values copied to a buffer given as an argument.

The subroutine documentation heading is terminated by the C end-of-comment character (*/), which must appear on a single line, starting in column one.

The subroutine declaration immediately follows the subroutine heading.2 The format of the subroutine and parameter declarations is shown in I.3.3 C Declaration Formats.

Example I-3:  Standard C Subroutine Layout:

/******************************************************************** 
* 
* fooGet - get an element from a foo 
* 
* This routine finds the element of a specified index in a specified 
* foo.  The value of the element found is copied to <pValue>. 
* 
* RETURNS: OK, or ERROR if the element is not found. 
* 
* ERRNO: 
*  S_fooLib_BLAH 
*  S_fooLib_GRONK 
*/ 
 
STATUS fooGet 
    ( 
    FOO      foo,         /* foo in which to find element */ 
    int      index,       /* element to be found in foo */ 
    int *    pValue       /* where to put value */ 
    ) 
    { 
    ...  
    }

I.3.3   C Declaration Formats

Include only one declaration per line. Declarations are indented in accordance with Indentation, and are typed at the current indentation level.

The rest of this section describes the declaration formats for variables and subroutines.

Variables

unsigned    rootMemNBytes;   /* memory for TCB and root stack */ 
int         rootTaskId;      /* root task ID */ 
BOOL        roundRobinOn;    /* boolean for round-robin mode */

FOO_NODE *  pFooNode;        /* foo node pointer */ 
FOO_NODE ** ppFooNode;       /* pointer to the foo node pointer */

typedef struct symtab   /* SYMTAB - symbol table */ 
    { 
    OBJ_CORE    objCore;        /* object maintanance */ 
    HASH_ID     nameHashId;     /* hash table for names */ 
    SEMAPHORE   symMutex;       /* symbol table mutual exclusion sem */ 
    PART_ID     symPartId;      /* memory partition id for symbols */ 
    BOOL        sameNameOk;     /* symbol table name clash policy */ 
    int         nSymbols;       /* current number of symbols in table */ 
    } SYMTAB;
This format is used for other composite type declarations such as union and enum.

The exception to never using a structure definition to declare a variable directly is structure definitions that contain pointers to structures, which effectively declare another typedef. This exception allows structures to store pointers to related structures without requiring the inclusion of a header that defines the type.

For example, the following compiles without including the header that defines struct fooInfo (so long as the surrounding code never delves inside this structure):


CORRECT:

typedef struct tcbInfo 
    { 
    struct fooInfo *  pfooInfo; 
    ... 
    }  TCB_INFO;


By contrast, the following cannot compile without including a header file to define the type FOO_INFO:


INCORRECT:

typedef struct tcbInfo 
    { 
    FOO_INFO *  pfooInfo; 
    ... 
    }  TCB_INFO;


Subroutines

There are two formats for subroutine declarations, depending on whether the subroutine takes arguments.

int lstFind 
    ( 
    LIST *   pList,   /* list in which to search */ 
    NODE *   pNode    /* pointer to node to search for */ 
    )

STATUS fppProbe (void)

I.3.4   C Code Layout

The maximum length for any line of code is 80 characters.

The rest of this section describes the conventions for the graphic layout of C code, and covers the following elements:

Vertical Spacing

for (i = 0; i < count; i++)
or the switch statement if the actions are short and nearly identical (see the switch statement format in Indentation).

The if statement is not an exception: the executed statement always goes on a separate line from the conditional expression:

if (i > count) 
    i = count;

Horizontal Spacing

status = fooGet (foo, i + 3, &value); 
foo.index 
pFoo->index 
fooArray [(max + min) / 2] 
string[0]

a = (b + c) * 
    (d + e); 
 
status = fooList (foo, a, b, c, 
                  d, e); 
 
if ((a == b) && 
    (c == d)) 
    ...

Indentation

  • subroutine declarations
  • conditionals (see below)
  • looping constructs
  • switch statements
  • case labels
  • structure definitions in a typedef

if ( condition ) 
    { 
    statements 
    } 
else 
    { 
    statements 
    }
The form of the conditional statement with an else if is:

if ( condition ) 
    { 
    statements 
    } 
else if ( condition ) 
    { 
    statements 
    } 
else 
    { 
    statements 
    }

switch ( input ) 
    { 
    case 'a': 
        ... 
        break; 
    case 'b': 
        ... 
        break; 
    default: 
        ... 
        break; 
    }
If the actions are very short and nearly identical in all cases, an alternate form of the switch statement is acceptable:

switch ( input ) 
    { 
    case 'a': x = aVar; break; 
    case 'b': x = bVar; break; 
    case 'c': x = cVar; break; 
    default: x = defaultVar; break; 
    }

Comments

  • Begin single-line comments with the open-comment and end with the close-comment, as in the following:

/* This is the correct format for a single-line comment */ 
 
foo = MAX_FOO;

  • Begin and end multi-line comments with the open-comment and close-comment on separate lines, and precede each line of the comment with an asterisk (*), as in the following:

/* 
 * This is the correct format for a multiline comment 
 * in a section of code. 
 */ 
 
foo = MIN_FOO;

int foo 
    ( 
    int     a,     /* this is the correct format for a */ 
                   /* multiline comment in a declaration */ 
    BOOL    b      /* standard comment at the end of a line */ 
    )
{ day = night;   /* when necessary, a comment about a line */                /* of code can be done this way */ }

I.3.5   C Naming Conventions

The following conventions define the standards for naming modules, routines, variables, constants, macros, types, and structure and union members. The purpose of these conventions is uniformity and readability of code.

aVariableName

A_CONSTANT_VALUE

__INCfooLibh

FOO_NODE *      pFooNode; 
FOO_NODE **     ppFooNode; 
FOO_NODE ***    pppFooNode;

I.3.6   C Style

The following conventions define additional standards of programming style:

Similarly, do not test booleans as non-booleans. For example, where libInstalled is declared as BOOL:


CORRECT:

if (libInstalled)

INCORRECT:

if (libInstalled == TRUE)


  • Use TRUE and FALSE for boolean assignment.
  • Use EOS for end-of-string tests.
  • Use NULL for zero pointer tests.
  • Use IMPORT for extern variables.
  • Use LOCAL for static variables.
  • Use FUNCPTR or VOIDFUNCPTR for pointer-to-function types.

I.3.7   C Header File Layout

Header files, denoted by a .h extension, contain definitions of status codes, type definitions, function prototypes, and other declarations that are to be used (through #include) by one or more modules. In common with other files, header files must have a standard file heading at the top. The conventions in this section define the header file contents that follow the standard file heading.

Structural

The following structural conventions ensure that generic header files can be used in as wide a range of circumstances as possible, without running into problems associated with multiple inclusion or differences between ANSI C and C++.

#ifndef __INCfooLibh 
#define __INCfooLibh 
    ... 
#endif /* __INCfooLibh */
See I.3.5 C Naming Conventions, for the convention for naming preprocessor symbols used to prevent multiple inclusion.

#ifdef __cplusplus 
extern "C" { 
#endif /* __cplusplus */ 
    ... 
#ifdef __cplusplus 
} 
#endif /* __cplusplus */

Order of Declaration

The following order is recommended for declarations within a header file:

  1. Statements that include other header files.

  1. Simple defines of such items as error status codes and macro definitions.

  1. Type definitions.

  1. Function prototype declarations.

Example I-4:  Sample C Header File

The following header file demonstrates the conventions described above:

/* bootLib.h - boot support subroutine library */ 
 
/* Copyright 1984-1993 Wind River Systems, Inc. */ 
 
/* 
modification history 
-------------------- 
01g,22sep92,rrr  added support for c++. 
01f,04jul92,jcf  cleaned up. 
01e,26may92,rrr  the tree shuffle. 
01d,04oct91,rrr  passed through the ansification filter, 
                 -changed VOID to void 
                 -changed copyright notice 
01c,05oct90,shl  added ANSI function prototypes; 
                 added copyright notice. 
01b,10aug90,dnw  added declaration of bootParamsErrorPrint(). 
01a,18jul90,dnw  written. 
*/ 
 
#ifndef __INCbootLibh 
#define __INCbootLibh 
#ifdef __cplusplus 
extern "C" { 
#endif /* __cplusplus */ 
 
/*  
 * BOOT_PARAMS is a structure containing all the fields of the  
 * VxWorks boot line. The routines in bootLib convert this structure 
 * to and from the boot line ASCII string. 
 */ 
 
/* defines */ 
 
#define BOOT_DEV_LEN            20      /* max chars in device name */ 
#define BOOT_HOST_LEN           20      /* max chars in host name */ 
#define BOOT_ADDR_LEN           30      /* max chars in net addr */ 
#define BOOT_FILE_LEN           80      /* max chars in file name */ 
#define BOOT_USR_LEN            20      /* max chars in user name */ 
#define BOOT_PASSWORD_LEN       20      /* max chars in password */ 
#define BOOT_OTHER_LEN          80      /* max chars in "other" field */ 
#define BOOT_FIELD_LEN          80      /* max chars in boot field */ 
 
/* typedefs */ 
 
typedef struct bootParams              /* BOOT_PARAMS */ 
    { 
    char bootDev [BOOT_DEV_LEN];        /* boot device code */ 
    char hostName [BOOT_HOST_LEN];      /* name of host */ 
    char targetName [BOOT_HOST_LEN];    /* name of target */ 
    char ead [BOOT_ADDR_LEN];           /* ethernet internet addr */ 
    char bad [BOOT_ADDR_LEN];           /* backplane internet addr */ 
    char had [BOOT_ADDR_LEN];           /* host internet addr */ 
    char gad [BOOT_ADDR_LEN];           /* gateway internet addr */ 
    char bootFile [BOOT_FILE_LEN];      /* name of boot file */ 
    char startupScript [BOOT_FILE_LEN]; /* name of startup script */ 
    char usr [BOOT_USR_LEN];            /* user name */ 
    char passwd [BOOT_PASSWORD_LEN];    /* password */ 
    char other [BOOT_OTHER_LEN];        /* avail to application */ 
    int  procNum;                       /* processor number */ 
    int  flags;                         /* configuration flags */ 
    } BOOT_PARAMS; 
 
/* function declarations */ 
 
extern STATUS bootBpAnchorExtract (char * string, char ** pAnchorAdrs); 
extern STATUS bootNetmaskExtract (char * string, int * pNetmask); 
extern STATUS bootScanNum (char ** ppString, int * pValue, BOOL hex); 
extern STATUS bootStructToString (char * paramString, BOOT_PARAMS * 
                                  pBootParams); 
extern char * bootStringToStruct (char * bootString, BOOT_PARAMS * 
                                  pBootParams); 
extern void   bootParamsErrorPrint (char * bootString, char * pError); 
extern void   bootParamsPrompt (char * string); 
extern void   bootParamsShow (char * paramString); 
 
#ifdef __cplusplus 
} 
#endif /* __cplusplus */ 
 
#endif /* __INCbootLibh */

I.3.8   Documentation Format Conventions for C

This section specifies the text-formatting conventions for source-code derived documentation. The WRS tool refgen is used to generate reference entries (in HTML format) for every module automatically. All modules must be able to generate valid reference entries. This section is a summary of basic documentation format issues; for a more detailed discussion, see the Tornado BSP Developer's Kit User's Guide: Documentation Guidelines.

Layout

To work with refgen, the documentation in source modules must be laid out following a few simple principles. The file sample.c in installDir/target/unsupported/tools/mangen provides an example and more information.

Lines of text should fill out the full line length (assume about 75 characters); do not start every sentence on a new line.

Format Commands

Documentation in source modules can be formatted with UNIX nroff/troff formatting commands, including the standard man macros and several WRS extensions to the man macros. Some examples are described in the sections below. Such commands should be used sparingly.

Any macro (or "dot command") must appear on a line by itself, and the dot ( . ) must be the first character on the logical line (in the case of subroutines, this is column 3, because subroutine comment sections begin each line with an asterisk plus a space character).

Special Elements

void getName 
    ( 
    int     tid,    /* task ID */ 
    char *  pTname  /* task name */ 
    )
You might write something like the following:

This routine gets the name associated with a specified task ID and copies it to <pTname>.

Note that there is one major exception to this rule. In the subroutine title, do not include the parentheses in the name of the subroutine being defined:


CORRECT:

/************************************************* 
* 
* xxxFunc - do such and such

INCORRECT:

/************************************************* 
* 
* xxxFunc() - do such and such


Avoid using a library, driver, or routine name as the first word in a sentence, but if you must, do not capitalize it.

For more information, see the VxWorks Programmer's Guide: I/O System.

References to documentation volumes should be set off in italics. For general cases, use the .I macro. However, in SEE ALSO sections, use the .pG and .tG macros for the VxWorks Programmer's Guide and Tornado User's Guide, respectively.

Table I-1:  Format of Special Elements


Component
Input
Output (mangen + troff)

library in title 
sysLib.c 
sysLib 
library in text 
sysLib 
(same) 
subroutine in title 
sysMemTop 
sysMemTop() 
subroutine in text 
sysMemTop() 
(same) 
subroutine parameter 
<ptid> 
(same) 
terminal key 
TAB, ESC, CTRL+C
(same) 
publication 
.I "Tornado User's Guide"
Tornado User's Guide  
.pG "Configuration"
VxWorks Programmer's Guide: Configuration  
Tornado User's Guide in SEE ALSO 
.tG "Cross-Development"
Tornado User's Guide: Shell  
emphasis 
\f2must\fP 
must  

Formatting Displays

* .CS 
*     struct stat statStruct; 
*     fd = open ("file", READ); 
*     status = ioctl (fd, FIOFSTATGET, &statStruct); 
* .CE

.TS 
center; tab(|); 
lf3 lf3 
l l. 
Command         | Op Code 
_ 
INQUIRY         | (0x12) 
REQUEST SENSE   | (0x03) 
TEST UNIT READY | (0x00) 
.TE
General stylistic considerations are as follows:

  • Redefine the tab character using the tab option; keyboard tabs cannot be used by tbl tables. Typically the pipe character ( | ) is used.
  • Center small tables on the page.
  • Expand wide tables to the current line length.
  • Make column headings bold.
  • Separate column headings from the table body with a single line.
  • Align columns visually.
Do not use .CS/.CE to build tables. This markup is reserved for code examples.

.IP "FIODISKFORMAT"  
Formats the entire disk with appropriate hardware track and  
sector marks.  
.IP "FIODISKINIT" 
Initializes a DOS file system on the disk volume.


1:  A list containing the definitions of each errno is maintained and documented separately.

2:  The declaration is used in the automatic generation of reference entries.