\input texinfo   @c -*-texinfo-*-
@c %**start of header
@setfilename ARexxBox.info
@settitle ARexxBox 1.11 Documentation
@setchapternewpage odd
@c %**end of header

@comment  ARexxBox.texi
@comment  English documentation for ARexxBox (TexInfo format)
@comment  Copyright (c) 1992,1993 Michael Balzer

@ifinfo
Manual for ARexxBox version 1.11

Copyright @copyright{} 1993 Michael Balzer
@end ifinfo

@titlepage

@title{ARexxBox}
@subtitle{ARexx Interface Design Tool}
@subtitle{Version 1.11}

@page
@vskip 0pt plus 1filll

Copyright @copyright{} 1992,1993 Michael Balzer
Oberon-2 source copyright @copyright{} 1993 hartmut Goebel

Permission is granted to copy and distribute this document as long as the
copyright notes and this permission remain unchanged throughout all copies.

@ignore
Permission is granted to process this file by TeX and print the results,
provided the printed document carries a copying permission notice identical to
this one except for the removal of this paragraph (this paragraph not being
relevant to the printed manual).
@end ignore

No guarantee of any kind is given that the programs described in this
document are 100% reliable.  You are using this material at your own risk.
The authors @strong{can not} be made responsible for any damage which is
caused by using these programs.

This package is freely distributable, but still copyright by Michael Balzer.
This means that you can copy it freely as long as you don't ask for a more
than nominal copying fee. This fee @strong{must not} be more than US $5 or 5
DM.

@strong{This limit applies to German Public-Domain dealers too!!}

Permission is granted to include this package in Public-Domain collections,
especially in Fred Fishs Amiga Disk Library (including CD ROM versions of it).
The distribution file may be uploaded to Bulletin Board Systems or FTP
servers. If you want to distribute this program you @strong{must} use the
original distribution archive @file{ARexxBox111.lha}.

The authors would like to see this packet included in any kind of
developer's tool chest (e.g.  the Native Developer's Upgrade Kit by
Commodore), but please tell us if you do so.

@strong{None} of the programs @strong{nor} the source code (nor parts of it)
may be used on any machine which is used for the research, development,
construction, testing or production of weapons or other military applications.
This also includes any machine which is used for training persons for
@strong{any} of the above mentioned purposes.

@end titlepage
@headings double
@comment ----------------------------------------------------------------


@comment ----------------------------------------------------------------
@comment --- Top Node (wird nicht gedruckt)                           ---
@comment ----------------------------------------------------------------
@ifinfo
@node Top, Copyright, (dir), (dir)
@top ARexxBox 1.11 Documentation

@menu
Common stuff:

* Copyright::            Copyright and other legal stuff
* Important::            Read this!
* Addresses::            Where to send bug reports, comments and gifts

The ARexxBox (ARB):

* Introduction::         Why ARexxBox?
* Requirements::         68040, 16 MB RAM, ...  ;-)
* Installation::         What to put where
* Usage::                What happens if I push this button?

The generated Code:

* Concept::              How it is supposed to work
* Files::                What is where
* InterfaceFunctions::   Interface between ARexx and your program
* Arguments&Results::    Parameters for and result values from commands
* Errors::               ARB's extended error code system
* How2use::              Step by step guidelines
* Oberon-2::             Remarks to the Oberon-2 source

Lookup chapters:

* ReadArgs::             ReadArgs switches and their types
* Library::              The library functions of ARB

Appendices:

* FileFormat::           Syntax of the .arb file format
* History::              The development history of ARexxBox
* Thanks::               The author would like to thank@dots{}
* Index::                Index for this document
@end menu

@end ifinfo
@comment ----------------------------------------------------------------


@comment ----------------------------------------------------------------
@comment --- Kapitel: Copyright (für Info/AmigaGuide Dokument)        ---
@comment ----------------------------------------------------------------
@ifinfo
@node Copyright, Important, Top, Top
@chapter Copyright and other legal stuff
@cindex Copyright
@cindex Distribution
@cindex Legal stuff

Copyright @copyright{} 1992,1993 Michael Balzer

Oberon-2 source copyright @copyright{} 1993 hartmut Goebel

Permission is granted to make and distribute verbatim copies of this manual
provided the copyright notice and this permission notice are preserved on
all copies.

@ignore
Permission is granted to process this file by TeX and print the results,
provided the printed document carries a copying permission notice identical to
this one except for the removal of this paragraph (this paragraph not being
relevant to the printed manual).
@end ignore

No guarantee of any kind is given that the programs described in this
document are 100% reliable.  You are using this material at your own risk.
The authors @strong{can not} be made responsible for any damage which is
caused by using these programs.

This package is freely distributable, but still copyright by Michael Balzer.
This means that you can copy it freely as long as you don't ask for a more
than nominal copying fee. This fee @strong{must not} be more than US $5 or 5
DM.

@strong{This limit applies to German Public-Domain dealers too!!}

Permission is granted to include this package in Public-Domain collections,
especially in Fred Fishs Amiga Disk Library (including CD ROM versions of it).
The distribution file may be uploaded to Bulletin Board Systems or FTP
servers. If you want to distribute this program you @strong{must} use the
original distribution archive @file{ARexxBox111.lha}.

The authors would like to see this packet included in any kind of
developer's tool chest (e.g.  the Native Developer's Upgrade Kit by
Commodore), but please tell us if you do so.

@strong{None} of the programs @strong{nor} the source code (nor parts of it)
may be used on any machine which is used for the research, development,
construction, testing or production of weapons or other military applications.
This also includes any machine which is used for training persons for
@strong{any} of the above mentioned purposes.

@end ifinfo

@comment ----------------------------------------------------------------
@comment --- Kapitel: Important remarks
@comment ----------------------------------------------------------------
@node Important, Addresses, Copyright, Top
@chapter Important remarks
@cindex FreeWare
@cindex Important remarks

Before you do anything else:  ARexxBox is a tool by programmers for
programmers.  If you're a user, this program is of no use for you, please
pass it to a friend who develops software.

One of the primary design goals of the ARexxBox and especially the
generated code was to come as close as possible to the ideas of the ``User
Interface Style Guide'' by Commodore.

If you haven't read this book yet, I'd recommend you do so before reading
on and using the ARexxBox.  Many of the potentially confusing things will
be clearer to you.

In my opinion, we have to establish a standard for ARexx interfaces; I
think it's a very annoying thing for the user having to learn a new syntax
and usage of ARexx for each new program she buys.

Of course, the Style Guide can't give final solutions to all problems ---
many of the ideas mentioned in the Guide need to be extended a bit.
Especially some standard command's parameters leave some questions.  I have
tried to complete these things when converting them to ARexxBox, but there
are certainly many more places than I recognized.  If you do such an
extension, please let me know, so we can share it amongst all ARB users.

ARexxBox is FreeWare, meaning you may copy and distribute it freely as long
as you follow the conditions mentioned in the copyright chapter, but the
complete ARexxBox is still copyrighted by me, the author. However, I grant
you the right to use the generated code freely as long as you do not use it
for military purposes as mentioned in the copyright chapter. You don't have
to pay any licenses for any part of the software.

All I'm asking for is that you put a remark into both the About window and
the documentation for any software using ARB generated code stating that
the ARexx interface was designed using the ARexxBox.  Also, I'd like to get
(email preferred) a list of the supported ARexx commands, but that's not a
must.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Adresse des Autors                              ---
@comment ----------------------------------------------------------------
@node Addresses, Introduction, Important, Top
@chapter Addresses of the Authors
@cindex Addresses
@cindex Bug reports
@cindex Suggestions
@cindex Gifts
@cindex E-Mail
@cindex InterNet Address
@cindex Mail Address

You can reach the author under one of the following addresses:

@table @asis
@item Mail:

@example
   Michael Balzer
   Wildermuthstraße 18
   W-5828 Ennepetal        (58256 from july 1993 on!)
   GERMANY
@end example

@item InterNet Electronic Mail:

@example
At work:
   balzer@@heike.informatik.uni-dortmund.de

At home:
   bilbo@@bagsend.aworld.de
or in the german Z-Net
   m.balzer@@aworld.zer
or from Fido
   Michael Balzer of 2:241/5604.19
@end example

The Fido address hasn't been tested up to now, if you don't get a reply
please try another way.

@end table

If you have questions concerning the Oberon-2 source, please contact:

@table @asis
@item Postadresse:

@example
   hartmut Goebel
   Aufseßplatz 5
   W-8500 Nürnberg 40      (90459 from july 1993 on!)
   GERMANY
@end example

@item InterNet Electronic Mail:

@example
At home:
   hartmut@@oberon.nbg.sub.org
or in the german Z-Net (not very frequently)
   hartmut@@asn.zer
or from Fido
   Harmut Goebel of 2:246/81.1
@end example
@end table


@comment ----------------------------------------------------------------
@comment --- Kapitel: Einleitung                                      ---
@comment ----------------------------------------------------------------
@node Introduction, Requirements, Addresses, Top
@chapter Introduction
@cindex Features

You probably already know how important ARexx is to the Amiga. So I'll
concentrate on convincing you to use ARexxBox for your ARexx interfaces
;-).

@section Why ARexxBox?

