home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
useful
/
util
/
edit
/
mg
/
src.lzh
/
amiga
/
rexx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-23
|
21KB
|
918 lines
/*
* This file sends out and recieves REXX commands (well recieving them means
* we hand the off to excline, but...)
*/
#include "rexx.h"
#ifdef REXX
#include <exec/types.h>
#include <exec/ports.h>
#include <rexx/storage.h>
#include <rexx/rxslib.h>
#ifdef LATTICE
#include <proto/exec.h>
#include <proto/intuition.h>
#else
#include <functions.h>
#endif
#undef TRUE
#undef FALSE
#include "def.h"
#include "line.h"
#include "buffer.h"
#include "window.h"
#include "macro.h"
#include "region.h"
#ifdef ANSI
#undef EOF /* Strange..., but stdio complains about it */
#include <stdio.h> /* Only if we've got sprintf in here */
#include <stdlib.h>
#include <fcntl.h>
#undef HUGE /* Collides with math.h */
#include <math.h>
#include <string.h>
#endif
/*
* The pointer to the Rexx library, which we really want when dealing with
* Rexx, and some return value for messages.
*/
struct Library *RexxSysBase;
#define FAIL_LOCKED 3
#define FAIL_NOREXX 4
/*
* My static functions.
*/
static int rexxdocommand PROTO((char *, long));
static int getrexxargs PROTO((struct RexxMsg *, int));
static int rexxread PROTO((int));
static int rexxstemint PROTO((char *, int, int));
static int rexxstemstring PROTO((char *, int, char *, int));
static int findline PROTO((struct line *));
static struct MsgPort *lockport PROTO((char *));
static int spinport PROTO((struct MsgPort *));
#ifdef LATTICE
long __stdargs SetRexxVar PROTO((struct RexxMsg *, char *, char *, long)) ;
#else
long SetRexxVar PROTO((struct RexxMsg *, char *, char *, long)) ;
static char *strupr PROTO((char *));
#endif
struct RexxArg *CreateArgstring PROTO((char *, long)) ;
long LengthArgstring PROTO((struct RexxArg *)) ;
void DeleteArgstring PROTO((struct RexxArg *)) ;
struct RexxMsg *CreateRexxMsg PROTO((struct MsgPort *, char *, char *)) ;
void ClearRexxMsg PROTO((struct RexxMsg *, long)) ;
void DeleteRexxMsg PROTO((struct RexxMsg *)) ;
/*
* Pointer to rexx macro to run on exit.
*/
static char *RexxExitCmd;
/*
* Commands that return results can only do so if the RexxMsg that caused
* them to be executed is willing to take results. To make this test easy,
* the RexxMsg is stored in CurrentMsg between it's being recieved and
* sending out the reply. Any other time, it will be NULL, and the Rexx
* command check for that if they shouldn't be executed unless there is a
* RexxMsg active. In addition, rexxlock needs to reply to this message
* indicating that the lock succeeded before going into locked mode, so it
* needs access to CurrentMsg. Result strings get passed from rexx commands
* back to the script - and the other way, in the case of rexxdoregion - via
* RexxResult. It's normally NULL, unless the executed command set a result,
* or a macro that we were still locked to on exit returned a result. In
* which case, it points to the RexxArgstring for the result. The consumer is
* responsible for deleting it, and the producer is responsible for creating
* it.
*
*/
static struct RexxMsg *CurrentMsg = NULL;
static struct RexxArg *RexxResult = NULL;
/*
* Things for dealing with asynch REXX messages. rexxport is the port that
* those messages come in on, and it's name is mgname. Since rexxport must be
* checked for messages in the event loop, it's not static. RepliesNeeded is
* the number of reply messages we need to see on rexxport. Lockadd is the
* address of the port name that a given macro is locked to, or NULL if we're
* not locked. ADDSIZE is the size of the port name we use for dynamically
* allocated ports
*/
struct MsgPort *rexxport = NULL;
static char mgname[5] = "mg\0\0";
static unsigned RepliesNeeded = 0;
static char *lockadd = NULL;
#define ADDSIZE 8
/*
* This routine dispatches any REXX messages coming in. However, to allow for
* REXX commands that start other REXX commands, we must save and restore the
* environment (CurrentMsg).
*/
int
disprexx(inport)
struct MsgPort *inport;
{
register int s, t;
register struct RexxMsg *savemsg;
savemsg = CurrentMsg;
for (;;) {
RexxResult = NULL;
/* Check for commands */
if (inport && (CurrentMsg = (struct RexxMsg *) GetMsg(inport))) {
if (CurrentMsg->rm_Node.mn_Node.ln_Type != NT_REPLYMSG)
s = excline(ARG0(CurrentMsg),
LengthArgstring((struct RexxArg *) ARG0(CurrentMsg)));
}
/* And then for replies or asynch commands */
else if (CurrentMsg = (struct RexxMsg *) GetMsg(rexxport)) {
if (CurrentMsg->rm_Node.mn_Node.ln_Type != NT_REPLYMSG)
if (!inport)
s = FAIL_NOREXX;
else if (lockadd)
s = FAIL_LOCKED;
else
s = excline(ARG0(CurrentMsg),
LengthArgstring((struct RexxArg *) ARG0(CurrentMsg)));
}
if (CurrentMsg == NULL)
break;
if (CurrentMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
RepliesNeeded -= 1;
s = CurrentMsg->rm_Result1 < 2
? 1 - CurrentMsg->rm_Result1
: ABORT;
t = ((char *)CurrentMsg->rm_CommAddr == lockadd);
if (s == TRUE && (CurrentMsg->rm_Action & RXFF_RESULT)
&& CurrentMsg->rm_Result2 != NULL)
/* Aha - a result. Deal with it. */
if (t)
RexxResult = (struct RexxArg *) CurrentMsg->rm_Result2;
else
DeleteArgstring((struct RexxArg *)
CurrentMsg->rm_Result2);
/* Free the memory for this message */
FreeMem(CurrentMsg->rm_CommAddr, ADDSIZE);
ClearRexxMsg(CurrentMsg, 16);
DeleteRexxMsg(CurrentMsg);
if (!t)
continue;
CurrentMsg = savemsg;
lockadd = NULL;
return s;
}
if (s < 2)
s = 1 - s;
CurrentMsg->rm_Result1 = s;
CurrentMsg->rm_Result2 = (RexxResult != NULL)
? (LONG) RexxResult
: 0L;
ReplyMsg((struct Message *) CurrentMsg);
}
CurrentMsg = savemsg;
return -1;
}
void
openrexx()
{
register short i, j;
if ((RexxSysBase = OpenLibrary(RXSNAME, 0)) == NULL)
return;
srand((unsigned) &lockadd); /* Just to make things change */
for (i = 33; i < 127; i++) {
for (j = 33; j < 127; j++) {
Forbid();
if (FindPort(mgname) == NULL)
rexxport = CreatePort(mgname, 0L);
Permit();
if (rexxport != NULL)
return;
mgname[2] = j;
}
mgname[3] = i;
}
/* No port opened, so we don't do Rexx, so we close RexxSysBase */
CloseLibrary(RexxSysBase);
RexxSysBase = NULL;
}
void
closerexx()
{
if (!RexxSysBase)
return; /* No Rexx to close */
if (RexxExitCmd != NULL)
rexxdocommand(RexxExitCmd, RXCOMM);
if (rexxport) {
while (RepliesNeeded) {
WaitPort(rexxport);
disprexx(NULL);
}
DeletePort(rexxport);
}
CloseLibrary(RexxSysBase);
}
/*
* Commands that make Rexx macros execute.
*/
rexxexitcommand(f, n)
{
int s;
static char exitcom[NLINE];
if (!RexxSysBase)
return FALSE;
if ((s = ereply("REXX command to run on exit: ", exitcom, NLINE)) != TRUE)
return s;
RexxExitCmd = exitcom;
return TRUE;
}
rexxcommand(f, n)
{
int s;
char cmd[NLINE];
if (!RexxSysBase)
return FALSE;
if ((s = ereply("REXX command: ", cmd, NLINE)) != TRUE)
return s;
return rexxdocommand(cmd, f & FFUNIV ? RXCOMM | RXFF_TOKEN : RXCOMM);
}
rexxcomregion(f, n)
int f, n;
{
char *out;
register RSIZE length, size;
register struct line *lp;
int status, insertres;
char *string;
struct region reg;
if (!RexxSysBase)
return FALSE;
if ((length = getregion(®)) != TRUE)
return length;
size = reg.r_size;
if ((out = malloc(size + 1)) == NULL) {
ewprintf("Can't get %d bytes", size + 1);
return FALSE;
}
string = out; /* Save the start of the thing... */
/* Copy the region to out */
lp = reg.r_linep;
length = llength(lp) - reg.r_offset;
bcopy(<ext(lp)[reg.r_offset], out, length);
size -= length;
out += length;
while (size > 0) {
/* Add a newline to the output string */
*out++ = '\n';
size -= 1;
/* Add part/all of the current line to the output string */
lp = lforw(lp);
length = llength(lp);
if (length > size)
length = size;
bcopy(ltext(lp), out, length);
out += length;
size -= length;
}
*out = '\0';
/* Figure out how many arguments we really have */
insertres = (n <= 0);
if ((f & FFARG) == 0)
n = 0;
else if (insertres)
n = -n;
if (n > MAXRMARG) {
ewprintf("Can only have