home *** CD-ROM | disk | FTP | other *** search
- /* amiga_minrexx.c -- ARexx interface
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /*
- * Originally by Radical Eye Software, modified by me.
- */
-
- static char *blurb = "Radical Eye MinRexx 0.4.jsh";
-
- #include "jade.h"
- #include "jade_protos.h"
-
- #include <clib/exec_protos.h>
- #ifdef _DCC
- # define RexxSysBase_DECLARED
- #endif
- #include <clib/rexxsyslib_protos.h>
- #include <string.h>
-
- _PR void rexx_init(void);
- _PR void rexx_kill(void);
-
- _PR VALUE do_sync_rexx(u_char *, bool);
- _PR void disp_rexx_port(void);
- static struct RexxMsg *send_rexx_cmd(u_char *, int(*)(), u_char *, u_char *, u_char *, long);
- _PR struct RexxMsg *sync_rexx_cmd(u_char *, bool, struct RexxMsg *);
- _PR struct RexxMsg *async_rexx_cmd(u_char *);
- _PR struct RexxMsg *async_rexx_string(u_char *);
- _PR void reply_rexx_cmd(struct RexxMsg *, long, long, u_char *);
- static void close_rexx_lib(void);
- static bool open_rexx_lib(void);
- static void reply_to_it(struct RexxMsg *);
-
- _PR u_long RexxSig;
- u_long RexxSig;
-
- static struct MsgPort *RexxPort;
- static bool BringerDown;
- static long StillNeedReplies;
- static struct RexxMsg *oRexxMsg;
- static VALUE RexxName;
-
- struct RxsLib *RexxSysBase;
-
- #define RX_EXTEN "jade"
-
- #define MAXRXOUTSTANDING (300)
- #define RXERRORIMGONE (100)
- #define RXERRORNOCMD (30)
-
- _PR VALUE cmd_rexx_async_macro(VALUE name);
- DEFUN("rexx-async-macro", cmd_rexx_async_macro, subr_rexx_async_macro, (VALUE name), V_Subr1, DOC_rexx_async_macro) /*
- ::doc:rexx_async_macro::
- (rexx-async-macro NAME) <AMIGA-ONLY>
- Asynchronously invokes the ARexx macro called NAME.
- ::end:: */
- {
- DECLARE1(name, STRINGP);
- if(async_rexx_cmd(VSTR(name)))
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_rexx_async_str(VALUE str);
- DEFUN("rexx-async-str", cmd_rexx_async_str, subr_rexx_async_str, (VALUE str), V_Subr1, DOC_rexx_async_str) /*
- ::doc:rexx_async_str::
- (rexx-async-str STRING) <AMIGA-ONLY>
- Gets ARexx to asynchronously interpret the string of REXX code STRING.
- ::end:: */
- {
- DECLARE1(str, STRINGP);
- if(async_rexx_string(VSTR(str)))
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_rexx_sync_macro(VALUE name);
- DEFUN("rexx-sync-macro", cmd_rexx_sync_macro, subr_rexx_sync_macro, (VALUE name), V_Subr1, DOC_rexx_sync_macro) /*
- ::doc:rexx_sync_macro::
- (rexx-sync-macro NAME) <AMIGA-ONLY>
- Invokes the ARexx macro NAME synchronously, returning its value when it
- exits (this will either be a number or a string.
- ::end:: */
- {
- DECLARE1(name, STRINGP);
- return(do_sync_rexx(VSTR(name), TRUE));
- }
-
- _PR VALUE cmd_rexx_sync_str(VALUE str);
- DEFUN("rexx-sync-str", cmd_rexx_sync_str, subr_rexx_sync_str, (VALUE str), V_Subr1, DOC_rexx_sync_str) /*
- ::doc:rexx_sync_str::
- (rexx-sync-str STRING) <AMIGA-ONLY>
- Synchronously executes the string of ARexx commands STRING, returning their
- exit value.
- ::end:: */
- {
- DECLARE1(str, STRINGP);
- return(do_sync_rexx(VSTR(str), FALSE));
- }
-
- _PR VALUE var_rexx_port_name(VALUE val);
- DEFUN("rexx-port-name", var_rexx_port_name, subr_rexx_port_name, (VALUE val), V_Var, DOC_rexx_port_name) /*
- ::doc:rexx_port_name::
- Variable holding the name of our ARexx port. (Amiga only).
- ::end:: */
- {
- if(val)
- return(NULL);
- return(RexxName ? RexxName : sym_nil);
- }
-
- void
- rexx_init(void)
- {
- int i;
- static UBYTE name[32];
- name[0] = V_StaticString;
- Forbid();
- for(i = 1;; i++)
- {
- sprintf(VSTR(name), "JADE.%d", i);
- if(!FindPort(VSTR(name)))
- {
- RexxPort = CreateMsgPort();
- if(RexxPort)
- {
- RexxPort->mp_Node.ln_Name = VSTR(name);
- RexxPort->mp_Node.ln_Pri = 1;
- AddPort(RexxPort);
- RexxSig = 1 << RexxPort->mp_SigBit;
- RexxName = name;
- }
- }
- break;
- }
- Permit();
- ADD_SUBR(subr_rexx_async_macro);
- ADD_SUBR(subr_rexx_async_str);
- ADD_SUBR(subr_rexx_sync_macro);
- ADD_SUBR(subr_rexx_sync_str);
- ADD_SUBR(subr_rexx_port_name);
- }
-
- void
- rexx_kill(void)
- {
- if(RexxPort)
- {
- RemPort(RexxPort);
- BringerDown = TRUE;
- if(oRexxMsg)
- {
- oRexxMsg->rm_Result1 = RXERRORIMGONE;
- ReplyMsg((struct Message *)oRexxMsg);
- oRexxMsg = NULL;
- }
- while(StillNeedReplies)
- {
- WaitPort(RexxPort);
- disp_rexx_port();
- }
- close_rexx_lib();
- DeleteMsgPort(RexxPort);
- RexxPort = NULL;
- }
- RexxSig = 0;
- }
-
- /*
- * This function [hopefully] performs a synchronous REXX call, from
- * which we get the result :)
- */
- VALUE
- do_sync_rexx(u_char *arg, bool isMac)
- {
- VALUE result = sym_nil;
- if(RexxPort && open_rexx_lib())
- {
- struct MsgPort *rp;
- if(rp = CreateMsgPort())
- {
- struct RexxMsg *rm;
- if(rm = CreateRexxMsg(rp, RX_EXTEN, RexxPort->mp_Node.ln_Name))
- {
- rm->rm_Action |= RXFF_RESULT;
- if(send_rexx_cmd(arg, reply_to_it, (char *)rm, NULL, NULL, (isMac ? 0 : RXFF_STRING) | RXFF_RESULT))
- {
- u_long rpsigmask = 1 << rp->mp_SigBit;
- u_long sigs;
-
- do {
- sigs = Wait(rpsigmask | RexxSig);
- disp_rexx_port();
- } while(!(sigs & rpsigmask));
-
- if(GetMsg(rp))
- {
- if(!rm->rm_Result1 && rm->rm_Result2)
- {
- result = valstrdup((u_char *)rm->rm_Result2);
- if(open_rexx_lib())
- DeleteArgstring((u_char *)rm->rm_Result2);
- }
- else
- result = newnumber(rm->rm_Result1);
- }
- }
- if(open_rexx_lib())
- DeleteRexxMsg(rm);
- }
- DeleteMsgPort(rp);
- }
- close_rexx_lib();
- }
- return(result);
- }
-
- static void
- close_rexx_lib(void)
- {
- if((!StillNeedReplies) && RexxSysBase)
- {
- CloseLibrary((struct Library *)RexxSysBase);
- RexxSysBase = NULL;
- }
- }
-
- void
- disp_rexx_port(void)
- {
- struct RexxMsg *rexxmsg;
- u_char *cmd;
-
- if(!RexxPort)
- return;
-
- while(rexxmsg = (struct RexxMsg *)GetMsg(RexxPort))
- {
- if(rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
- {
- if (rexxmsg->rm_Args[1])
- {
- ((int (*)(struct RexxMsg *))(rexxmsg->rm_Args[1]))(rexxmsg);
- }
- DeleteArgstring(rexxmsg->rm_Args[0]);
- DeleteRexxMsg(rexxmsg);
- StillNeedReplies--;
- close_rexx_lib();
- }
- else
- {
- cmd = (u_char *)rexxmsg->rm_Args[0];
- while (*cmd > 0 && *cmd <= ' ')
- cmd++;
- rexxmsg->rm_Result1 = 0;
- rexxmsg->rm_Result2 = 0;
-
- if(BringerDown)
- rexxmsg->rm_Result1 = RXERRORIMGONE;
- else
- {
- VALUE res;
- oRexxMsg = rexxmsg ;
- cursor(CurrVW, CURS_OFF);
- res = evalstring(cmd, FALSE);
- if(res)
- {
- if(STRINGP(res))
- reply_rexx_cmd(rexxmsg, 0, 0, VSTR(res));
- else if(NUMBERP(res))
- {
- u_char buf[32];
- sprintf(buf, "%d", VNUM(res));
- reply_rexx_cmd(rexxmsg, 0, 0, buf);
- }
- else if(res == sym_nil)
- reply_rexx_cmd(rexxmsg, 5, 0, NULL);
- else
- reply_rexx_cmd(rexxmsg, 0, 0, NULL);
- }
- else
- rexxmsg->rm_Result1 = RXERRORNOCMD;
- cursor(CurrVW, CURS_ON);
- }
- oRexxMsg = NULL ;
- ReplyMsg((struct Message *)rexxmsg);
- }
- }
- refreshworldcurs();
- }
-
- static bool
- open_rexx_lib(void)
- {
- if(RexxSysBase || (RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L)))
- return(TRUE);
- return(FALSE);
- }
-
- static struct RexxMsg *
- send_rexx_cmd(u_char *s, int(*f)(), u_char *p1, u_char *p2, u_char *p3, long m)
- {
- struct MsgPort *rexxport;
- struct RexxMsg *rexxmsg;
-
- if((!RexxPort) || (StillNeedReplies > MAXRXOUTSTANDING-1))
- return(FALSE);
- rexxmsg = NULL;
- if(open_rexx_lib()
- && (rexxmsg = CreateRexxMsg(RexxPort, RX_EXTEN, RexxPort->mp_Node.ln_Name))
- && (rexxmsg->rm_Args[0] = CreateArgstring(s, (long)strlen(s))))
- {
- rexxmsg->rm_Action = RXCOMM | m;
- rexxmsg->rm_Args[1] = (u_char *)f;
- rexxmsg->rm_Args[2] = p1;
- rexxmsg->rm_Args[3] = p2;
- rexxmsg->rm_Args[4] = p3;
- rexxmsg->rm_Node.mn_Node.ln_Name = RXSDIR;
- Forbid();
- if(rexxport = FindPort(RXSDIR))
- PutMsg(rexxport, (struct Message *)rexxmsg);
- Permit();
- if(rexxport)
- {
- StillNeedReplies++;
- return(rexxmsg);
- }
- else
- DeleteArgstring(rexxmsg->rm_Args[0]);
- }
- if(rexxmsg)
- DeleteRexxMsg(rexxmsg);
- close_rexx_lib();
- return(FALSE);
- }
-
- struct RexxMsg *
- async_rexx_cmd(u_char *s)
- {
- return(send_rexx_cmd(s, NULL, NULL, NULL, NULL, 0));
- }
-
- struct RexxMsg *
- async_rexx_string(u_char *s)
- {
- return(send_rexx_cmd(s, NULL, NULL, NULL, NULL, RXFF_STRING));
- }
-
- static void
- reply_to_it(struct RexxMsg *msg)
- {
- struct RexxMsg *omsg = (struct RexxMsg *)(msg->rm_Args[2]);
- reply_rexx_cmd(omsg, msg->rm_Result1, msg->rm_Result2,
- (u_char *)msg->rm_Result2);
- ReplyMsg((struct Message *)omsg);
- }
-
- struct RexxMsg *
- sync_rexx_cmd(u_char *s, bool isMac, struct RexxMsg *msg)
- {
- return(send_rexx_cmd(s, reply_to_it, (u_char *)msg, NULL, NULL,
- isMac ? 0 : RXFF_STRING));
- }
-
- void
- reply_rexx_cmd(struct RexxMsg *msg, long primary, long secondary,
- u_char *string)
- {
- if(!primary && (msg->rm_Action & (1L << RXFB_RESULT)))
- {
- if(string && open_rexx_lib())
- secondary = (long)CreateArgstring(string, (long)strlen(string));
- else
- secondary = 0L;
- }
- msg->rm_Result1 = primary;
- msg->rm_Result2 = secondary;
- close_rexx_lib();
- }
-