
If you are an Amigoid to whom one or more of the following statements applies:


    1. You always wanted to learn ARexx but the fact that it can't even flash
    the screen by itself bothered you (well I know that there is \007),

    2. You badly need quick and easily created wrapper-programs for your new
    great E routines using ARexx's monitoring capabilities,

    3. You want to write something really useful as PD, Shareware or
    something, but don't know what people out there would need and truly
    appreciate,

    4. You want to start programming in E in an unconventional way,

    5. You need some speial and quick functions for your ARexx scripts,

    6. You often listen to those PC/Macintosh los... sorry -- 'users' and
    begin to envy them their 'servers' and stuff,

    7. You have your nose more or less in the middle of your face...


    THIS IS FOR YOU !  IT WILL MAKE YOU HAPPY !


What it is you're asking? Well this is a E module, called rexxHostC.m, two
sources as example of using it, and this ReadMe.

The module provides you with an extremely user-friendly 'engin' for writing
Rexx function-hosta (i.e. servers). Take a look on the 'mini_host.e' file to
see how concise can an E program be! And it really provides ARexx with a
Intuition function! The executable is 5112 bytes big.

The engin is object-oriented, it has been pretty thoroughly tested, and it
returns all memory used. What else can I say...? Here comes the HOW-TO.

---------------------------------------------------------------

After creating an instance of a rexxHostC object, by calling NEW rexxHostC()
with required parameter/s, the program by itself will open rexsyslib.library,
create a public port with the provided or default name, add it to ARexx's
host list and [possibly after executing some user-provided function] enter a
loop waiting for ARexx function-calls, intercepting them and executing. This
loop will be broken if either:

    1. COMMAND 'bye' arrives at its port

    2. the program got ^C

    3. the method break() is executed [directly or not] by any callback

and then our instance of the rexxHostC object will do the cleanup, that is:
reply the outstanding messages, delete the port, close the rexsyslib.library
etc.  and commit suicide. In most cases the host will terminate [unless, for
some strange reason, you decide otherwise and put lots of other code after
it].

The rexxHostC class has quite a few methods, but you don't need most of them
if you don't want them; they are only there to help you. Notice that the
'mini_host' demo uses no other method but the constructor!

Here comes short description of the available methods:

---------------------------------------------------------------

CONSTRUCTOR:

    rexxHostC(  callback_list,
                name            = 'rexx_host',
                host_priority   = -50,
                func_ptr        = NIL )

where:

    callback_list
    -------------

    is a list of pairs: [ S, C, S, C, ... , S, C ]

    'S' being an UPPERCASE string like 'BEEP' or 'BYE_BYE' [quotes
    included!], representing the name of the function you are adding to ARexx
    'C' is a callback i.e. a pointer to a PROC'ess; it can also be a quoted
    expression, a string like 'I love this\n', or just NIL; in the last
    case ARexx will not find any function with this callback's name --
    just as if  the name-string was not there. This callback-list is
    [roughly] checked for validity and if it doesn't conform exception 4
    i.e. ERR_BADLIST will be raised.

    Callbacks take no arguments [not directly anyway] and return either
    nothing or [nicer thing to do] a string [not necessarily an EString]
    like 'this is your callback speaking', 'TRUE', or '666'. ARexx will by
    himself [!] translate those strings that represent numbers [like the last
    one here] to numbers. It is as easy as that for direct values, for
    variables you will probably use the supplied routines longToStr() and
    charToStr(), which turn an integer like 69 or a char like "A" into a
    string for ARexx.  See the 'big_host' demo-source for that. As to
    callbacks' arguments there are three support routines supplied for that
    purpose: getNumArgs(), getStr( index ) and getNum( index ), read later on
    about them.

    name
    ----

    [optional] is a string representing name for your message-port which must
    be different from all currently present public ports present in the
    system or you will get exception 2 i.e. 'ERR_NOTUNIQUE'.


    host_priority
    --------------

    [optional] is the priority AMONG all Arexx libraries and hosts. It is NOT
    any task priority, so don't be too surprised at the low default value. In
    fact you SHOULD NEVER USE HIGHER priority than any of the libraries/hosts
    you will be calling, DEADLOCK will result otherwise! I would personally
    never attempt anything over 0. 'host_priority' value will be clipped to
    a number between -100 and 100.


    func_ptr
    --------

    is the [optional] pointer to function you want executed AFTER setup is
    completed, probably nothing more important than announcing that it is
    waiting for Rexx messages.


