User Guide for the CDT

Benoît Dupont de Dinechin

1. Synopsis

1.1. Extract, Configure, Build, Install

The CDT is configured like a GNU package. It has a autoconf-generated configure script and a automake-generated Makefile.in.

The normal use of CDT is to install its build products for use by client applications:

cd /tmp
svn co https://svn.cdt.codex.cro.st.com/svnroot/cdt/trunk/CDT
mkdir build && cd build
../CDT/configure --prefix=/my/local/install
make all check install

By default, GCC compilation with -fshort-enums -Wall -O2.

1.2. Using from a Client Package

In the client package's configure.ac:

CDT_PREFIX=${with_cdt-$prefix}
CPPFLAGS="-I$CDT_PREFIX/include $CPPFLAGS"
LDFLAGS="-L$CDT_PREFIX/lib $LDFLAGS"
AC_CHECK_HEADER(CCL.h,,[AC_MSG_ERROR([CCL.h not found! Use --with-cdt argument.])])
AC_CHECK_LIB(CCL,CCL_INIT,,[AC_MSG_ERROR([libCCL not found! Use --with-cdt argument.])])

In the client package's main driver:

int main(int argc, char *argv[]) {
  int status = 0;
  CCL_INIT();
  // ...
  CCL_FINI();
  return status;
}

1.3. More on CDT Libraries Usage

For each CDT library LIB (either CCL or CAL):

2. Coding Style of CDT Libraries

2.1. Structure and Members Names

The structures are typically defined like:

typedef struct MyStruct_ {
  int16_t FOO;
  int16_t BAR;
} MyStruct_, *MyStruct;

In order to support a function-like syntax for structure member access, macros are often defined and used like this:

#define MyStruct_FOO(this)      (0, (this)->FOO)
#define MyStruct__FOO(this)     (&(this)->FOO)
#define MyStruct_BAR(this)      (0, (this)->BAR)
#define MyStruct__BAR(this)     (&(this)->BAR)
...
MyStruct_ *array = calloc(sizeof(MyStruct_), 2);
MyStruct myStruct1 = &array[0], myStruct2 = &array[1];
*MyStruct__FOO(myStruct1) = MyStruct_FOO(myStruct2);
++*MyStruct__BAR(myStruct2);

Using function-like syntax for structure member access makes the source code easier to change, whether doing global searches and replace or moving around structure members.

2.2. Variable and Function Names

For pointers to structure variables these, use mixedCase names with first letter in lower case and a name that corresponds to the structure. Keep the trailing '+_+' for the structure variables and prepend a leading '+_+' to the pointer to structure pointer variables:

MyStruct_ myStruct_;
MyStruct myStruct = &myStruct_;
MyStruct *_myStruct = &myStruct;

Method-like functions use the structure name as a prefix, followed by an action name in mixedCase with first letter in lower case:

void MyStruct_swapFooBar(MyStruct this) {
  int16_t temp = MyStruct_FOO(this);
  *MyStruct__FOO(this) = MyStruct_BAR(this);
  *MyStruct__BAR(this) = temp;
}

2.3. Iteration Macros for Containers

There is a iteration macro defined for (almost) each CDT container:

typedef struct Point_ { int X, Y; } Point_, *Point;
IDList_Ctor(idlist, NULL);
...
Point pair = IDList_push(idlist, sizeof(Point_));
...
IDList_FOREACH(idlist, Point_, pair) {

printf("(d)\t", pair->X, pair->Y); } IDList_ENDEACH;

Such macros can then be used to define typed iteration macros:

#define BasicBlock_FOREACH_Operation(this, operation) \
  IDList_FOREACH(BasicBlock_idlist(this), Operation_, operation)
#define BasicBlock_ENDEACH_Operation \
  IDList_ENDEACH;

3. Memory Allocation in CDT Libraries

3.1. Custom Memory Allocation

A popular memory allocation policy is to buffer the calls to the system malloc() and free() with a memory pooling system:

3.2. CDT/BSL Memory Allocator

Selected Memory methods:

struct Memory_;
typedef struct Memory_ Memory_, *Memory;
Memory Memory_new(Memory parent, size_t pooled size);
void *Memory_alloc(Memory this, size_t size);
void Memory_free(Memory this, void *address);
Memory Memory_delete(Memory this);

3.3. Modular Programming

The source code for a library sould be in its own subdirectory, and should be decomposed into modules. A module is the minimal unit of testing and is composed of several source files:

It is good practice to have each module define its namespace: all symbols names should be prefixed by Module.

3.4. Subtyping Containers

3.5. Embedding Containers

3.6. Memory Management

3.7. Exception Handling

3.8. Serialization to XML