\t Extension Things

\j This document defines a standard mechanism for a procedure interface that
can, in principle, provide extensions to any programming language.

The structure allows several related procedures to be stored in one Thing.
This simplifies maintenance and reduces the system overheads.

Parameters are passed to the extension using conventions similar to the C
programming language. The parameter list contains keys and values passed to
the routine and pointers to more complex parameters.
The parameter list itself should not be modified.
Each extension can have its own definition of the
parameter list: there is both a formal definition to provide automatic
interfacing to high level languages, and an informal description to provide
user help texts.

The interface provides for procedures only. If a procedure has one principal
return parameter, this should be defined as the last parameter in the list.
A high level language interface can then identify this easily if the
extension procedure is called as a high level language function. Note that
this is different from calling a high level language procedure as a function
where the error return would be expected as the function value.

Extension procedures should not normally allocate memory for the return
parameters, the call mechanism provides that the amount of memory available
for a return parameter is either fixed by the parameter type or is specified
for a particular call.

If a procedure requires to return a variable size parameter, with no limit on
its size, and the space
pre-allocated is not sufficient, then it should return the error ERR.BFFL
and the parameter list must be defined in such a way that procedure may be
re-called. In this case it is unlikely that an automatic interface from the
high level language will be appropriate.

Th aim of this definition is not to provide a universal interface which will
cover all eventualities, but to make the interface in the majority of cases
automatic, while keeping the interface simple and efficient.


\f Extension Thing Header

\j All offsets are relative to the address of the flag.

\f
  thh_flag  $00   4 bytes  flag signalling standard header: value "THG%"
  thh_type  $04   long     type of Thing: value $01000003
  thh_next  $08   long     offset of next Thing in list (0 for last)
  thh_exid  $0c   long     extension ID
  thh_pdef  $10   long     offset to parameter definitions (or 0)
  thh_desc  $14   long     offset to description
  thh_code  $18            entry point for extension code - should exit with RTS

\t Level 1 Extension Parameter Definition

\j The parameters for a extension thing are defined as a table of words.
Each word defines the type of parameter that is possible. The table is
terminated by a zero word. In general, a single call value or key
is denoted by a positive word, while a pointer to a parameter value
is negative. The value -1 is used to delimit a group of repeated parameters.
The value -character is used to start a "keyed" group of parameters.
Because extra information on pointer parameters is passed to the extension
procedure, these parameters can be allowed
to be one of a list of possible types. Note that extension procedures
with optional or repeated parameters may have ambiguous definitions. Ambiguous
parameter definitions cannot be handled by general purpose interface code from
a high level language, so that such routines will require individually
coded interfaces.

The simplest parameters are call values or keys. The parameter definitions
for these are all low value, positive words. The distinction between
a key and a call value is that the former has a significance which is
defined internal to the extension procedure, while that latter has a numerical
value.

\f Call Values and Keys

  thp.key   $0001          key

  thp.char  $0004          character
  thp.ubyt  $0008          unsigned byte
  thp.sbyt  $000a          signed byte
  thp.uwrd  $0010          unsigned word
  thp.swrd  $0012          signed word
  thp.ulng  $0020          unsigned long
  thp.slng  $0022          signed long

  thp..opt     12          bit set if parameter optional
  thp..nnl     11          bit set if null parameter is negative (-1)


\j For parameters where the item in the parameter list is a pointer to a value,
the situation is rather more complex. For each parameter, there may be a number
of possibilities. The word in the list is formed by ORing all the possibilities
together. There are bits that define that the parameter is a pointer and
defines whether the parameter is call, return, updated or specified by the
calling code.

\f Pointer Parameter Usage

  thp..ptr     15          bit set for pointer parameter
  thp..cal     14          bit set for call parameter
  thp..ret     13          bit set for return parameter

  thp.upd   $e000          updated parameter
  thp.call  $c000          call parameter
  thp.ret   $a000          return parameter
  thp.ptr   $8000          call or return parameter (specified by calling code)


