$Header$
First a little background: SWIG was started in 1995 as a one-person project and continued in this mode until about 1998 (at which point development all but stopped due to some sort of post-dissertation shock syndrome). Unfortunately, as a result, the state of the code can best be described as being a huge hacked up C++ disaster. A working disaster, but a disaster nonetheless.
The primary goal of future SWIG development is to reengineer the original system and address many of its design flaws and to produce what can best be described as a highly extensible and modular compiler framework. To this end, there are a few things I want to do. First, I want to restructure SWIG as a collection of loosely coupled modules written in either ANSI C or scripting languages. Second, I want the system to be minimalistic in its use of data structures and interconnections (e.g., almost all data in the new system is passed around in hash tables for instance). The primary reason for this is that the fewer data structures there are, the less you have to remember. Finally, I was to reevaluate the whole idea of what a SWIG module is and expand the definition to include just about anything from parsers, preprocessors, optimizers, interface editors, and code generators.
The rest of this document describes the basics of how to develop code for SWIG and a few useful guidelines.
Modules should make every attempt to use only those functions described in the POSIX.1 standard. This includes most of the functions contained the Kernighan and Ritchie C programming book. Use of operating system dependent functionality such as socket libraries should always be included inside a conditional compilation block so that it can be omitted on problematic platforms. If you are unsure about a library call, check the man page or contact Dave.
When choosing a module name, please pick a name that is not currently in use. As a general convention, the first letter of a module name is capitalized such as "Perl". Alternatives such as "perl" or "PERL" should be avoided. In certain instances, the first two letters may be capitalized as in "CParse." The exact usage of this is somewhat inconsistent and isn't terribly important--just make sure the first letter is capitalized. Also, module names should not start with numbers, include underscores or any other special non-alphanumeric characters.
All header files should have include guards and be C++ aware. For example:
#ifndef _SWIGPERL_H
#define _SWIGPERL_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* You're declarations here */
...
#ifdef __cplusplus
}
#endif
#endif /* _SWIGPERL_H */
To minimize compilation time, please include as few other header files as possible.
The structure of each file should include a short copyright message, author information, a CVS revision tag, and an abstract like this:
/* -----------------------------------------------------------------------------
* Simplified Wrapper and Interface Generator (SWIG)
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1999-2000, University of Chicago.
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
static char cvsroot[] = "$Header$";
/* -----------------------------------------------------------------------------
* include.c
*
* This file implements the functions used to locate and include files in
* the SWIG library. Functions for maintaining the library search path are
* also located here.
* ----------------------------------------------------------------------------- */
#include "swig.h"
/* Declarations */
typedef struct {
int x, y;
} Foo;
...
/* Private Declarations (used only in this file) */
static int avariable;
...
/* Functions */
...
The CVS revision tag should be placed into a static string as shown
above. This adds the revision information to the SWIG executable and
makes it possible to extract version information from a raw binary
(sometimes useful in debugging). Copyright messages do not need to be
attributed to the University of Chicago provided that the module is
released under an Open Source copyright that allows redistribution.
As a general rule, files start to get unmanagable once they exceed about 2000 lines. Files larger than this should be broken up into multiple files.
/* Simple bottom-up program */
#include <stdio.h>
int foo(int x, int y) {
/* Implement foo */
...
}
int bar() {
...
foo(i,j);
...
}
...
int main(int argc, char **argv) {
...
bar();
...
}
This choice of design is somewhat arbitrary however it has a number of
benefits particular to C. In particular, a bottom-up design generally
eliminates the need to include forward references--resulting in
cleaner code and fewer compilation errors.
/* -----------------------------------------------------------------------------
* void Swig_add_directory(DOH *dirname)
*
* Adds a directory to the SWIG search path.
* ----------------------------------------------------------------------------- */
void
Swig_add_directory(DOH *dirname) {
...
}
As for the function declaration itself, the return type and specifiers
(extern or static) should appear on a separate line followed by the
function name as shown.
In general, the module name should match the name of the module subdirectory and the function name should be in all lowercase with words separated by underscores.Preprocessor_define() Swig_add_directory()
typedef struct SwigScanner {
...
} SwigScanner;
typedef struct LParseType {
...
} LParseType;
In this case, both the name of the module and the type should be capitalized. Also, whenever
possible, you should use the "typedef struct Name { ... } Name" form when defining new
data structures.
Separate words in a constant should be separated by underscores as shown.#define SWIG_TOKEN_LPAREN 1
typedef struct SwigScanner {
DOH *text; /* Current token value */
DOH *scanobjs; /* Objects being scanned */
DOH *str; /* Current object being scanned */
char *idstart; /* Optional identifier start characters */
int next_token; /* Next token to be returned */
int start_line; /* Starting line of certain declarations */
int yylen; /* Length of text pushed into text */
DOH *file; /* Current file name */
} SwigScanner;
typedef struct Foo {
int line;
} Foo;
It is better to simply hide the implementation of Foo and provide an interface like this:
There are many good reasons for doing this not the least of which is that it allows you to change the internal representation of Foo without breaking everyone else's module (or at the very least having to recompile the universe).typedef struct Foo Foo; extern int Foo_getline(Foo *f); extern void Foo_setline(Foo *f, int line);