ARexxBox (inspired by Jan van den Baard's GadToolsBox) is a tool that eases
the design, construction and implementation of an ARexx interface for a
program. An interface generated by ARexxBox automatically conforms to the
ARexx standards mentioned in Commodore's ``User Interface Style Guide''.

Here are the features:

@itemize

@item Syntax and result method conform to the ``Style Guide'', e.g. the
code uses ReadArgs to give the commands a syntax similar to DOS commands,
and there is automatic support for the keywords VAR and STEM.

@item Each command of an interface may have as many arguments and results
as you like.

@item All ReadArgs() templates are allowed for arguments and will be
recognized by ARexxBox, for results you may use the options /N and /M ---
also coming with full support by the Box.

@item Graphical user interface (made with GadToolsBox :-).

@item Generates C or Oberon-2 source@footnote{The Oberon-2 source was
designed to be object oriented and ``type-save''.}

@item There's an option to generate code for a CommandShell where the user
may enter ARexx commands directly and view the results.

@item The CommandShell can execute batch programs as well.

@item A program may open an arbitrary number of ARexx ports and
CommandShells.

@item The standard commands mentioned by the ``Style Guide'' come in
separate files, ready--to--use. There's example interface code for some of
these.

@end itemize


@comment ----------------------------------------------------------------
@comment --- Kapitel: Systemanforderungen                             ---
@comment ----------------------------------------------------------------
@node Requirements, Installation, Introduction, Top
@chapter Requirements

@section Hardware

The hardware requirements are neglectible, ARB should run on any Amiga.

Okay, there's @emph{one} thing:  As the ARB window is taller than 200
lines, you have to use something larger than that. Or you could set the
system font to some 6 or 7 point font.

As programmers normally don't work on a 640x200 screen, this shouldn't cast
any problems.

@section Software
@cindex reqtools.library

Both ARB and the generated code will only run on OS2.04 or higher.

The Box itself also makes use of the reqtools library by Nico Francois.
This is only for the Box, the generated code does not use it!

@section C source
@cindex ANSI C
@cindex amiga.lib
@cindex amiga.lib
@cindex rexxvars.o

You will need an ANSI compatible C compiler which offers an option to
include (link) functions from @file{amiga.lib} by Commodore.

The @file{amiga.lib} must be version 37.32 (12.11.91) or later. This
version is available as part of the Native Developer's Upgrade Kit for
OS2.04.

You can do without @file{amiga.lib}. I reassembled the needed functions
(@code{GetRexxVar} and @code{SetRexxVar}) and included them as separate
source. Aztec spends very much time scanning @file{amiga.lib}, so if you
link with this object you will get shorter turn-around times.

I, on the other hand, cannot guarantee that this code is completely
compatible to those from @file{amiga.lib}, and of course you won't make use
of any future enhancements in the lib.

@section Oberon-2 source
@cindex RVI
@cindex OLink

You will need AmigaOberon V3.0 or later.

The source is based upon a non standard class library and some other
modules (see Oberon subdirectory).

The module RVI is an interface to some part of the amiga.lib, you have to
link with this module if using amiga.lib functions:
@example
OLink RxTest OBJ oberon:obj/amiga.lib
@end example

If you have got the object file ``rexxvars.o'' from one of the ARexx
developer kits, you can use the $JOIN option to link it onto the object
file of the RVI module.  In this case, you don't need to specify amiga.lib
for linking.  Doing the same with amiga.lib itself is not recommended, your
files would become very big.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Installation
@comment ----------------------------------------------------------------
@node Installation, Usage, Requirements, Top
@chapter Installation

Basically you don't have to install anything. Just copy all parts to a
place where you (or your compiler) can find them. Some Oberon modules are
not only for ARB but also of general use.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Bedienung
@comment ----------------------------------------------------------------
@node Usage, Concept, Installation, Top
@chapter Usage

There's nothing unusual in using ARexxBox. If you've ever used an amiga
application, you should have no problems at all.

Before defining some complex ARexx interface, you should probably first
read the chapter explaining the concept of the Box. To get a first
impression, you could now load the file @file{arb/Misc.arb}. Click on
@code{GETATTR} in the leftmost list.

The remaining two listviews should now fill with the parameters and result
fields of the command @code{GETATTR}. Each element of any list can be
changed using the gadgets below of the list.

@menu
* Input::            How to enter a new command
* MsgPort Basename::
* CommandShell::
* Merge in::
* Print::
* Generate Source::  To C or not to C, that is the question
* Clipboard::        Cut, Copy and Paste
@end menu

@comment ----------------------------------------------------------------
@node Input, MsgPort Basename, , Usage
@section Input
@cindex ARB input
@cindex Shortcuts
@cindex up & do

To enter a command definition, do the following steps: Push key 
@key{N}, enter the name of the ARexx command and confirm with @key{RETURN}.
ARexxBox will now convert all characters to upper case and those not
allowed to underscores (@file{_}) and then check if the name is unique. If
there is already a command with that name, you can change the name of the
new command and try again.

Then enter the arguments. For each argument, push @key{E} and enter the
name (optionally with ReadArgs style type tags). This name will also be
checked for collisions with existing arguments.

With results, it's just the same, only the shortcut for a new result field
is key @key{W}.

You can move args and results up and down, either just after entering them
or later after selecting them via clicking on them, by pushing the gadgets
labeled `up' and `do'.  You can remove any list element by selecting it and
then clicking on `Remove'.

The types of the arguments and results must be given in ReadArgs() style
(see AutoDocs), for example ARG1/K/N or LIST/M.  Only the (optional and
combinable) switches /N and /M are allowed for results.

@comment ----------------------------------------------------------------
@node MsgPort Basename, CommandShell, Input, Usage
@section MsgPort Basename
@cindex MsgPort Basename

The `MsgPort Basename' is the default base name for all ARexx message ports
opened by the application. If necessary, a proper number will be appended
to the name to make it unique (e.g. ``FOOWRITE.13'').

Any application should recognize the shell or workbench argument
``PORTNAME'' to change this base name.  Such a user supplied base name will
also be made unique via an appended number if necessary.

In addition, the MsgPort Basename will be used as the standard extension
for ARexx script files for the application, so you should choose a short
text for it. The PORTNAME tooltype has no effect on this.

@comment ----------------------------------------------------------------
@node CommandShell, Merge in, MsgPort Basename, Usage
@section CommandShell
@cindex CommandShell

For C, ARB will generate additional code for a command shell if you turn
this gadget on.  You should normally leave it on, as the command shell code
can also be used to execute external macro programs.

The switch makes no difference for Oberon, where the command shell code is
always available.

The command shell is a kind of shell, which gives the user a direct interface
to all ARexx commands of an application. The user can execute the ARexx
commands from this shell as if it were a normal shell and the commands were
DOS commands. The results of commands get printed in a readable form in
the shell window.

For example, you could use the commandshell to quickly execute some macro
without having to use ARexx directly.  Or you can use this as a way to make
some commands only available to the advanced user.

If you give a command shell a file as its input channel, it will execute
the commands in the file line by line.  So you can also use it to execute
external macro programs.

@comment ----------------------------------------------------------------
@node Merge in, Print, CommandShell, Usage
@section Merge in
@cindex Merge in

Merge is like Open, only it does not clear the command list before loading
the data file. Merge will only add commands which are not already defined
in the current project.

So with merge, you can build your own ARexx command packages for different
purposes and later combine them as you need them. I already entered all
standard commands mentioned by the Style Guide, try to combine some of
these packages into your test file.

@comment ----------------------------------------------------------------
@node Print, Generate Source, Merge in, Usage
@section Print
@cindex Print

This shall become a documentation aid.  It currently only prints name,
syntax and results for all commands.  If you have a good suggestion on a
better output format for this function, please tell me.

@comment ----------------------------------------------------------------
@node Generate Source, Clipboard, Print, Usage
@section Generate Source
@cindex Generate Source
@cindex ATT: Interface changed!

Starts the source generator. You may select any part of an already existing
source output in the file requester or enter a complete new base name. Any
ARB extension (@file{.c}, @file{.h} or @file{_rxif.c} or for Oberon @file{.mod})
will be cut off. Some safety checks will be done (e.g. if you are going to
destroy another file accidentally) and then the source will be generated.

The new source files first go into @file{T:}, to prevent possible damages
caused by crashes or other bad things. The new files will be copied to the
actual destination directory as soon as they have been completed in
@file{T:}.

The new files in @file{T:} won't be deleted if some error happens while
copying them to their real location. So if some bad things happen, you
still have a chance to save them yourself.

When generating the source, the Box will set the internal status of all
commands to `old'.  A new command has status `new' and if you edit a
command, the Box sets the status to `changed'.  The source generator relies
on this status flag to tell which commands have been altered since the last
source generation.  If a command has been altered, the generator will put a
remark (``ATT:  Interface changed!'') into the source right before the
interface function correlating to that command.

You should look for this comment and check the consistency of the interface
and the variable naming of the RXD structure against the real (perhaps on
some older version basing) code before compiling again.  Some cases the
compiler won't find...

An important thing to have this remarks working is to save an ARB project
after generating the source to it. If you do not save it, the changes of
the status flags won't be saved as well. That's not tragic, but the Box
will not know about the changes next time.

There are currently two source generators available, one for C (the
original thing) and one for Oberon (by hartmut Goebel). Please ask hartmut
if you have questions concerning the Oberon part.

@comment ----------------------------------------------------------------
@node Clipboard, , Generate Source, Usage
@section Clipboard
@cindex Cut
@cindex Copy
@cindex Erase
@cindex Paste
@cindex Mark Range

Cut, Copy and Erase work on either the currently selected command or on a
range of commands.

To mark a range for these operations, choose ``Mark Range'', click on the
first and then on the last command of the wanted range.

Selecting a single command clears the range selection.

Paste, like Merge, will only include commands not already there.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Konzept
@comment ----------------------------------------------------------------
@node Concept, Files, Usage, Top
@chapter Concept
@cindex Concept

Besides conforming to the Style Guide, another primary design goal of
ARexxBox was to ease the usage of ARexx to a programmer as much as
possible.

@menu
* Initializing::                Open port
* Commands from ARexx::         Dispatcher and interface functions
* Expanding commands::          ExpandRXCommand() and external commands
* Commands to ARexx::           SendRexxCommand()
* Closedown::                   Close port
@end menu

@node Initializing, Commands from ARexx, , Concept
@section Initializing
@cindex Concept: Init

The function SetupARexxHost() will open the ARexx port and return a pointer
to an object of the type @code{struct RexxHost}. This pointer is a kind of
file handle for the ARexx port, all other ARexx functions generated by the
Box need this pointer.

In Oberon-2 SetupARexxHost() also returns a pointer, which serves as the
`receiver' of the methods.

So all operations relate to a specific port (an application can have any
number of ARexx ports, e.g. a text editor could open one port for each open
file).

@node Commands from ARexx, Expanding commands, Initializing, Concept
@section Commands from ARexx
@cindex Konzept: Commands from ARexx

To handle its ARexx port, all the application has to do is listen to the
port (signal) and call the function ARexxDispatch(), which will fetch and
handle all incoming messages until the port is empty and then return.

Each command has its corresponding interface function (the interface
between ARexx and your code), the address of this interface function is in
the command list entry to the command. Normally such an interface function
just checks the parameters and then calls the right core functions of your
application. All you have to do is implementing these interface functions
--- and the Box will help you by generating the skeleton code for each new
command.

The actual (user supplied) parameters for a command are passed to the
interface function via a specially created data structure.  The interface
function in turn returns its results by storing them in the same data
structure before returning. The ARB routines take care to pass the results
back to ARexx according to their types and conforming to the Style Guide.

@node Expanding commands, Commands to ARexx, Commands from ARexx, Concept
@section Expanding commands
@cindex Concept: Expanding commands

To support both the ALIAS standard command and other things like macros,
there is a callback function which will be called by the parser before
discarding an unknown command.

The parser analyzes incoming command lines and determines which interface
function to call. If the command line does not match any command of the
list, the parser will call ExpandRXCommand(), which could then do an ALIAS
expansion and return the substituted command to the parser.

The parser will then try once again to recognize the command.  If this
second try fails again, the original command will be sent to the ARexx
server process.  So if there is an external script program of this name, it
will be executed as if it were an internal part of your application,
external commands are totally transparent to the user. The result of an
external command will be sent back to the original caller.

Demonstration of this feature: Change to directory @file{test} and start
@file{test}. Close the CommandShell by typing EOF (@key{C-\}) and then
enter the following command in another shell:

@code{rx "options results; address 'arbtest'; test 'FooBar'; say result"}

As the test program does not have an internal command called ``test'', the
external script @file{test.arbtest} will be executed, which in turn will
output a message into the output window of the test program and then return
the string ``Testtext!'' to the caller (yeah, I know, very imaginative).

If no external command of the given name exists, the command will finally
be classified as ``unknown'' and the parser will return an error to the
caller.

Once again the complete process for a command:

@enumerate
@item Command in internal command list?
@item If not: ExpandRXCommand() -> new Command known?
@item If not: Is it an external script?
@item If not: Error - not implemented
@end enumerate

@node Commands to ARexx, Closedown, Expanding commands, Concept
@section Commands to ARexx
@cindex Concept: Commands to ARexx

Of course the application may also send commands to ARexx, there are some
special support functions for this direction available (see
SendRexxCommand).

As such commands generally (being just normal Exec messages) run
asynchronously, the ARexxBox has a special mechanism to react on the return
of such a call. So you can start an ARexx command and then later get the
result from it.  Of course you have to make sure you can identify which
result belongs to which command (see chapter on how to use the code).

To prevent late replies to break, the Box routines will count all sent
commands and reject to close the port until all replies have been received
(see Closedown).

@node Closedown, , Commands to ARexx, Concept
@section Closedown
@cindex Concept: Closedown

SetupARexxHost's counterpart is obviously CloseDownARexxHost. This one
closes the port and releases all allocated ressources.

The final closedown may be delayed automatically, if there are some
commands which were sent to ARexx but have not returned yet. The Box will
then wait for all these commands to be finished before closing the port.
Any new commands coming up during this phase will be returned immediately
with an error ``Host closing down''.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Dateien
@comment ----------------------------------------------------------------
@node Files, InterfaceFunctions, Concept, Top
@chapter Files

The source generated by ARB should be compilable without any changes. All
needed interface functions (the only part you have to work on) should at
least be there as empty template code.

@section C
@cindex Source: C

The C source consists of five files:

@itemize @minus

@item @file{name.c} contains the basic functions like
SendRexxCommand(), SetupARexxHost() and ARexxDispatch().  Normally, you
only have to compile this module once, as there are no changes from editing
the command list to this module. The only change in the Box which also
changes this module is the switch for @code{CommandShell}, as the command
shell functions reside in this module.

@item @file{name.h} contains the basic constants and structures for the
ARexx port. Also found here are the prototypes and structure definitions
for all the needed interface functions.

@item @file{name_rxcl.c} carries the global variables, first of all the
list of commands for the interface.

@item @file{name_rxif.c} contains the interface functions.  This is the
only module you have to change.  The Box will automatically keep any
existing code and save functions no longer needed (e.g.  if you have
deleted some commands) to the file

@item @file{name_rxifstore}, from where they can be retrieved later if you
decide to put them in again or want to use them in another application.

@end itemize

@section Oberon
@cindex Source: Oberon

The Oberon source consists of four files:

@itemize @minus

@item @file{RxName.mod} carries the command list and some basic functions
like SetupARexxHost().

@item @file{NameARB.mod} defines the basic constants.

@item @file{NameRXIF.mod} contains all the interface functions and their
data structures. This is the only module you have to edit. Existing
functions will be preserved, functions no longer needed will be moved to
the file

@item @file{Name_rxifstore}, from where you can get them back later.

@end itemize

@section ARB special comments
@cindex Source: ARB comments
@cindex Comments

In the interface module, the Box will generate some comments of the form
@code{/* $ARB:  ...  */} (or on Oberon @code{(* !ARB:  ...  *)}, which must
not be changed in any way.

Somewhere at the top of the interface module there will be a comment
telling to which project file this source module belongs. The Box will
check this ID and reject to extend an existing code which has been
generated from another ARB project.

Each interface function is enclosed in two comments (`B'egin and `E'nd with
ID of function).  All source code between these two comments will be
considered as belonging to this function and will always be preserved (or
moved to the storage file) completely. So if you need some variables or
support functions for an interface function, be sure to define them between
the proper comment lines.

If you changed the definition of a command, the Box will generate a warning
comment right ahead of the corresponding interface function.  This comment
of the form ``ATT:  Interface changed!'' may be removed, but you really
should first check if the code needs to be changed according to the new
arguments or results.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Interfacefunktionen
@comment ----------------------------------------------------------------
@node InterfaceFunctions, Arguments&Results, Files, Top
@chapter Interface Functions
@cindex Interface Functions

@section Basics
@cindex Data structure
@cindex Transfer structure
@cindex Interface structure

An interface function consists of three phases,

@itemize
@item initialization,
@item the working phase and
@item closedown,
@end itemize

which will be called by the ARexxBox routines in this order.

The first phase serves for allocating and initializing the memory for the
transfer data structure that will transfer the arguments and result values
between the basic functions and the interface function.

You can also use this phase for other initializations, e.g. allocating
local buffer memory or the like.

The second phase should do the actual work and use the parameters from the
previously (phase 1) allocated transfer structure. Any results should be
stored into this structure as well before returning.

There are two special elements in every transfer structure, rc and rc2.
These two relate to the normal return codes, any ARexx command may produce.
In addition, the ARB offers an extended error code system (see chapter on
Errors).

After execution of phase 2, the Box will extract all results and send them
back to the ARexx server process.  Then phase 3 will be called for freeing
all locally allocated ressources.

You will find some working examples on the form and function of interface
functions in the directory @file{rxif}.  Especially the --- completely
working --- HELP function should serve well as a complex example.

Anyway, here is the concrete structure of an interface function:

@example
void rx_help( struct RexxHost *host, struct rxd_help **rxd,
              long action, struct RexxMsg *rexxmsg )
@{
    struct rxd_help *rd = *rxd;   /* for simplification and local
                                     extensions */

    struct rxs_command *rxc;      /* local variables */
    int cnt = 1;

    switch( action )
    @{
        case RXIF_INIT:
            /* Phase 1! */
            /* allocate the transfer structure */
            *rxd = calloc( sizeof *rd, 1 );
            /* no defaults to set, so just return */
            break;
            
        case RXIF_ACTION:
            /* Phase 2! */
            /* do it! */
            
            if( rd->arg.prompt )
            @{
                rd->rc = -10;
                rd->rc2 = (long) "Prompt option not yet implemented";
                return;
            @}
            
            and so on, making also some allocations:
                rd->res.commanddesc = malloc( ... )
            and
                rd->res.commandlist = [calloc];
            which have to be freed in phase 3...
            
            break;
        
        case RXIF_FREE:
            /* Phase 3! */
            /* free any allocated ressources */
            
            if( rd->res.commanddesc )
                free( rd->res.commanddesc );
            if( rd->res.commandlist )
                free( rd->res.commandlist );
            
            /* free the transfer object */
            free( rd );
            break;
    @}
    
    /* back to the dispatcher */
    return;
@}
@end example

@section Local Memory
@cindex Local Memory
@cindex static

If you need local memory in an interface function, you must not use static
or global variables in any case! Always remember: Your interface code has
to be reentrant, any interface function may be called many times at once
--- not only if more than one port is open! Also local static variables do
not fit into object oriented design (and would cause big troubles in Oberon
for example).

There's a simple trick for local memory:  Just extend the transfer
structure, add elements for your local variables locally at the end.
Example:

@example
void rx_rx( struct RexxHost *host, struct rxd_rx **rxd,
            long action, struct RexxMsg *rexxmsg )
@{
    struct @{
        /* first the original structure */
        struct rxd_rx rd;
        /* followed by our local extension(s) */
        long tempval;
        char *tempbuffer;
        ...
    @} *rd = (void *) *rxd;
...
@end example

Or in Oberon:

@example
PROCEDURE Rx * (host: rxh.RexxHost; VAR rxd: rxh.RXDPtr; action: INTEGER);
VAR
  rd: POINTER TO RECORD (rxdRx) (* Extension of the original structure *)
    tempval: LONGINT;
    tempbuffer: BT.DynString;
    ...
  END;
...
@end example

As you can see, we made a local extension of the rxd_rx structure, giving
us `local' variables (tempval and tempbuffer).  As the transfer structure
including these extensions will be allocated during the first phase and
freed in the last phase, these variables can be used like local memory
without any conflict.

@section Examples
@cindex rxif examples

There are some example commands (their interface functions) in the
directory named @file{rxif}.  Some of them are ready-to-use, e.g.  the HELP
command only needs an application specific graphical user interface.

If you have written a commonly usable (i.e.  application independant)
command and would like to give it to the whole community of ARexxBox users,
please send it to me (command definition, functionality and source), I will
include it in the next release.

I would like to see a library of standard commands arise, which can easily
be included into any project.  Such a library of ARexx commands would make
ARexx interface development even easier.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Argumente&Resultate
@comment ----------------------------------------------------------------
@node Arguments&Results, Errors, InterfaceFunctions, Top
@chapter Arguments & Results
@cindex VAR
@cindex STEM
@cindex RESULT

@section Arguments
@cindex Arguments
@cindex ReadArgs

The ARexxBox concept has been developed from the ideas and suggestions of
the Style Guide.

One of the essential basics of this concept is to have the arguments of
ARexx commands looking and feeling just like normal shell command
arguments. So the Box uses the DOS function ReadArgs() to parse the
parameters of a concrete command.

First of all, you should now read the chapter on ReadArgs.

Okay. Now to the Box's specialities:

If a command has at least one result field, the Box will automatically
generate the two (invisible) arguments VAR and STEM.

These give the user of the final application the option to choose the
result method.  There are two methods, the first (RESULT/VAR) returns all
assigned result fields concatenated and separated by spaces in one
variable, the second (STEM) uses an ARexx stem variable to separate the
result fields.

If neither VAR nor STEM were specified by the user, method one
(concatenated) will be used to return all results in the standard ARexx
variable @code{RESULT}.

If the user wants to have structured results, she should choose the STEM
method.

VAR and STEM are not mutually exclusive, the user may use both methods at
the same time. There will be no @code{RESULT} variable assignment if at
least one of these options is in use.

@section Results
@cindex Results
@cindex Types

In order to offer a consistant interface in both directions, the ARexxBox
code implements @emph{exactly the same} syntax and method which is used for
arguments also for the results. There's one restriction on the type tags
allowed for results: Only the optional type switches @key{/N} and @key{/M} are
supported up to now. Switches like @key{/K} do not make any sense for
results, and instead of boolean results (@key{/S} or @key{/T}) you better
use integer fields, which are more flexible, as an integer only appears in
the output if set.

Here are the types for results:

@itemize
@item @code{FOOBAR} is a string
@item @code{FOOBAR/M} is an array of strings
@item @code{FOOBAR/N} is an integer (or bool)
@item @code{FOOBAR/N/M} is an array of integers
@end itemize

As you can see, the results (which @emph{your} interface function will
produce!) may be of the same types as the arguments. Of course, all result
fields are optional as well, if you don't assign any value to the foobar
result above, it will not show up in the result of the command.

An example:  Start the Box, open the file @file{arb/Other.arb} and select
the @code{HELP} command.  As you can see, the HELP command has two result
fields, one beeing a simple string (@code{COMMANDDESC}) and one beeing an
array of strings (@code{COMMANDLIST}).

This means, the ARexxBox will generate the following result fields in the
transfer structure for this command, @code{struct rxd_help}:

In C:

@example
    char *commanddesc;
    char **commandlist;
@end example

In Oberon (the types have been resolved for this example):

@example
    commanddesc: BasicTypes.DynString;
    commandlist: POINTER TO ARRAY OF BasicTypes.DynString;
@end example

Your HELP command may set any of these two fields by assigning values to
them, e.g.

@example
    static char *myarray[4] = @{ "foo", "bar", "dubidu", NULL @};
    rxd->res.commanddesc = "Blafasel";
    rxd->res.commandlist = myarray;
@end example

In Oberon you also have to take care of the string length, but the lists
also don't need a closing NIL:

@example
    rxd.res.commanddesc := MoreStrings.CopyString("Blafasel");
    NEW(rxd.res.commandlist,3); (* three entries *)
    rxd.res.commandlist[1] := MoreStrings.CopyString("foo");
    rxd.res.commandlist[2] := MoreStrings.CopyString("bar");
    rxd.res.commandlist[3] := MoreStrings.CopyString("dubidu");
@end example

(Remark:  The normal HELP command will set only one of the two results
(depending on the parameters), but it could assign both if necessary.)

The ARB does all the conversions and assignments which are necessary to
have the result method beeing Style Guide conform: Integers will be
converted to strings, array entries will be counted and their number will
be put in front of them.

You can check it out easily: Start the test program (@file{test/test}) and
enter @code{help} in the command shell. Without any parameter, the command
will produce the list of commands understood by the test program's ARexx
interface, doing so by only assigning the field @code{rxd->res.commandlist}.

The output contains the number of commands (list entries that is) followed
by the commands (entries).  This is the result method for single,
unstructured variables, what you see is exactly what would have been
assigned to the RESULT variable if the command would have been triggered
from ARexx instead of the command shell.  This output may be redirected
into any variable using the keyword @code{VAR}.

Now enter @code{help stem kl.}. Examine the output, this is exactly what
would have been used as an assignment list for ARexx. For this structured
result method, arrays get a new first element called
@code{resultname.COUNT} followed by the entries of the array numbered from
0 upto COUNT-1.

The example above would produce the following result:

Using VAR method:
@example
    "BlaFasel 3 foo bar dubidu"
@end example

Using STEM method with root name hr (recommended method because of the
multiple, structured result values):
@example
    hr.COMMANDDESC = "BlaFasel"
    hr.COMMANDLIST.COUNT = 3
    hr.COMMANDLIST.0 = "foo"
    hr.COMMANDLIST.1 = "bar"
    hr.COMMANDLIST.2 = "dubidu"
@end example

An ARexx program may traverse these lists using a simple loop:

@example
help stem a.
say 'There are' a.commandlist.count 'commands available, that are:'
do i=0 to a.commandlist.count-1
    say a.commandlist.i
    end i
@end example

Do you still have that test program running?  Good.  Enter @code{help stem
single.  help}.  The HELP command will now only assign a value to the
result field @code{COMMANDDESC} (Feld @code{rxd->res.commanddesc}). As you
can see, the output reflects also clearly, which result field has been used
for the result. This only applies to the STEM method.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Fehler
@comment ----------------------------------------------------------------
@node Errors, How2use, Arguments&Results, Top
@chapter Error Codes
@cindex Error Codes
@cindex RC
@cindex RC2

If a command cannot execute normally, it should return an error code
reflecting this condition so the caller can react on the problem.

For this purpose ARexx normally only offers the @code{RC} variable, which
may be set to an integer error code (normal range 0..20).

The ARexxBox offers a slightly extended method with an automatically
generated variable called RC2. This variable can hold error codes as well
as strings (descriptions), which may be read by the calling ARexx program
after command execution.

So we have two error variables, rc and rc2, in every transfer structure.
The sign of rc serves as the type tag for rc2, if rc is positive, rc2 is an
integer value, if rc is negative, rc2 is a string pointer.

Here's an example for an additional integer error code (you should use DOS
error codes where possible):

@example
    rd->rc = 10;
    rd->rc2 = ERROR_NO_FREE_STORE;
@end example

And here's one for an additional error description:

@example
    rd->rc = -10;
    rd->rc2 = (long) "Prompt option not yet implemented";
@end example

The last one again for Oberon:

@example
    rd.rc = -10;
    rd.rc2 = SYSTEM.ADR("Prompt option not yet implemented");
@end example

An integer value will of course be converted to a string, strings will be
passed to ARexx without change.  A negative rc will be converted to
positive.

This extended error return method is not a Style Guide suggestion, but I
think it's a good and usable extension, as you can give the user detailed
error strings in addition to the simple RC value.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Einbindung
@comment ----------------------------------------------------------------
@node How2use, Oberon-2, Errors, Top
@chapter How to use the generated Code
@cindex How to use the Code

@section Design questions
@cindex Design questions
@cindex Software layers

It's a good idea to build applications in an object oriented manner
beginning with the core functions inside and building layers of interface
functions around the core. On an ideal application core one should be able
to build interface functions for any user interface - be it graphical or
textual or...

With such a design, you don't have much problems implementing the interface
layer for the graphical user interface.  And the layer for ARexx consists
of the interface functions pregenerated by the ARexxBox and later completed
by you.  Another interface layer could for example be made for terminals at
the serial port.

A core of basic application functions greatly simplifies the implementation
of the ARexx layer.

A simple example: Imagine an application opening files. This opening of a
file with a given path and name could be a basic core function, errors
could be returned through defined return values to the caller (that is an
interface function).

The GUI layer would then contain a function which gets called by the window
dispatcher if the user chooses submenu ``Open'' from the projects menu.
This function would then open a file requester, read the name and then call
the core function to actually load the file. Any error codes would be given
to the user via suitable requesters.

The corresponding function of the ARexx interface layer needn't do as much,
as it normally will receive the name of the file to open as a parameter.
All it has to do is do a parameter check and then call the same core
function.  Any problems would be returned to ARexx through the error result
fields.

@section Example
@cindex Example test

This example is not an example for the ideal layer design mentioned in the
chapter before, it's merely an example on how to use the basic functions
generated by the ARexxBox.

You should now load the file @file{test/test.c} into your text editor and
examine the implementation of the following steps.

@subsection Initializing

There's only one library you have to open for the ARexxBox generated code,
the @code{rexxsyslib.library}. Of course you should offer an option to the
user for changing the base name of the ARexx port.

If you intend to make use of the result hook mechanism (remember:  to
handle asynchronous results from commands you sent off to ARexx), you
should assign the address of your result hook function to the global
variable @code{ARexxResultHook}.  For Oberon you would redefine the
abstract method `HandleResult' in the proper module of your project.

Now, to open the ARexx port and do all the necessary internal inits, just
call SetupARexxHost().

@subsection CommandShell

The command shell needs an input and an output channel. The example just
opens a normal console window, but you could also use files for that
purpose (e.g. to execute scripts).

The command shell runs synchronously, the call will not return until the
input channel is empty (EOF or Ctrl-\ from the console).

Of course the caller has to close the I/O channels.

@subsection SendRexxCommand

As you can see, sending commands to ARexx is very simple.

If you want to differ between the results your result hook will get, you
have to take care of the result recognization yourself. Remember: The
results will come in an unpredictable order, depending on what the commands
did and what else was running.

One possible method is to store the addresses of all ARexx messages you
send off and later compare them to the addresses of the result messages, as
ARexx will (currently) use the same message object for results. But that
may change anytime, so I'd recommend this method: Use one of the free ARG
fields of an ARexxMessage to store any kind of message ID there. For this
method you will have to do the two steps of SendRexxCommand() yourself by
first calling CreateRexxCommand(), then assigning the ID and then calling
CommandToRexx().

@subsection ARexxDispatch

Now you do what any Amiga application does - wait for signals. If the ARexx
port triggers a signal, you simply call ARexxDispatch(). The ARexx
dispatcher will process all messages on the port and then return.

Of course, the same structure (signal -> dispatcher) can be used for
windows (the whole GUI layer).

@subsection CloseDown

The example program does an indirect closedown, the CloseDownARexxHost()
call is in the function closedown() which was hooked onto the exit
procedure before.  The return of the CloseDown routine may be delayed if
there are any outstanding replies.  Take care:  Also the routine pointed to
by ARexxResultHook may be called in that situation!


@comment ----------------------------------------------------------------
@comment --- Kapitel: Oberon-2
@comment ----------------------------------------------------------------
@node Oberon-2, ReadArgs, How2use, Top
@chapter Hints concerning the Oberon-2 source
@cindex Oberon-2

These are some remarks to the concept, implementation and some design
decisions of the Oberon-2 source by hartmut Goebel.

@section Concept

One design goal of this implementation was to give the programmer full type
safety while retaining the comfortable aspects of Oberon (e.g.  the garbage
collector). This was a challenge to me, as the parameters of the result
structure depend on the result template and cannot be checked at compile
time@footnote{I think the generic procedures in ARBRexxHost (especially
ARBRexxHost.CreatStem) do an elegant job on this problem. I recommend you
have a look at them.}. 

Another goal was to build upon the PortHandle class library, that was under
development right then --- some ideas from ARB have been used there as
well.

As a conclusion from this, the source has been designed in an object
oriented manner. This was no problem, as the original C design is also
object oriented. Merely the interface functions have not been designed to
be methods, as they couldn't be called in a generic way otherwise.

@section Results

While the parameters will be parsed by Dos.ReadArgs() which will put their
values into the special transfer structure (see also 'ReadArgs'), this job
has to be done by ARBRexxHost for the results.  This offers the chance to
at least have the full Oberon type safety and comfort with the results.

The following type equivalence applies to the results (type descriptors
have been resolved):

@itemize
@item @code{FOOBAR} -> @code{BasicTypes.DynString;}
@item @code{FOOBAR/M} -> @code{POINTER TO ARRAY OF BasicTypes.DynString;}
@item @code{FOOBAR/N} -> @code{POINTER TO ARRAY 1 OF LONGINT;}
@item @code{FOOBAR/N/M} -> @code{POINTER TO ARRAY OF LONGINT;}
@end itemize

As you can see, /M results are dynamic arrays. You only need to allocate
them with the needed number of elements and enter the data, for example:
@example
NEW(rx.res.foobar,10);
@end example
for 10 list entries.

You don't need the final NIL (like with C) with Oberon.  This is also the
reason for /M/N results being directly an @code{ARRAY OF LONGINT} instead
of an @code{ARRAY OF POINTER TO LONGINT}.  This is a little inconsistant
for the interface, but much more comfortable.

Parameters and simple numerical results have been declared as @code{POINTER
TO ARRAY 1 OF CHAR}, as Oberon does not support pointers to unstructured
types (although AmigaOberon does).

@section Documentation

As the design and language is completely different from C, the C
documentation is not very good for the Oberon side. This applies especially
to the procedures defined by the PortHandle class library and its extension
ARBRexxHost.

I therefore recommend using the documentation to this library.  You should
find all needed information there. If not, please tell me what misses and I
will complete it.

hartmut Goebel


@comment ----------------------------------------------------------------
@comment --- Kapitel: ReadArgs
@comment ----------------------------------------------------------------
@node ReadArgs, Library, Oberon-2, Top
@chapter ReadArgs
@cindex ReadArgs

ReadArgs() uses ascii templates to know the number and types of the
arguments.  The destination memory is just an array of longwords, which
have to be interpreted by the program corresponding to their types.

Example: A template ``DATEI,ARG1,FORCE'' means there are three possible
arguments. So the destination array must be able to hold at least three
longwords.

@section Template syntax
@cindex ReadArgs: Template syntax

ReadArgs() allows five basic data types identified by special appended
switches in the template string:

@itemize @minus
@item String: Default, no switch
@item Integer: @code{/N}
@item Boolean: @code{/S} for switch or @code{/T} for toggle
@item List: Additionally appended @code{/M} --- lists of strings and integers
are supported
@end itemize

It's essential to remember, that every argument (besides those with
@code{/A} for `Always required') is optional and doesn't need to have any
assignment.

Example: @code{FILE/A,LINES/N,STDIN/S} means, three arguments are possible,
but only the first one must be specified by the user. The first one is a
string, the second an integer and the third is a boolean.

It is possible to force the user to put the keyword before an argument by
adding the @code{/K} switch, this may be necessary for complex templates.
Also you can define aliases for a keyword (e.g. abbreviations).

Example: @code{FILES/M/A,AS=TO/K/A} is the template for the AmigaDOS join
command. It forces the user to put either `AS' or `TO' right before the
destination file. Valid argument lines for this template would be:

@itemize
@item @code{file1 file2 as ram:dest}
@item @code{foo bar test to blafasel}
@item @code{as=ram:test source1 source2 source3 source4}
@end itemize

The last example demonstrates that ReadArgs() doesn't need a fixed order of
the parameters if the user specifies the keywords.  And `KEYWORD DATA' is
equivalent to `KEYWORD=DATA'.

Forcing the user to use the keywords is a must be in many situations with
multiple arguments, as ReadArgs() would otherwise have problems to differ
between those arguments for the array and those for the other arguments.

@section Results
@cindex ReadArgs: Results

Boolean arguments can be specified or not in an actual argument line, so
their state is represented by a plain longword.

All other types are completely optional, so they are represented not by
objects but by pointers to objects.  If a pointer is NULL, no value was
specified for the related argument.  Strings are pointers to characters,
integers are pointers to longwords.  Lists are NULL--terminated arrays of
pointers to either strings or longwords.

The following type equivalence results for C:

@itemize
@item @code{String} @result{} @code{char *}
@item @code{Array of strings} @result{} @code{char **}
@item @code{Integer} @result{} @code{long *}
@item @code{Array of integers} @result{} @code{long **}
@item @code{Boolean} @result{} @code{long}
@end itemize

The module ARBRexxHost defines these types for Oberon.

Another example:  The template
@code{FILES/M/A,AS=TO/K/A,FORCE/S,MAX/N,SOUND/T,LINES/N/M} would have the
following data structure for the argument values:

@example
struct readargs_result
@{
    char **files;
    char *to;
    long force;
    long *max;
    long sound;
    long **lines;
@} rda_result;
@end example

(Remark:  This template is not correct, it's merely an example for the type
equivalence.  Actually a template may contain only @emph{one} @key{/M}
switch.)

The fields of the structure may be assigned default values before calling
ReadArgs(), the system call will only alter those elements whose arguments
have been specified by the user.  Boolean arguments are different:  /S
arguments will always be set according to their keyword being specified (if
not specified, the value will be zero), but /T arguments will toggle the
previously set default value --- in theory, I haven't tested this behaviour
yet.

So for strings and integers you can see from the primary pointer in the
structure above, if the parameter has been specified at all. Otherwise the
pointer is NULL.

Arrays may be of any size, so their end has to be marked by a NULL entry.

@section More Features
@cindex ReadArgs: More Features

There's another switch, @key{/F}, used to assign an argument the whole rest
of the command line from that point, no matter what keywords or special
characters may be in it. You normally don't need this one and should take
care if you use it.

Parameters which are not set in between quotation marks by the user will
first be checked against the possible keywords.  So an input of ``foo bar
all qwe'' to a template ``Dir/M,All/S'' will set the switch ALL and return
the array ``foo'', ``bar'', ``qwe'' in DIR.  If the user had specified
``all'' in quotation marks, it would have been taken into the array instead
of being considered as being the ALL switch.

As mentioned above, you should not have more than one array (@key{/M}) per
template to avoid problems.

If there are unassigned /A arguments left after parsing, ReadArgs() will
first try to fill them with the last elements of any /M type argument. An
example for this behaviour is the copy command: The template ``From/A/M,To/A''
with an input of ``copy file1 file2 file3 destination'' will assign the
last word to the TO argument --- just like you'd expect it to do.

On ReadArgs please also see @file{AutoDocs:dos.doc}.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Library
@comment ----------------------------------------------------------------
@node Library, FileFormat, ReadArgs, Top
@chapter Library

@menu
TABLE OF CONTENTS

* ARexxBox/ARexxDispatch::
* ARexxBox/CloseDownARexxHost::
* ARexxBox/CommandShell::
* ARexxBox/CommandToRexx::
* ARexxBox/CreateRexxCommand::
* ARexxBox/DoShellCommand::
* ARexxBox/ExpandRXCommand::
* ARexxBox/FindRXCommand::
* ARexxBox/FreeRexxCommand::
* ARexxBox/ReplyRexxCommand::
* ARexxBox/SendRexxCommand::
* ARexxBox/SetupARexxHost::
* ARexxBox/StrDup::
@end menu

@comment ----------------------------------------------------------------
@node ARexxBox/ARexxDispatch, ARexxBox/CloseDownARexxHost, , Library
@section ARexxBox/ARexxDispatch
@cindex ARexxBox/ARexxDispatch

@example
ARexxBox/ARexxDispatch                                 ARexxBox/ARexxDispatch

   NAME
        ARexxDispatch -- get ARexx command from MsgPort and execute it

   SYNOPSIS
        ARexxDispatch( rexxhost );

        void ARexxDispatch( struct RexxHost * );

   FUNCTION
        ARexxDispatch fetches and executes all queued commands from
        the given RexxHost's message port.
        
        If a reply for some previously (with SendRexxCommand()) sent
        command comes in, the counter variable for still outstanding
        replies will be decreased by one and the RexxMsg and it's
        associated memory will be freed by FreeRexxCommand().
        
        In the main program, you should just check for the signal
        of the host's message port and call ARexxDispatch()
        without actually getting the message. All work will be
        done by the dispatcher.

   INPUTS
        rexxhost - pointer to an active RexxHost structure with
                   a valid MsgPort

   RESULTS

   SEE ALSO
        SendRexxCommand(), SetupARexxHost(), DoShellCommand()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/CloseDownARexxHost, ARexxBox/CommandShell, ARexxBox/ARexxDispatch, Library
@section ARexxBox/CloseDownARexxHost
@cindex ARexxBox/CloseDownARexxHost

@example
ARexxBox/CloseDownARexxHost                       ARexxBox/CloseDownARexxHost

   NAME
        CloseDownARexxHost -- close & free ARexx host

   SYNOPSIS
        CloseDownARexxHost( rexxhost );

        void CloseDownARexxHost( struct RexxHost * );

   FUNCTION
        CloseDownARexxHost() waits until replies for all pending
        ARexx commands have been received and then closes the
        ARexx port and frees all memory associated with that
        RexxHost structure.
        
        All messages sent to a closing host will be replied
        immediately with an error "Host closing down".

   INPUTS
        rexxhost - the RexxHost to close down

   RESULTS

   SEE ALSO
        SetupARexxHost(), SendRexxCommand()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/CommandShell, ARexxBox/CommandToRexx, ARexxBox/CloseDownARexxHost, Library
@section ARexxBox/CommandShell
@cindex ARexxBox/CommandShell

@example
ARexxBox/CommandShell                                   ARexxBox/CommandShell

   NAME
        CommandShell -- process Commands from a file

   SYNOPSIS
        CommandShell( rexxhost, fhin, fhout, prompt );

        void CommandShell( struct RexxHost *, BPTR, BPTR, char * );

   FUNCTION
        CommandShell() sets the Flag ARB_HF_CMDSHELL in the
        RexxHost's flag field and then processes input from fhin
        until EOF or the CmdShell flag in the RexxHost being cleared
        (e.g. by the standard Rexx command "CMDSHELL CLOSE").
        
        The input is read line-wise, with newline as EOL. Each
        line will be parsed and executed just like a built-in custom
        ARexx command, exactly like it was called via an ARexx host
        messageport.
        
        The parsing and execution of each line is done by the
        function DoShellCommand().
        
        If fhout is not NULL, the output of the commands will be
        printed to fhout. The output of the commands will NOT be
        assigned to any variables, as there is no underlying ARexx
        script program that could hold these variables. Instead,
        the output will be formatted to be human-readable.
        
        The prompt string (if not NULL) will be printed to fhout
        as an input request before reading an input line.
        
        New (ARB 0.99d): The rexxhost parameter has to point to a
        valid RexxHost structure. This is for identifying which
        command shell belongs to which window/instance of the main
        process.
        
        New( ARB 0.99e):  To support the "RX" command sending
        asynchronous messages to ARexx, this function now catches
        the replies of those messages and frees them using
        FreeRexxCommand().  Messages sent _to_ this host will be
        replied immediately with an error "CommandShell Port".

   INPUTS
        rexxhost - an initialized RexxHost structure
        fhin - the input FileHandle (see dos.library/Open())
        fhout - the output FileHandle (or NULL)
        prompt - the prompt string (or NULL)

   RESULTS

   SEE ALSO
        DoShellCommand(), ARexxDispatch(), dos.library/Open()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/CommandToRexx, ARexxBox/CreateRexxCommand, ARexxBox/CommandShell, Library
@section ARexxBox/CommandToRexx
@cindex ARexxBox/CommandToRexx

@example
ARexxBox/CommandToRexx                                 ARexxBox/CommandToRexx

   NAME
        CommandToRexx -- send a prepared RexxMsg to the ARexx server

   SYNOPSIS
        msg = CommandToRexx( rexxhost, rexxmessage );

        struct RexxMsg *CommandToRexx( struct RexxHost *, struct RexxMsg * );

   FUNCTION
        CommandToRexx just sends the given RexxMsg to the ARexx
        server process without changing any fields of the Msg.
        It will also increment the counter for outstanding replies
        in the RexxHost structure.
        
        You can use this function together with CreateRexxCommand()
        to easily create customizable command messages for Rexx.

   INPUTS
        rexxhost - an initialized RexxHost structure
        rexxmessage - an initialized ARexx message

   RESULTS
        msg - the same as rexxmessage, just for easy further processing

   SEE ALSO
        CreateRexxCommand(), SendRexxCommand()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/CreateRexxCommand, ARexxBox/DoShellCommand, ARexxBox/CommandToRexx, Library
@section ARexxBox/CreateRexxCommand
@cindex ARexxBox/CreateRexxCommand

@example
ARexxBox/CreateRexxCommand                         ARexxBox/CreateRexxCommand

   NAME
        CreateRexxCommand -- allocate & initialize rexxmsg for a command

   SYNOPSIS
        rexxmsg = CreateRexxCommand( rexxhost, command, fh );

        struct RexxMsg *CreateRexxCommand( struct RexxHost *, char *, BPTR );

   FUNCTION
        This function will create a RexxMsg structure for the given
        RexxHost, create an Argstring from the command string and
        use that string to initialize the message as a RXCOMM type
        with RXFF_RESULT requested.
        
        The file handle will be used for both input and output.
        
        You can use this function to create a standard ARexx command
        with the additional possibility to set some extra parameters
        before sending the command to ARexx using CommandToRexx().

   INPUTS
        rexxhost - an initialized RexxHost structure
        command - the command string
        fh - the input/output FileHandle (see dos.library/Open())

   RESULTS
        rexxmsg - a pointer to the new RexxMsg structure

   SEE ALSO
        CommandToRexx(), SendRexxCommand(), dos.library/Open()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/DoShellCommand, ARexxBox/ExpandRXCommand, ARexxBox/CreateRexxCommand, Library
@section ARexxBox/DoShellCommand
@cindex ARexxBox/DoShellCommand

@example
ARexxBox/DoShellCommand                               ARexxBox/DoShellCommand

   NAME
        DoShellCommand -- parse & execute a command line

   SYNOPSIS
        DoShellCommand( rexxhost, commandline, fhout );

        void DoShellCommand( struct RexxHost *, char *, BPTR );

   FUNCTION
        DoShellCommand parses the given string assuming it contains
        an ARexx-style command line.
        
        New (ARB 0.99e):  If normal parsing fails, the external
        function ExpandRXCommand() will be called to expand any
        macros.  If the expansion fails or the expanded command
        can't be recognized either, an error will be returned.
        
        If no errors occur during parsing, it tries to execute the
        command with the given arguments. The results of the command's
        execution will be printed in a human-readable format to fhout
        if fhout is not NULL.
        
        If errors occur, DoShellCommand prints a string describing
        the error to fhout (if not NULL).
        
        New (ARB 0.99d): The rexxhost parameter has to point to a
        valid RexxHost structure. This is for identifying which
        command shell belongs to which window/instance of the main
        process.

   INPUTS
        rexxhost - an initialized RexxHost structure
        commandline - the string to be parsed & executed
        fhout - the output FileHandle (or NULL)

   RESULTS
        none

   SEE ALSO
        CommandShell(), ExpandRXCommand(), <dos/dos.h>

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/ExpandRXCommand, ARexxBox/FindRXCommand, ARexxBox/DoShellCommand, Library
@section ARexxBox/ExpandRXCommand
@cindex ARexxBox/ExpandRXCommand

@example
ARexxBox/ExpandRXCommand                             ARexxBox/ExpandRXCommand

   NAME
        ExpandRXCommand -- expand macros and/or aliases (V0.99e)

   SYNOPSIS
        newcommand = ExpandRXCommand( rexxhost, oldcommand )

        char *ExpandRXCommand( struct RexxHost *, char * );

   FUNCTION
        This is an 'external' function you should provide if you
        want to have command aliases or the like. The minimal
        version of this function is just a return(NULL) as generated
        in the rxif module.
        
        ExpandRXCommand() will be called by the parser if it doesn't
        know how to interpret a command string. Expansion could now
        for example be a look up in the host's macro table.
        
        Any strings returned by this function have to be allocated
        explicitly using the standard C memory functions.  The
        calling parser will free() them.

   INPUTS
        rexxhost - the RexxHost we are working on
        oldcommand - the commandline the parser doesn't know

   RESULTS
        newcommand - an explicitly allocated memory area con-
                     taining the expanded command (or NULL)

   SEE ALSO
        DoShellCommand(), ARexxDispatch()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/FindRXCommand, ARexxBox/FreeRexxCommand, ARexxBox/ExpandRXCommand, Library
@section ARexxBox/FindRXCommand
@cindex ARexxBox/FindRXCommand

@example
ARexxBox/FindRXCommand                                 ARexxBox/FindRXCommand

   NAME
        FindRXCommand -- search the ARexxBox command table (V0.99e)

   SYNOPSIS
        rxscmd = FindRXCommand( command )

        struct rxs_command *FindRXCommand( char * );

   FUNCTION
        This function returns a pointer to the given command's entry
        in the ARexxBox-generated command table.  It exists to
        support those functions working on/with commands, like HELP
        or ENABLE/DISABLE.
        
        This function does no macro expansion.  The comparisons are
        case independant so you don't have to convert your input to
        upper case beforehand.  As this is exactly the routine used
        by the parser to find a command, it will handle
        abbreviations.

   INPUTS
        command - the command name to search for

   RESULTS
        rxscmd - the rxs_command structure of that command
                 (or NULL if command not found)

   SEE ALSO

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/FreeRexxCommand, ARexxBox/ReplyRexxCommand, ARexxBox/FindRXCommand, Library
@section ARexxBox/FreeRexxCommand
@cindex ARexxBox/FreeRexxCommand

@example
ARexxBox/FreeRexxCommand                             ARexxBox/FreeRexxCommand

   NAME
        FreeRexxCommand -- free the associated memory of a RexxMsg

   SYNOPSIS
        FreeRexxCommand( rexxmessage );

        void FreeRexxCommand( struct RexxMsg * );

   FUNCTION
        This is basically a PD ARexx routine provided by William S. Hawes.
        
        It frees all memory associated with a particular (previuosly sent)
        ARexx message structure. It will also close any stdin/stdout
        channels associated to that Rexx message.
        
        You normally shouldn't have to bother with this one because the
        dispatcher will call it for you.

   INPUTS
        rexxmsg - the rexx message to free

   RESULTS

   SEE ALSO
        SendRexxCommand()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/ReplyRexxCommand, ARexxBox/SendRexxCommand, ARexxBox/FreeRexxCommand, Library
@section ARexxBox/ReplyRexxCommand
@cindex ARexxBox/ReplyRexxCommand

@example
ARexxBox/ReplyRexxCommand                           ARexxBox/ReplyRexxCommand

   NAME
        ReplyRexxCommand -- reply a rexx message from rexxmast

   SYNOPSIS
        ReplyRexxCommand( rexxmsg, primary, secondary, result );

        void ReplyRexxCommand( struct RexxMsg *, long, long, char * );

   FUNCTION
        This is a PD ARexx routine provided by William S. Hawes.
        
        It replies a given rexx message to the rexx master process,
        filling in a primary and a secondary return code plus
        optionally a supplied result string.
        
        The result string will only be converted to an ARexx string,
        if the primary return code equals 0, and will then destroy the
        contents of the secondary return code. So you provide either
        primary and secondary return codes or a result string.
        
        You normally shouldn't have to call this function!
        It is only mentioned here, because it is not part of the
        ARexxBox routines, but part of the original ARexx distribution
        by William S. Hawes.
        
        New (ARB V0.99d): Now creates an ARexx variable "RC2" for the
        secondary return code. If primary is positive, secondary is
        interpreted as a long, if primary is negative, secondary is
        interpreted as a char *. RC will become positive in any case.
        
        RC2 will only be assigned if the ARexx RESULT flag is set.

   INPUTS
        rexxmsg - the message structure to reply
        primary - the primary return code (rc)      ( >0      <0   )
        secondary - the secondary return code (rc2) (long or char *)
        result - the result string

   RESULTS

   SEE ALSO
        SendRexxCommand(), FreeRexxCommand()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/SendRexxCommand, ARexxBox/SetupARexxHost, ARexxBox/ReplyRexxCommand, Library
@section ARexxBox/SendRexxCommand
@cindex ARexxBox/SendRexxCommand

@example
ARexxBox/SendRexxCommand                             ARexxBox/SendRexxCommand

   NAME
        SendRexxCommand -- invoke rexx command script

   SYNOPSIS
        rexxmsg = SendRexxCommand( rexxhost, command, filehandle )

        struct RexxMsg *SendRexxCommand( struct RexxHost *, char *, BPTR );

   FUNCTION
        This is basically a PD ARexx routine provided by William
        S. Hawes.
        
        This function sends the given command string to the ARexx
        master process for execution as an ARexx command. The
        command string contains the file name of the ARexx script
        to be started. If the filehandle is not NULL, it will be
        used as stdin and stdout for the Rexx script. If it is
        NULL, the Rexx program will use stdin/stdout of the
        calling process.
        
        If necessary, the default extension (defined in the
        generated header file under the name REXX_EXTENSION) will
        be added to the file name.
        
        Messages sent using this function will be replied to by
        the ARexx master process as soon as the execution of the
        command script stops. The application MUST NOT close
        it's messageport before all replies have been received!
        To simplify things, ARexxBox does this book-keeping for you.
        CloseDownARexxHost() will wait for all missing replies to
        arrive before closing down the messageport.
        
        The dispatcher will automagically detect any replies,
        count them and do a FreeRexxCommand() for each reply, so
        you don't have to bother with this either.
        
        Internally, this function is implemented using the two
        more atomic functions CreateRexxCommand() and
        CommandToRexx().

   INPUTS
        rexxhost - the RexxHost to be used to send the command
        command - the file name of the ARexx script
        filehandle - Filehandle for stdin/stdout or NULL

   RESULTS
        rexxmsg - the sent rexx message structure (for comparisons)

   SEE ALSO
        FreeRexxCommand(), CloseDownARexxHost(), ARexxDispatch(),
        CreateRexxCommand(), CommandToRexx()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/SetupARexxHost, ARexxBox/StrDup, ARexxBox/SendRexxCommand, Library
@section ARexxBox/SetupARexxHost
@cindex ARexxBox/SetupARexxHost

@example
ARexxBox/SetupARexxHost                               ARexxBox/SetupARexxHost

   NAME
        SetupARexxHost -- initialize and open an ARexx host

   SYNOPSIS
        rexxhost = SetupARexxHost( basename );

        struct RexxHost *SetupARexxHost( char * );

   FUNCTION
        This function allocates and initializes a RexxHost
        structure. It opens a public message port under the
        given basename. If no basename (NULL) was specified,
        the default basename as entered in the ARexxBox window
        will be used instead.
        
        Anyway, if a public port of that name already exists,
        SetupARexxHost() will start adding numbers to the name
        until a unique name is found. So if for example the
        basename is "myhost" and there is already a port of that
        name in the system, the name will be changed to
        "myhost.1" (then to "myhost.2" and so on).
        
        The actual name will be copied to the portname field of
        the RexxHost structure. It is a good idea to tell the
        user about the actual port name of the new host.

   INPUTS
        basename - the messageport basename or NULL

   RESULTS
        rexxhost - the initialized RexxHost structure, ready to
                   go. Pass this pointer to CloseDownARexxHost(),
                   ARexxDispatch() and SendRexxCommand().

   SEE ALSO
        CloseDownARexxHost(), ARexxDispatch(), SendRexxCommand()

@end example

@comment ----------------------------------------------------------------
@node ARexxBox/StrDup, , ARexxBox/SetupARexxHost, Library
@section ARexxBox/StrDup
@cindex ARexxBox/StrDup

@example
ARexxBox/StrDup                                               ARexxBox/StrDup

   NAME
        StrDup -- duplicate a string

   SYNOPSIS
        copy = StrDup( origin );

        char *StrDup( char * );

   FUNCTION
        This routine will do exactly the same as its standard C lib
        counterpart strdup(), but use the exec function AllocVec()
        for allocating the needed memory.
        
        (So YOU are responsible for freeing the copy!)

   INPUTS
        origin - the original string

   RESULTS
        copy - the copy of the original string

   SEE ALSO
        strdup(), exec.library/AllocVec(), exec.library/FreeVec()

@end example


@comment ----------------------------------------------------------------
@comment --- Kapitel: Dateiformat
@comment ----------------------------------------------------------------
@node FileFormat, History, Library, Top
@chapter File Format
@cindex File Format

The ARB file format is an extendable ASCII format (line separator is LF).
Besides the obvious data (syntax of the commands, their arguments and
results) an ARB file contains common and command specific tags.

The first line of an ARB file contains the ID string @code{ARB}.
Beginning with line two comes the first, global tag block. Each tag line
begins with a dollar followed without a space by the tag ID (type: long).
The rest of the line contains alphanumeric parameters, separated by spaces.

Up to now there's only one global tag ID:

@itemize
@item ID 1, two parameters:
 @enumerate
 @item File-ID (unsigned long): This is the ID used by ARB to tell
  if an existing source belongs to the project.
 @item Next-Cmd-ID (unsigned long): The ID for the next new command
  (which is @emph{not} the number of commands!).
 @end enumerate
@end itemize

The first line after this tag block contains the MsgPort base name. The
next line contains the status of the CommandShell gadget (1 for checked).
The following lines up to the end of the file are the command definitions.
Each command entry is of the form:

@itemize
@item Command name
@item Tag block (first char = @code{$}, followed by the tag ID as above)
@item Arguments (one per line)
@item Separator (line containing just a `minus')
@item Results (one per line)
@item Another separator line
@end itemize

There are currently two tag IDs for commands:

@itemize
@item ID 1, two parameters:
 @enumerate
 @item Command-ID (unsigned long): For identifying the command
  in an existing source.
 @item Status (char): `N' for `New', `C' for `Changed'
  or `O' for `Old'.
 @end enumerate
@item ID 2, one parameter:
 @enumerate
 @item ExtStatus (char): Like Status, for documentation status of cmd.
 @end enumerate
@end itemize

There will possibly be other tag IDs in the future, so please write an
intelligent parser for the tag blocks. Unknown tags should be ignored.


@comment ----------------------------------------------------------------
@comment --- Kapitel: Geschichte
@comment ----------------------------------------------------------------
@node History, Thanks, FileFormat, Top
@chapter History
@cindex History

History of ARexxBox Releases:

@example
V0.99
    first beta release

V0.99a
    FIXED: Argument and result lists could work on an
    invalid command -> Enforcer-Hit/Crash.
    (Report: RALF_KAISER@@AWORLD)

V0.99b
    ENHANCED: GadToolsBox source fixed to use the System Default
    Font instead of the Screenfont for Layout and Gadgets.
    (Report: SYSOP@@INSIDER [Garry Glendown])

V0.99c
    FIXED: The equal sign '=' wasn't allowed for arguments.
    
    FIXED: After changing some argument or result, the display
    now shows the changed element, rather than the last one
    in that list.
    
    FIXED: The font routines still had some error.
    (Report: F.J.Reichert [F_J_REICHERT@@SAARAG])

V0.99d
    FIXED: All pointer conversions are now clean. The code
    should now be compileable without warnings.
    Added pragma #includes and _toupper() for SAS/C.
    (Report: W_KUETING@@HSP)
    
V0.99e
    FIXED: When _no_ result field was given, the code
    generated an "out of memory" error.
    
    ENHANCED: ReplyRexxCmd() now creates the variable RC2, it
    contains the "Secondary Returncode", which can be set in
    any rxif-structure under the name rc2. This variable can
    be used to return detailed error codes to the calling
    rexx program.
    
    This feature is an extension of the style guide conventions,
    IMHO a good one. If you have complaints or comments on 
    this idea, please tell me!
    
    RC2 will only be generated if a) 'options results' was given
    and b) RC != 0. The field rc2 may contain an error code (long)
    as well as an error string (char *). Code is the default.
    The software distinguishes these two types by the sign of
    rc, rc positive means rc2 is a long, rc negative means rc2
    is a char *.
    A negative rc will be converted to positive before beeing
    returned to the caller.
    
    Example for error CODE:
        rd->rc = 10;
        rd->rc2 = ERROR_OBJECT_NOT_FOUND;
    
    Example for error STRING:
        rd->rc = -10;
        rd->rc2 = (long) "You idiot! No object!";
    
    The standard error strings are _not_ localized. As soon as
    I get some infos and tools for this, I'll do it.

    ENHANCED: SendRexxCommand() now has a new parameter for
    better supporting the standard command "RX". It is a
    FileHandle (BPTR!), which becomes the stdin/stdout of
    the executed arexx script. FreeRexxCommand() closes
    the file (if necessary).
    
    SendRexxCmd() now returns the address of the sent
    RexxMsg structure (or NULL for error).
    
    ENHANCED: The RexxHost structure now has a new field
    called "userdata". It can be used to hook the RexxHost
    onto your own structures, e.g. for linking hosts and
    and their project instances together.
    
    ENHANCED: Every command now has a global "enabled"
    flag. If the flag is 0, the dispatcher will not execute
    that command anymore until the flag will be set again.
    The user should have the ability to manipulate this flag
    using the (standard) arexx commands ENABLE and DISABLE
    (see rxif/*.c).
    
    CHANGED: Any CommandShell now must have its own RexxHost,
    that means that host _must_not_ be used as a normal ARexx
    port simultaneously.
    
    ENHANCED: As a consequence, every rxif function now gets
    the RexxHost of the ARexx port resp. CmdShell as it's
    (first) parameter. Therefore the function can decide
    whether it was called from ARexx or from a Shell and
    on which project it should work.
    
    ENHANCED: Another consequence is the new flag ARB_HF_CMDSHELL
    for supporting the standard command CMDSHELL. The flag is
    in the 'flags' field of the RexxHost structure. If it's
    set, that host is currently running a shell. You can
    clear the flag from anywhere causing the shell to close
    (after processing the next command).
    
    FIXED: ARB no longer accepts argument or result names
    consisting of only spaces or only options.
    
    CHANGED: As some rxif functions have to access them,
    the structs 'rxs_command' and 'rxs_commandlist' are now
    defined in the headerfile. For accessing the command
    list, there is a new function:
        struct rxs_command *FindRXCommand( char *name );
    
    FIXED: Arguments with '=' are now translated correctly
    into variable names for C. The last alias component
    will be used as the var name.
    
    ENHANCED: There is now a callback function for words
    the parser doesn't recognize:
        char *ExpandRXCommand( struct RexxHost *host,
                               char *commandline );
    This function will be called before the parser returns
    an error. If the function returns NULL, the error will be
    generated, if not, the parser assumes that the function
    was able to analyze the input and tries to parse the
    returned string.
    This function can be used to implement command aliases
    or processing of non-standard commands.
    
    Attention! ExpandRXCmd() has to allocate memory for the
    returned string, using standard C functions! This memory
    will be freed by the parser after processing the string!
    
    ENHANCED: ARB now does more safety checks on saving the
    source modules, so you should never accidentally destroy
    other code.
    
    NOTE: One of the standard commands as suggested by the
    style guide uses the keywords "VAR" and "STEM" to
    describe the INPUT variables instead of the former
    usage as OUTPUT descriptors. I don't think this is a
    good choice as there can't be any results from this
    function that way. I suggest other names for those
    arguments, e.g. "FROMVAR" and "FROMSTEM".
    Comments?
    
    (The ARB doesn't look at the already existing args, if
    a command has some result, "VAR" and "STEM" will be
    added to the template.)
    
    Some of the style guide suggestions are not very precise
    and need extensions to operate correctly. I added some
    extensions to the arexx standard commands. Comments
    welcome.
    
    FIXED: Numeric results now work.

V0.99f
    ENHANCED: ARB now uses two FileRequesters, one for the
    binaries and the other for sources. The patterns now
    remain what you set them to and have defaults with #?
    instead of *.
    (Report: Stefan Zeiger)
    
    FIXED: Window->TopEdge is now font sensitive.
    (Report: Stefan Zeiger)
    
V0.99g
    FIXED: The parser now returns the ReadArgs() error code
    in rc2.
    
    CHANGED: No longer appends \n to the template string
    before parsing (not needed).
    
    CHANGED: The ARexxBox now uses the ASL file requester.
    (Wish: Garry Glendown [Sysop@@Insider])
    
V1.00
    ENHANCED: Source now compatible to GCC. Remaining
    warnings may be ignored.
    
    CHANGED: FindRXCommand() now only accepts real abbreviations
    of commands.
    
--- FIRST PUBLIC RELEASE ---
    
V1.01
    ENHANCED: FindRXCommand() now uses binary search
    (so it's now complexity O(log n) instead of O(n))

V1.02
    ADDED: Clipboard support
    
    FIXED: CreateVAR() didn't check an allocation
    (Report: Rüdiger Dreier)
    
    CHANGED: SendRexxCommand() is now divided into two functions,
    CreateRexxCommand() and CommandToRexx(). So one can change a
    created msg if needed before sending it to ARexx.
    
    ENHANCED: Unknown commands will now be sent to ARexx before
    being treated as "unknown". External ARexx programs will be
    called in a transparent way with this method.
    (Suggestion: Rüdiger Dreier)
    
    ENHANCED: DoRXCommand() and DoShellCommand() polished a bit.
    (Report: Hartmut Goebel)
    
    FIXED: The dispatcher now checks incoming msgs.
    (Report: Hartmut Goebel)
    
    FIXED: In free_stemlist() was a potential FreeMem bug.
    
    CHANGED: Now using AllocVec/FreeVec instead of (m|c)alloc and free.
    Needed a new function as well, a replacement for strdup:
        char *StrDup( char *string )
    (Suggestion: Rüdiger Dreier)
    
    FIXED: The CloseDown could cause running scripts on that port to hang.
    (Report: Rüdiger Dreier)
    
V1.03
    ENHANCED: New parameter for the Box: FONT=<name>/<size>, specifies
    the font to use. Default is now again the Screen font (Style Guide).
    (Suggestion: Timothy J. Aston)

    CHANGED: If an empty port name was specified, the default will be used.
    (Suggestion: hartmut "Essich" Goebel)

    CHANGED: VAR and STEM parameters will now be converted to upper case,
    as SetRexxVar() doesn't do this by itself.
    (REXX standard)

V1.04
    FIXED: Path for project files will be kept when importing files via
    "Merge".
    (Report: Stefan Reisner)
    
    FIXED: ARG0 now casted to (char *) everywhere.
    (Report: Marc Schröer)
    
    ENHANCED: The header now has got it's own #define.
    (Marc Schröer)
    
V1.05
    ENHANCED: Source generation now intelligent, old interface functions
    will be recognized through special comments in the source and either be
    kept or moved to a storage file.
    (Suggestion: all.all; ID idea: Christoph Teuber)
    
    CHANGED: File format changed to reflect the new source generation.
    The Box will read the old format.
    
    ENHANCED: SetupARexxHost() now needs a second parameter: An optionally
    previously allocated MsgPort. So one can use a special port, e.g. to
    use one signal for all ARexx ports.
    (Suggestion: Stefan Reisner)
    
V1.10
    ENHANCED: The Oberon source generator is there at last. The
    Oberon source is completely by the Oberon Wizard Extraordinary
    hartmut "Essich" Goebel. Questions and comments concerning
    Oberon please go directly to him, as I don't know Oberon.
    
    ENHANCED: Implemented result hook method, if the variable
    ARexxResultHook contains the address of a function, it will be
    called for all replies to messages sent to ARexx.
    
    FIXED: FreeRexxCommand() no longer closes stdin and stdout if
    these were entered.

V1.11
    FIXED: Some last changes for Oberon.

----------- Release 2 -------------

V1.12
    FIXED: The HELP command produced Enforcer hits (strlen(0)).
    (Report: Klaas Hermanns)
    
    ENHANCED: Introduced tag #2 for commands: External status flag,
    "New" state of this flag will only be reset by external programs,
    e.g. documentation aids like ARB2TeXinfo by Albert Weinert.
    (Suggestion: Albert Weinert)
    
    FIXED: The command list was generated not alphabetically but
    numerically sorted (by their IDs).
    (Report: Klaas Hermanns)
    
    ENHANCED: Instead of the binary search algorithm, the Box now
    generates a real finite state machine for searching of commands
    (FindRXCommand). The binary search method had a big design flaw
    with abbreviations on the alphabetically sorted list of commands.
    (ATT: This has been implemented for C only up to now!)
    (Report: Klaas Hermanns)
    
    FIXED: For SAS C, toupper() will be #undefined. Also there is now
    the real function cast in the list of commands.
    (Report: Klaas Hermanns)
    
    FIXED: The MIN and MAX results of Misc.arb/GETATTR have to be
    numbers, of course.
    (Report: Klaas Hermanns)
    
    FIXED: "Merge" trashed the command list when merging in existing
    commands.
    
    CHANGED: Now declares the external library bases with their
    appropriate types (C).
    (Wunsch: Klaas Hermanns)
    
    CHANGED: In arb/advanced.arb, commands REQUESTNUMBER and
    REQUESTSTRING, I changed the argument called "DEFAULT" to "DEFAULTNUM"
    resp. "DEFAULTSTR" to avoid conflicts with the 'default' keyword in C.
    (Report: Klaas Hermanns)
    
    ENHANCED: There's now another parameter for all interface functions
    called "struct RexxMsg *rexxmsg", which will contain the address of
    the message from REXX if called by ARexx. If called from a command
    shell, it will contain NULL, so you can also use it to determine the
    caller. This is to support GetRexxVar(), which needs this pointer.
    (Report: Klaas Hermanns)
    
    FIXED: I now define toupper() as a function for GCC. The macro caused
    problems by evaluating the parameter more than once.

    FIXED: The command shell parameter parsing had a bug (the ReadArgs
    buffer wasn't cleared).
    
----------- Release 3 -------------
@end example


@comment ----------------------------------------------------------------
@comment --- Kapitel: Danksagungen
@comment ----------------------------------------------------------------
@node Thanks, Index, History, Top
@chapter Thanks
@cindex Thanks

I'd like to thank the following persons:

@itemize

@item The people behind the Amiga, for the Amiga and AmigaOS Release 2.

@item William S. Hawes, for his excellent port of Rexx.

@item Jan van den Baard, for his GadToolsBox, which inspired me and was a
great help in designing the user interface.

@item Nico Francois, for his reqtools.library with its really
programmer and user friendly requesters.

@item hartmut Goebel, for the Oberon-2 source.

@item All my active beta testers and all who sent me suggestions (see
history).

@item Christoph Teuber and Oliver Wagner, for the AWorld Mailbox System.

@end itemize


@comment ----------------------------------------------------------------
@comment --- Kapitel: Index
@comment ----------------------------------------------------------------
@node Index, , Thanks, Top
@unnumbered Index

@printindex cp

@comment ----------------------------------------------------------------


@comment ----------------------------------------------------------------
@comment --- Inhaltsverzeichnis (nur gedrucktes Dokument)             ---
@comment ----------------------------------------------------------------
@contents

@bye
