tinyswig
A tiny wrapper generator for the Transterpreter.
===================================================
Copyright (C) 2007 Matthew C. Jadud

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
===================================================

Tinyswig is a tiny wrapper generator. What this means is that it allows developers working with the Transterpreter to quickly take pieces of C code and "wrap it up" so that they can then use it from their occam-pi programs.

Tinyswig has a fairly simple command-line interface. As of 20070528:

------------------------------------
prompt$ ./tinyswig -h 
tinyswig [ <option> ... ] <first-file> [<additional-files>] ...
 where <option> is one of
  -v, --version : Get the current version of TinySwig
  -p <the-prefix>, --prefix <the-prefix> : Specifies a prefix for the generated occam-pi PROC names.
  -n, --no-prefix : Suppresses the generation of prefixes on occam-pi PROC names.
  -c <the-c-filename>, --c-filename <the-c-filename> : Output name for the generated C file. Default is 'external_special_hooks.c'.
  -o <the-occam-filename>, --occam-filename <the-occam-filename> : Output name for the generated occam-pi PRAGMAs.
  --help, -h : Show this help
  -- : Do not treat any remaining argument as a switch (at this level)
 Multiple single-letter switches can be combined after one `-'; for
  example: `-h-' is the same as `-h --'
------------------------------------

USING TINYSWIG
==============
Documentation of tinyswig's usage takes the form of an extended example. 

A typical use of tinyswig is to take one or more .c files and generate a set of wrappers for those files. For example, let's assume you have a C file that looks like:

------------------------------------
/* file: inc.c */

void increment (int w[]) {
  int x = w[0];
  x = x + 1;
}
------------------------------------

The procedure 'increment' takes in an occam-pi workspace, expects a single integer to be passed to it, and increments that integer. To use this function from occam-pi, we need to provide some compiler directives; tinyswig simplifies that process.

If we run tinyswig on this file directly, nothing interesting happens. Sure, tinyswig outputs some files ("external_inc_hooks.c" and "external_inc_pragmas.occ"), but both of these files are empty for all intents and purposes. This is because none of the C code in the file "inc.c" is annotated for use by tinyswig.

If we call tinyswig on this directly, we get three files as a result. The command line looks like:

prompt$ tinyswig inc.c

and the three files look like:

[FILE: external_inc_hooks.c]
------------------------------------
/* File generated by tinyswig on Monday, May 28th, 2007 11:27:12pm */
/* tinyswig is a part of the Transterpreter toolchain */

#include "inc.h"

/* There are 1 external functions to be hooked in. */
void *external_function_hooks[1];

void *get_special_hooks()
{
        external_function_hooks[0] = increment ;
        return external_function_hooks;
}
------------------------------------


[FILE: external_inc_pragmas.occ]
------------------------------------
-- File generated by wicked Scheme program tinyswig on Monday, May 28th, 2007 11:27:12pm 
-- tinyswig is a part of the Transterpreter toolchain

#IF NOT DEFINED (GUARD.externalincpragmasocc.1180391232)
#DEFINE GUARD.externalincpragmasocc.1180391232 TRUE

#PRAGMA EXTERNAL "PROC C.tvmspecial.0.ffi.increment () = 0"
INLINE PROC ffi.increment ()
  C.tvmspecial.0.ffi.increment ()
:

#ENDIF
------------------------------------


[FILE: inc.h]
------------------------------------
/* File generated by tinyswig on Monday, May 28th, 2007 11:27:12pm */
/* tinyswig is a part of the Transterpreter toolchain */

void increment (int w[]);
------------------------------------

What tinyswig has done is generate a wrapper for use in our occam-pi programs. However, it has done so *incorrectly*. This is because tinyswig cannot know what kinds of information you are passing to the procedure 'increment'. Therefore, you must annotate all of the functions you want tinyswig to wrap so it can make sense of them. A corrected version of "inc.c" therefore looks like:

------------------------------------
/* file: inc.c */

void increment (int w[]) { /* INT v */
  int x = w[0];
  x = x + 1;
}
------------------------------------

Now, when we run tinyswig over this file, the pragmas look a little different:


[FILE: external_inc_pragmas.occ]
------------------------------------
-- File generated by wicked Scheme program tinyswig on Monday, May 28th, 2007 11:33:05pm 
-- tinyswig is a part of the Transterpreter toolchain

#IF NOT DEFINED (GUARD.externalincpragmasocc.1180391585)
#DEFINE GUARD.externalincpragmasocc.1180391585 TRUE

#PRAGMA EXTERNAL "PROC C.tvmspecial.0.ffi.increment (INT v ) = 0"
INLINE PROC ffi.increment (INT v )
  C.tvmspecial.0.ffi.increment (v)
:

#ENDIF
------------------------------------

This is important; now, the occam-pi compiler can correctly lay out the call to the foreign C code, and correctly pass a single integer value through to the C procedure "increment". 

WHAT ELSE DO YOU NEED TO DO?
==========================
Once you have run tinyswig over your code (successfully), you're nearly ready to use your C code from within occam-pi. 

1. Compile your hooks.
----------------------
First, you'll need to either compile your hooks as a dynamically loadable library (on large platforms like desktops), or you'll need to compile them into the Transterpreter wrapper for whatever platform you're working on. Either way, documentation on that process can be found on the Transterpreter website. 

Potential starting points in this quest include:

http://www.transterpreter.org/wiki/Porting/StaticCodeStaticFFI

and in the documentation directory of the source tree:

trunk/documentation/manual/FFI.html

2. Include your hooks.
----------------------
Second, in your occam-pi program, you'll need to #INCLUDE the PRAGMA file. This will give the compiler and linker enough information to generate the correct bytecode sequences for the Transterpreter to reach out into your C library and invoke the corresponding C procedure.