Amiga SimpleRexx Toolkitby Michael Sinz (MKSoft Development)Copyright 1985-1999 - All Rights Reserved Here is the raw AmigaMail article and documentation I wrote for SimpleRexx.  This is included in the SimpleRexx archive. |
SimpleRexxA Simplified Interface into the world of ARexxARexx, ARexx, ARexx.  2.0 has ARexx.  So, why and how do I support ARexx? The "Why?" has been answered elsewhere and that is not what this article is about.  Let it suffice that you should support ARexx within your application.  It is a standard that Commodore is pushing and we hope that all new applications will have ARexx support. As to the "How?", that is what this article is about.  We understand that your existing software may not currently support ARexx and that some of you may never even have looked at what is needed to support ARexx.  New applications can be designed with ARexx support in mind and, with the advent of the AppShell by David Junod, the work involved to support ARexx is nothing more than what is needed to support the features within you application.  However, existing code may not move into the AppShell easily and you may wish to do a minor upgrade to your application to support ARexx. SimpleRexx is a set of routines that handle the low-level ARexx work for you in such a way as to have your application work with or without ARexx on the target system.  The goal of SimpleRexx is to make adding at least the minimum level of ARexx support to an application a trivial task. Working with ARexxREXX is, at its heart, a string processing language.  Most everything that happens in REXX is in the form of a string; even numbers are passed as ASCII representations in most situations. The Amiga implementation of REXX, known as ARexx, and is part of Release 2.0 of AmigaDOS.  ARexx has a very complete implementation of the REXX language plus the ability to send and receive control messages from "outside" sources.  ARexx then can operate on them in synchronous fashion.  The messages contain text strings that are then interpreted by ARexx as REXX commands or by the "outside" source (the Application) as its commands. An application that "supports ARexx" is one that can receive and send ARexx messages.  The messages are, like the REXX language, string based and contain the command string of the operation wanted. To make this even more interesting, there are ways to send and receive data from ARexx.  The data can come in the message itself or via the ARexx RVI (Rexx Variable Interface).  In either case data can be transferred to and from ARexx.  A complete ARexx supporting application would need to be able to send data to a requesting ARexx program/script and get data from that program. The following code shows how to use the ARexx support library to send and receive ARexx messages.  It also is a "wrapper" around these functions to provide a simplified interface to ARexx to help promote and simplify the idea of adding ARexx support to your existing applications. SimpleRexxExample.c is a very simple example of the use of the calls in SimpleRexx.  The test.rexx script is an example script to try running while SimpleRexxExample is running.  It will send commands to SimpleRexxExample in order to control it. test.results is the output of test.rexx. Overview of FunctionsThe source to SimpleRexx is a single file.  It is SimpleRexx.c. The header file to that contains the type definitions and prototypes for the functions is in the file SimpleRexx.h. Functions that are "available" via SimpleRexx are used as follows:
|
/* * This is an example of how to use the SimpleRexx code. */ #include <exec/types.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <intuition/intuition.h> #include <proto/exec.h> #include <proto/intuition.h> #include <rexx/storage.h> #include <rexx/rxslib.h> #include <stdio.h> #include <string.h> #include "SimpleRexx.h" /* * Lattice control-c stop... */ int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */ int chkabort(void) { return(0); } /* really */ /* * The strings in this program */ char *strings[]= { "50: Window already open", /* STR_ID_WINDOW_OPEN */ "101: Window did not open", /* STR_ID_WINDOW_ERROR */ "50: No Window", /* STR_ID_WINDOW_NONE */ "80: Argument error to WINDOW command", /* STR_ID_WINDOW_ARG */ "100: Unknown command", /* STR_ID_COMMAND_ERROR */ "ARexx port name: %s\n", /* STR_ID_PORT_NAME */ "No ARexx on this system.\n", /* STR_ID_NO_AREXX */ "SimpleRexxExample Window" /* STR_ID_WINDOW_TITLE */ }; #define STR_ID_WINDOW_OPEN 0 #define STR_ID_WINDOW_ERROR 1 #define STR_ID_WINDOW_NONE 2 #define STR_ID_WINDOW_ARG 3 #define STR_ID_COMMAND_ERROR 4 #define STR_ID_PORT_NAME 5 #define STR_ID_NO_AREXX 6 #define STR_ID_WINDOW_TITLE 7 /* * NewWindow structure... */ static struct NewWindow nw= { 97,47,299,44,-1,-1, CLOSEWINDOW, WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SIMPLE_REFRESH|NOCAREREFRESH, NULL,NULL, NULL, NULL,NULL,290,40,-1,-1,WBENCHSCREEN }; /* * A *VERY* simple and simple-minded example of using the SimpleRexx.c code. * * This program, when run, will print out the name of the ARexx port it * opens. Use that port to tell it to SHOW the window. You can also * use the ARexx port to HIDE the window, to READTITLE the window's * titlebar, and QUIT the program. You can also quit the program by * pressing the close gadget in the window while the window is up. * * Note: You will want to RUN this program or have another shell available such * that you can still have access to ARexx... */ void main(int argc,char *argv[]) { short loopflag=TRUE; AREXXCONTEXT RexxStuff; struct Window *win=NULL; ULONG signals; if (IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",NULL)) { /* * Note that SimpleRexx is set up such that you do not * need to check for an error to initialize your REXX port * This is so your application could run without REXX... */ RexxStuff=InitARexx("Example","test"); if (argc) { if (RexxStuff) printf(strings[STR_ID_PORT_NAME], ARexxName(RexxStuff)); else printf(strings[STR_ID_NO_AREXX]); } while (loopflag) { signals=ARexxSignal(RexxStuff); if (win) signals|=(1L << (win->UserPort->mp_SigBit)); if (signals) { struct RexxMsg *rmsg; struct IntuiMessage *msg; signals=Wait(signals); /* * Process the ARexx messages... */ while (rmsg=GetARexxMsg(RexxStuff)) { char cBuf[24]; char *nextchar; char *error=NULL; char *result=NULL; long errlevel=0; nextchar=stptok(ARG0(rmsg), cBuf,24," ,"); if (*nextchar) nextchar++; if (!stricmp("WINDOW",cBuf)) { if (!stricmp("OPEN",nextchar)) { if (win) { error=strings[STR_ID_WINDOW_OPEN]; errlevel=5; } else { nw.Title=strings[STR_ID_WINDOW_TITLE]; if (!(win=OpenWindow(&nw))) { error=strings[STR_ID_WINDOW_ERROR]; errlevel=30; } } } else if (!stricmp("CLOSE",nextchar)) { if (win) { CloseWindow(win); win=NULL; } else { error=strings[STR_ID_WINDOW_NONE]; errlevel=5; } } else { error=strings[STR_ID_WINDOW_ARG]; errlevel=20; } } else if (!stricmp("READTITLE",cBuf)) { if (win) { result=win->Title; } else { error=strings[STR_ID_WINDOW_NONE]; errlevel=5; } } else if (!stricmp("QUIT",cBuf)) { loopflag=FALSE; } else { error=strings[STR_ID_COMMAND_ERROR]; errlevel=20; } if (error) { SetARexxLastError(RexxStuff,rmsg,error); } ReplyARexxMsg(RexxStuff,rmsg,result,errlevel); } /* * If we have a window, process those messages */ if (win) while (msg=(struct IntuiMessage *) GetMsg(win->UserPort)) { if (msg->Class==CLOSEWINDOW) { /* * Quit if the close gadget... */ loopflag=FALSE; } ReplyMsg((struct Message *)msg); } } else loopflag=FALSE; } if (win) CloseWindow(win); FreeARexx(RexxStuff); CloseLibrary((struct Library *)IntuitionBase); } } |