Note that 'callback_list' is the only argument you must give the constructor.
Another unusual thing is that we have no public destructor.

---------------------------------------------------------------

    num := getNumArgs()
           ------------

    returns the number of arguments the function in question got from ARexx,
    it will be something between 0 and 15.

---------------------------------------------------------------

    string, fGood := getStr( index )
                     ---------------

    gives you the argument number 'index' as a string, the second BOOLEAN
    return-value tells you whether this argument is valid, that is -- if it
    really came from ARexx [this you might already know if you have
    previously called getNumArgs()].

    N.B. It starts from 1, as the argument #0 is the command itself!

---------------------------------------------------------------

    num, fGood := getNum( index )
                  ---------------

    gives you the argument number 'index' as an integer, the second BOOLEAN
    return-value tells you whether this argument is valid, that is -- if the
    argument-string with this index string really came from ARexx and if it
    is a number.

    N.B. It starts from 1, as the argument #0 is the command itself!

---------------------------------------------------------------

    break()
    -------

    breaks the waiting/receiving/executing loop and kills the rexxHandlerC
    object.

---------------------------------------------------------------

    str := longToStr( long )
           -----------------

    str := charToStr( char )
           -----------------

    as already said, these functions will turn an integer or a char
    respectively into a string just as ARexx wants it for a return-value from
    its function, it is only needed for variables, the direct values can be
    returned with strings like '123' or 'oui monsieur'.

---------------------------------------------------------------

    major, minor := version()
                    ---------

    returns major and minor version number of the rexxHostC.m
    the current values are bye the way: 0 and 4

=======================================================================

EXCEPTIONS that might be raised by rexxHostC-object:


"MEM"                   meaning: 'not enough memory'

"REXX"                  meaning: 'rexxsyslib.library not found'

ERR_NONAME      = 1     meaning: 'I got NIL as port-name'

ERR_NOTUNIQUE   = 2     meaning: 'port-name not unique'

ERR_LISTNIL     = 3     meaning: 'callback-list ptr NIL'

ERR_BADLIST     = 4     meaning: 'bad callback-list'

ERR_NOTADDED    = 5     meaning: 'host not added to ARexx list...'

---------------------------------------------------------------

LIMITATIONS:

There are two major I can think of:

    1. As all other similar Rexx hosts I met [for example RexxFuncHost by
    Donald T. Meyer] one such active host screens all other from receiving
    function-calls; so that ONLY ONE CAN BE EFFECTIVE AT ANY TIME.  This is
    due to the fact that, differently than with libraries, ARexx will not
    send your function-call to any other host whatever error was reported by
    the one that received it. It would be possible to find a solution to that
    -- if I still feel any urge to play with this piece of software I might
    do that -- but in practice it shouldn't be so much of a problem
    considering E's lightning speed of compilation. If you already have the
    callbacks, you can create a new host in couple of minutes and launch it
    in place of the previously running one. It might even be possible to have
    dynamically created callback-lists: if/when we start to get flooded with
    great PD/ShareWare/commercial modules containing just callback-lists and
    callbacks themselves [there would be some problems with getting the
    arguments for the callbacks though], you would be able to manage them
    dynamically from ARexx to be included in just one rexxHostC-based server.

    2. UPPER/lower case does not matter for all function-calls. It wouldn't
    be any problem to implement this as optional, but I doubt whether it
    would be so useful. Both ARexx and AmigaDOS tend to be case-insensitive
    in most cases, and preventing ARexx from turning the name in your
    function-call to uppercase requires additional work.


This was written in E v3.0b and v3.1a [registered version], by Piotr Obminski
in December 1994. It is, an off-spin of a much larger project, but I
found it so cute that I decided to polish it and present it to the so called
'Amiga community' [as community service]. The example-proggies are PD, but
the rexxHostC.m is Copyrighted FreeWare by me that is Piotr Obminski.
