Introduction

The style and layout to be used for programming on cmgui, cmulgeom, gx, mulgraph, emap and related projects.

For the examples in this document, < and > are used to enclose things that depend on the instance.

For questions, clarification or justification see David Bullivant.

Layout

General

Module

In general, a module is built around a data structure or group of data structures and contains the type definitions (.h) and the function prototypes (.h) and function definitions (.c) for manipulating the types. For a widget module, there may also be a .uil file.

Notes:

.h File

/*******************************************************************************
FILE : <module_name>.h

LAST MODIFIED : <day> <month as name> <year including century>

DESCRIPTION :
<A description of what the module is for and what it can do.>
==============================================================================*/
#if !defined (<module name in capitals>_H)
#define <module name in capitals>_H

#include <<system includes>>
#include "<project includes specified relative to project base directory eg.
graphics/finite_element.h>"

/*
Global types
------------
*/
<type definitions>

/*
Global variables
----------------
*/
<variable declarations. Should all be storage class extern>

/*
Global functions
----------------
*/
<prototypes for the functions that can be used by other modules>
#endif

Notes:

.c File

/*******************************************************************************
FILE : <module_name>.c

LAST MODIFIED : <day> <month as name> <year including century>

DESCRIPTION :
<A description of what the module is for and what it can do.>
==============================================================================*/
#include <<system includes>>
#include "<project includes specified relative to project base directory eg.
graphics/finite_element.h>

/*
Global variables
----------------
*/
<variable declarations. Same as in .h except without extern and with
initializers>

/*
Module types
------------
*/
<declarations for types which are only used within the module. Should be
storage class static>

/*
Module variables
----------------
*/
<declarations for variables which are global to this module only. Should be
storage class static>

/*
Module functions
----------------
*/
<definitions for functions which are used in this module only. Should be
storage class static>

/*
Global functions
----------------
*/
<definitions for the functions prototyped in .h>

Notes:

.uil File

!*******************************************************************************
!FILE : <module_name>.uil
!
!LAST MODIFIED : <day> <month as name> <year including century>
!
!DESCRIPTION :
!<A description of what the widgets are for.>
!===============================================================================
module <module_name>_module
names=case_sensitive

procedure
<names of the procedures used in the uil code and assigned in the C code. On
separate lines>

identifier
<names of the identifiers used in the uil code and assigned in the C code. On
separate lines>

object
<the widget definitions>

end module;

Notes:

struct Declaration

Top Level

struct <Struct_name>
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>

DESCRIPTION :
<A description of what the type is for.>
==============================================================================*/
{
<struct body>
}; /* struct <Struct_name> */

Notes:

As a Field

struct
{
<struct body>
} <field_name>;

Notes:

union Declaration

As for struct, but with struct replaced by union.

enum Declaration

enum <Enum_type>
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>

DESCRIPTION :
<A description of what the type is for.>
==============================================================================*/
{
<ENUM_CONSTANTs on separate lines>
}; /* enum <Enum_type> */

Notes:

Function Prototype

<return type> <function_name>(<parameter list>);
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>

DESCRIPTION :
<A description of what the function does and what the parameters are.>
==============================================================================*/

Notes:

Function Definition

<return type> <function_name>(<parameter list>)
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>

DESCRIPTION :
<A description of what the function does and what the parameters are.>
==============================================================================*/
{
<variable declarations>

ENTER(function_name);
<function body>
LEAVE;

return (<return_variable>);
} /* <function_name> */

Notes:

Variable Declarations

int anatomical_list_length,coordinate_list_length,field_list_length,i;
struct FE_node_field *node_field_1,*node_field_2;
struct FE_node_field_component *component_1,*component_2;
struct FE_node_field_info *field_info;
struct FE_node_field_info_list_item *item;
struct FE_node_field_list_item *node_field_item;

if Statement

if (<condition>)
{
<then clause>
}
else
{
<else clause>
}

Notes:

do Statement

do
{
<do body>
} while (<condition>);

Notes:

while Statement

while (<condition>)
{
<while body>
}

Notes:

for Statement

for (<initialize>;<terminate>;<update>)
{
<for body>
}

Notes:

switch Statement

switch (<expression>)
{
case <case_label1>: case <case_label2>:
{
<case clause>
} break;
default:
{
<default clause>
} break;
}

Notes:

Debug Statements

Debug statements should be preceded by the comment

/*???debug */
and the indentation should be restarted in column 1.

Comments

Apart from the special comments shown above, all comments should be on separate lines and be indented at the current level of indentation. Temporary comments querying existing code or suggesting enhancements should be of the form

/*???<programmer identification> . <text> */

Style

return

The return statement should only ever be the last statement in a function. There should be at most one return statement per function.

exit

The exit statement should not be used.

break

The break statement should only be used to end clauses in a switch statement (see above).

continue

The continue statement should not be used.

goto

goto should not be used.

elseif

elseif should not be used.

typedef

typedef should not be used for struct's, union's or enum's.

Memory Allocation

The macros ALLOCATE and DEALLOCATE (in general/debug.h) should be used for all memory allocation and deallocation (no malloc or free).

ENTER and LEAVE (in general/debug.h)

ENTER should be the first statement and LEAVE should be the second to last or last (if no return) statement in every function.

Comments

Comments should be factual, and should only attempt humour if they are bloody funny.

Clarity

Code should not be obscure. One tactic to help achieve this is to only do one thing per statement, e.g.,

a[i]=b;
i++;
instead of
a[i++]=b;

Lists

Macros have been written (graphics/list.h) for creating and using lists. These macros should be used for all lists.

Casting NULL

NULL should always be caste to the appropriate type.

Using reference counting

Reference counting should be carried out using the macros ACCESS, DEACCESS, and REACCESS on objects that need it. When this is done, the following rules apply: