rink documentation
(c) Ben Summers 1994

This file describes the rink interface for the parent program.



The run time system
~~~~~~~~~~~~~~~~~~~

The rink run time system is supplied as an AOF file. This is currently bound
to the C run time system, but can easily be modified to work with any
lanuage.

The parent must be linked with the run time system and the pointer block.
The pointer block also contains sugar functions for memory allocation and
internal error translation.

A C header file, called rink.h is provided for use with C. It defines
several functions used to control the run time system.


****************************************************************************

rink_load is used to load a segment.

   os_error *rink_load(char *segment_name, char *links_name,
      rink_seghandle *sh, rink_check *ck)

It returns a handle to the segment for use with future calls to the system
in *sh, and returns 0 to signify that no error occured.

The pointer to the error block is either an operting system error, or a rink
internal error. These can be translated by the parent application by using
rinkptr to create a sugar function to a translation function other than the
default.

ck is a pointer to a structure. This must match the header of the file to be
loaded as a check that the file is the right thing to be loading. The
segment will be rejected if the main version number is greater than that
given. The code version number is ignored, and is merely for information
only.

Version numbers can be read with rink_readversion().


****************************************************************************

rink_fn is used to call a child function within the segment by finding it's
address. It is more efficient than rink_call, and allows the compiler to
perform type checking, although it is slightly more complex to use.

Results with sizes > a word can be passed back, and floating point arguments
can be handled.


   typedef void *(*_rink_fn)(void);

   _rink_fn rink_fn(rink_seghandle cd, int entry);

It returns the address of the function, or zero if it does not exist in the
header. ch is the handle of the segement as returned by rink_seghandle.
entry is the entry number within the header, numbered from zero.

It is used by casting it to an appropriate type of pointer to a function.
For example, to call a function taking 6 integer arguments which returns an
interger, use something like


typedef int (*fn6)(int, int, int, int, int, int);

  result = ((fn6)rink_fn(code, 6))(1, 2, 3, 4, 5, 6);


****************************************************************************

** rink_call is used to call a child function within the segment.

**    void *rink_call(rink_seghandle ch, int entry, ...);

** It returns the return value of the child function. This need not be a
** pointer to void, but can be any word sized result. ch is the handle of the
** segement as returned by rink_seghandle. entry is the entry number within the
** header, numbered from zero.

** This function takes a variable number of parameters. The number supplied to
** this function must match those defined in the header - unpredicatable things
** may happen if this is wrong.

** I suggest you use small sugar functions to your child functions to allow the
** C compiler to type check them, and to avoid repeated casting when writing
** code. These can be replaced by #define macros for the production program to
** avoid the small speed penalty.


**    **** removed in version 0.02

****************************************************************************

rink_enum_named is used to find the names of all named functions, and a
pointer to that function.

   _rink_fn rink_enum_named(rink_seghandle cd, int *ref, char **name);

Set *ref to 0 before starting, and the call it repeatedly until *ref == -1.
After each call, *ref is set to refer to the next function, *name contains a
pointer to the name of the function and a pointer to the function is
returned.

For example, to print the names of all named functions within a segment, and
call them assuming that they take no arguments, use something like


typedef void (*fn0)(void);

void list_and_call(void)
{
  int l;
  char *name;
  _rink_fn fn;

  l = 0;
  do {
    fn = rink_enum_named(code, &l, &name);
    printf("*** %s\n", name);
    ((fn0)fn)();
  } while(l >= 0);
}


****************************************************************************

rink_readversion returns a pointer to a structure containing the version
numbers of a segment.

   rink_version *rink_readversion(rink_seghandle sh);


****************************************************************************

rink_unload is used to remove a segement from the parents memory.

   void rink_unload(rink_seghandle ch);


****************************************************************************


Using rinkptr to create pointer block
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The command line syntax of mkptrmap is

  rinkptr <symbol list> <output rink map> <output AOF file>

<symbol list> is a file used to find the symbols to include in the map. It's
format is described below. 'std_symlst' is a symbol list which includes all
the standard C library and the symbols necessary to interface with the C run
time system.

<output rink map> is the name of the output map file for the main rink
program. It's format is undefined and may change in future releases.

<output AOF file> is the name of the output AOF file which contains the
pointer block for the rink run time system. This file should be linked into
the parent program.

The current version of rinkptr performs very little checking of the input,
so any incorrect input may cause unpredicatable behaviour.



The symbol list format
~~~~~~~~~~~~~~~~~~~~~~

This file contains four sections, a list of sugar functions for the run time
system, a list of C header files, a list of symbols to remove from those
gained from the C header files, and a list of extra symbols not included in
the C header files. The sections are described in the order they must appear
in the file.


The sugar functions
~~~~~~~~~~~~~~~~~~~
This section is preceded by '*** sugar_functions:' on a line of it's own.
This allows you to use functions other than the default memory allocation
and error translation routines in the run time system. Each line specifies a
different sugar function, and is in the form

<token>:<function>

where token is a token to identify which sugar function you want to set, and
function is the name of the function you want to use for this purpose.

This section must be present, even if it is empty.

Tokens are

alloc, default 'malloc'
Used to allocating memory for the segments. prototype as malloc.

free, default 'free'
Used to free memory allocated by alloc.

errtrans, default '_rink_default_trans'
Used to translate rink errors. prototype:

os_error *trans(int err_number);

The default error translator returns a pointer to an error block with a
textual message in english, and the error number as err_number. Values for
err_number can be

Number  Default message
  -1    "No room"
  -2    "Not a rink segment"
  -3    "Not a rink links file"
  -4    "Segment is too recent"


The extra symbols
~~~~~~~~~~~~~~~~~

This section is preceded by '*** extra_symbols:' on a line of it's own. You
should include names of variables you wish to be accessiable to the
segments in this list, and any additional functions which cannot be picked
out of the supplied header files.

Blank lines are allowed.


The ignore symbols
~~~~~~~~~~~~~~~~~~

This section is preceded by '*** ignore_symbols:' on a line of it's own. You
should include names of symbols you wish to be removed from the list which
mkptrmap will produce from the list of C header files. This is necessary
because the code to read functions from C header files may occasionally pick
up other tokens which do not refer to vaild symbols. You will know when to
include a name in this list because the linker will fault the symbol when
the resultant AOF pointer block file is linked into the parent.

Blank lines are allowed.


The headers
~~~~~~~~~~~

This section is preceded by '*** header:' on a line of it's own. You should
include names of all header you want to scan. rinkptr will first attempt to
find the files in the current directory, but if they cannot be found there,
another attempt will be made to find them using the C: path set up by the
DDE.

Blank lines are not allowed, and the section ends at EOF.

Names are only mangled to the format 'h.foobar' from 'foobar.h' if the line
is merely something like 'foobar.h'. If you want to include a file on a
different path than C: or the current directory, you must use the form
'adfs::Ben.$.Dev.rink.h.thingy', 'MyPath:h.foobar' or something similar. (ie
a proper RISC OS filename)


