Programming AmigaOS in C

10. Arexx

ARexx is an interpreted programming language provided with AmigaOS 2 or later. It is also an Inter-Process Communication tool that allows ARexx scripts to communicate
with programs which has a Arexx Port included. To communicate with ARexx a program much use Message Ports (see Windows) to receive arexx commands sent to them
and deal with them. A good implementation of ARexx is the Minrexx development tools from Aminet which I shall use here.

In your C program you need to include a list of commands your ARexx interface will support. For example, this is the list of commands from freedraw.c. The first value is
the arexx command and the second value is the address of the function to call in your program (all should be lower case).

struct rexxCommandList rcl[] = {
   { "color", &rexxcolor },
   { "box", &rexxbox },
   { "fbox", &rexxfbox },
   { "line", &rexxline },
   { "tofront", &rexxtofront },
   { "toback", &rexxtoback },
   { "exit", &rexxexit },
   { "version", &rexxversion },
   { "spawn", &rexxspawn },
   { NULL, NULL } 

In your program, you need to open a window and then wait for message events to appear and deal with them as you normally do but you need to check for Arexx messages
as well.

#include <minrexx.h>
/* Get command line parameters. Argc = number of arguments, Argv = Array of string parameters */
int main(int argc, char *argv[]) { struct Library *OpenLibrary() ; struct Window *OpenWindow() ; struct Message *GetMsg() ; struct IntuiMessage *NewMessage; .......... long rexxbit ; char firstcommand[256] ; ......... /* Open a Rexx port called 'freedraw' and send a command to it, if any. Rcl is the command list     "fd" is the file extension for macros, and disp is a user dispatch program address. */ rexxbit = upRexxPort("freedraw", rcl, "fd", &disp) ; firstcommand[0] = 0 ; /* Read arguments and concatenate them to first command string */ for (x=1; x<argc; x++) {    strcat(firstcommand, argv[x]) ;    strcat(firstcommand, " ") ; } if (firstcommand[0]) {    /* Send out an Arexx message and return immediately */    asyncRexxCmd(firstcommand) ; ..... while(keepGoing) { /* Wait for a message signal and also for rexx bits as well */ Wait( (1L << Window->UserPort->mp_SigBit) | rexxbit); /* Process ARexx messages */ dispRexxPort() ; ...... } return(0); }

The dispRexxPort function is the main function that deals with ARexx messages. This will check for messages
returned in the RexxMsg structure, which is retreived with the GetMsg() function. It uses the rm_Args[] values
to call the relevant function needed which is defined in the list earlier.

For example, here's the function for drawing a line using a ARexx command 'Line'.

void rexxline(msg, p)
   struct RexxMsg *msg ;
   char *p ;
     parseargs(p, 4) ;
     clipxy(0) ;
     clipxy(2) ;
     Move(Window->RPort, (long)args[0], (long)args[1]) ;
     Draw(Window->RPort, (long)args[2], (long)args[3]) ;

It requires 4 arguments which is passed via the character string 'p' and split into 4 values in to the array args[] using
the parseargs() function in freedraw.c.

Below is an arexx script called 'sample.fd' which passes two Arexx commands to the 'freedraw' Arexx port called
'Color' and 'Line', where Color has one argument and Line has 4 arguments passed to it. Note that Arexx scripts always
start with a command line between /* and */ markers and the 'address' command states what Arexx port to use.

/* draw something with freedraw */
address 'freedraw'
color = 0
do i = 20 to 400
   'Color ' color
   color = color + 1
   if color > 3 then color = 0
   'Line ' 20 i i 400
   end i


Next Page