mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
4.6 KiB
4.6 KiB
rexxsyslib.library — ARexx Scripting Interface
Overview
ARexx is the Amiga's built-in macro/scripting language (based on IBM's REXX). Any application can host an ARexx port to receive commands from scripts and other applications — this is the Amiga's primary inter-application communication mechanism for user-facing scripting.
flowchart LR
SCRIPT["ARexx Script<br/>(text file)"] -->|"Sends command<br/>to named port"| PORT["Application<br/>ARexx Port<br/>(e.g., 'MYAPP')"]
PORT -->|"Parses command<br/>returns result"| SCRIPT
APP2["Other Application"] -->|"FindPort + PutMsg"| PORT
style PORT fill:#e8f4fd,stroke:#2196f3,color:#333
Adding an ARexx Port to Your Application
#include <rexx/storage.h>
#include <rexx/rxslib.h>
struct MsgPort *arexxPort = CreateMsgPort();
arexxPort->mp_Node.ln_Name = "MYAPP"; /* public port name */
arexxPort->mp_Node.ln_Pri = 0;
AddPort(arexxPort); /* make it publicly findable */
/* In your main event loop, combine with IDCMP: */
ULONG arexxSig = 1 << arexxPort->mp_SigBit;
ULONG idcmpSig = 1 << window->UserPort->mp_SigBit;
ULONG sigs = Wait(arexxSig | idcmpSig);
if (sigs & arexxSig)
{
struct RexxMsg *rmsg;
while ((rmsg = (struct RexxMsg *)GetMsg(arexxPort)))
{
STRPTR cmd = ARG0(rmsg); /* the command string */
/* Parse and execute: */
if (stricmp(cmd, "QUIT") == 0)
{
rmsg->rm_Result1 = 0; /* RC = 0 (success) */
rmsg->rm_Result2 = 0;
running = FALSE;
}
else if (strnicmp(cmd, "OPEN ", 5) == 0)
{
char *filename = cmd + 5;
LONG rc = OpenFile(filename);
rmsg->rm_Result1 = rc ? 0 : 10; /* 0=ok, 10=error */
rmsg->rm_Result2 = 0;
}
else if (stricmp(cmd, "VERSION") == 0)
{
rmsg->rm_Result1 = 0;
/* Return a string result: */
if (rmsg->rm_Action & RXFF_RESULT)
rmsg->rm_Result2 = (LONG)CreateArgstring("1.0", 3);
}
else
{
rmsg->rm_Result1 = 5; /* RC_WARN — unknown command */
rmsg->rm_Result2 = 0;
}
ReplyMsg((struct Message *)rmsg);
}
}
/* Cleanup: */
RemPort(arexxPort);
/* Drain remaining messages: */
struct RexxMsg *rmsg;
while ((rmsg = (struct RexxMsg *)GetMsg(arexxPort)))
{
rmsg->rm_Result1 = 20; /* RC_FATAL */
ReplyMsg((struct Message *)rmsg);
}
DeleteMsgPort(arexxPort);
Sending ARexx Commands
struct Library *RexxSysBase = OpenLibrary("rexxsyslib.library", 0);
struct MsgPort *replyPort = CreateMsgPort();
struct RexxMsg *rmsg = CreateRexxMsg(replyPort, NULL, "MYAPP");
rmsg->rm_Args[0] = (STRPTR)CreateArgstring("OPEN test.txt", 13);
rmsg->rm_Action = RXCOMM | RXFF_RESULT;
/* Find the target application's port: */
Forbid();
struct MsgPort *target = FindPort("TARGETAPP");
if (target)
{
PutMsg(target, &rmsg->rm_Node);
Permit();
WaitPort(replyPort);
GetMsg(replyPort);
Printf("Return code: %ld\n", rmsg->rm_Result1);
if (rmsg->rm_Result1 == 0 && rmsg->rm_Result2)
{
Printf("Result: %s\n", (char *)rmsg->rm_Result2);
DeleteArgstring((STRPTR)rmsg->rm_Result2);
}
}
else
{
Permit();
Printf("Target port not found\n");
}
DeleteArgstring(rmsg->rm_Args[0]);
DeleteRexxMsg(rmsg);
DeleteMsgPort(replyPort);
ARexx Script Example
/* MyScript.rexx — control MYAPP from ARexx */
ADDRESS 'MYAPP'
OPEN 'work:data/image.iff'
IF RC > 0 THEN DO
SAY 'Failed to open file, RC=' RC
EXIT 10
END
VERSION
SAY 'App version:' RESULT
QUIT
Return Codes
| Value | Constant | Meaning |
|---|---|---|
| 0 | RC_OK |
Success |
| 5 | RC_WARN |
Warning (command not understood, etc.) |
| 10 | RC_ERROR |
Error (command failed) |
| 20 | RC_FATAL |
Fatal error (port shutting down) |
Common ARexx-Aware Applications
| Application | Port Name | Example Commands |
|---|---|---|
| Workbench | WORKBENCH |
OPEN, CLOSE, WINDOW |
| MultiView | MULTIVIEW.n |
OPEN, PRINT, QUIT |
| IBrowse | IBROWSE |
GOTOURL, RELOAD |
| CygnusEd | rexx_ced |
OPEN, SAVE, MARK, CUT |
| TextPad | TEXTPAD |
LOAD, SAVE, FIND |
References
- NDK39:
rexx/storage.h,rexx/rxslib.h - ADCD 2.1: rexxsyslib.library autodocs
- arexx_integration.md — Complete ARexx integration guide: dispatch tables, antipatterns, use-case cookbook
- See also: process_management.md — process/task message ports