\j If the parameter is optional, then the optional bit should be set (or
the word is ORed with the optional key value.

\f Optional Parameter

  thp..opt     12          bit set if parameter is optional

  thp.opt   $1000          optional


\j The parameter could be an array of given type with a standard header: note
that the standard interface code will always allow a single value to be used
in its place.

\f Array Parameter

  thp..arr     11          bit set for array

  thp.arr   $0800          array

\j An array is either a one dimensional table of values (not possible for
strings) or a one dimensional table of pointers. These pointers may
point to further one dimensional tables of values or pointers (this implements
multi-dimensional arrays).

\j Each table is preceded by a two long words. The first specifies whether the
table is a table of values (0), a table of pointers to values (negative) or
a table of pointers to further tables (positive = number of further levels).
The second specifies the number of items in the table. Each pointer is a
long word.

\j To finish off the definition word, the values defining each of the possible
types of parameter should be ORed with the word so far. Note that, provided
there is at most one signed value possible, the values representing the
parameter usage, option, array and types may be ADDed together rather than
ORed. Note also that a you may not have both unsigned and signed values.


\f Parameter Types

  thp..sgn      1          bit set if value is signed
  thp..chr      2          bit set if character allowed
  thp..byt      3          bit set if byte value allowed/required
  thp..wrd      4          bit set if word value allowed/required
  thp..lng      5          bit set if long value allowed/required

  thp..str      8          standard string
  thp..sst      9          sub-string

  thp.char  $0004          character
  thp.ubyt  $0008          unsigned byte
  thp.sbyt  $000a          signed byte
  thp.uwrd  $0010          unsigned word
  thp.swrd  $0012          signed word
  thp.ulng  $0020          unsigned long
  thp.slng  $0022          signed long
  thp.fp8   $0042          eight byte floating point
  thp.str   $0100          string
  thp.sstr  $0200          sub-string



\t Example Parameter Definitions

\f COPY

      dc.w  thp.call+thp.str   pointer to source file
      dc.w  thp.call+thp.str   pointer to destination file
      dc.w  0

\f SER_BUFF

      dc.w  thp.opt+thp.ulng   optional unsigned long
      dc.w  thp.opt+thp.ulng   optional unsigned long
      dc.w  0

\f PRT_USE$

      dc.w  thp.ret+thp.str    pointer to return string
      dc.w  0

\t Informal Description

\j To be defined - usage, full name, parameter descriptions.


\t Parameter List

\j For each parameter that is passed there is one or two long words in
the parameter list. For a key it is just the key in a long word. The
procedure itself will determine how much of the key is significant.
For a call value, the value is in the least significant part of the long word,
the rest of the long word is ignored. If a key or call parameter is marked
as optional, then the interface code should provide a default value (normally
zero or -1 depending on thp..nnl) if the parameter is missing

For a pointer there are eight bytes: two words followed by a long word.
The first word specifies the usage of the parameter. If
it was an optional parameter and it is missing, the value is 0. Otherwise
thp..ptr and either or both thp..cal and thp..ret are set. The thp..arr bit will
be set if the pointer is to an array. In addition, one of the lower bits
must be set to define the type of parameter. The thp..sng and thp..key bits
should be clear.

The next word is zero for most parameters, but for a return string it is the
maximum space available, and for a call sub-string it is the length of the
sub-string.

The next long word is the pointer to the parameter value (or array definition).
If it is a missing optional parameter the value is ignored, but, for
future compatibility, zero should be supplied.

A repeated group of parameters is prefaced by a long word with the
number of repeats.


\t Defining Extension Things

\j Extension Things do not need to be written to strict rules. Since it can
be assumed that the code calling the Extension Thing is fully aware of the
requirements and behaviour of the Extension Thing, an Extension Thing
can be any routine. It is, however, advantageous to be more strict than this.
If the Extension Thing is defined with an unambiguous parameter definition,
and it accepts a parameter list in the standard form described above, and
it is clean to the extent of preserving all registers except d1 and a1
(meeting the SuperBASIC interpreter requirements for a6 and a7 as well), and it
returns a standard error code (-ve) or escape code (+ve) or zero in d0,
and it has at most one return parameter, then
it will usually be possible to interface to the Extension Thing automatically.

The format of an Extension Thing does not allow more than a four character ID.
This is to simplify access. It is up to the high level language itself to
define a suitable name although the name in the informal description may be
used.

One requirement of the definition of an Extension Thing is that it must be
shareable.

\t Accessing Extension Things

\j Depending on the extent to which an Extension Thing is to be used, an
application can either USE the Extension Thing during initialisation and
save the address of the Extension Thing (and possibly the Thing linkage) or
it can USE the Extension Thing as required and FREE it immediately afterwards.
The latter is simpler, the former is more efficient for small, frequently used
Extension Things.


\t When to Use Extension Things.

\j There are many ways of extending the SMS2 operating system. Using an
Extension Thing is just one. There are two cases where it is appropriate to
add an extension thing. The first is where the extension is provided to
access some hardware dependent facility or other facility which is an optional
extra. Provided that the Extension Thing has an unambiguous parameter
definition and a clean interface, it should be possible to add such an
extension to any high level language. The second case is where there is a
facility which is likely to be required to be called from a number of languages
and involves a considerable amount of code. In this case, it is not so
important that the facility has either a unambiguous definition or a clean
interface.

The SER_PAR_PRT extension things are good examples of the first. These are
very simple extensions which are linked to the serial and parallel port drivers.
The FILE_SELECT extension is a good example of the latter, this is a very
complex, but useful procedure.

An Extension Thing may not be appropriate if the procedure is just a direct
interface to a operating system facility (e.g. INK, PAPER, CLS etc.).
