[comp.sys.amiga] IPC ... an ARexx example

kim@amdahl.uts.amdahl.com (Kim DeVaughn) (03/07/88)

[ For all you do ... this line's for you ... ]

With all the current discussion about IPC methodology, ARexx, and such, this
seems like a good time to post the attached example of a simple form of an
ARexx interface.  It is being posted here, rather than in comp.sources.amiga,
as it is short, and is primarily example code.

In the attached shar file, you'll find a small standalone program called
"rex" that I used to familiarize myself with the (COMMAND form of the)
ARexx interface.  You'll also find the actual interface file (rexx.c) that
I used to interface Matt's "dme" editor to ARexx.

Besides the rexx.c file, I only had to add about 20 lines of code to the
dme sources (which Matt has improved upon, I believe).  This interface
added less than 2K to the dme executable.

Not included are the header files that come in the ARexx package ... I don't
have Bill Hawes' permission to redistribute them (yet), nor the C bindings,
but if you have ARexx, you have a copy of them anyway.  Of course you need
ARexx to run the "rex" example (try "rex args" to see what "rex" passes to
ARexx, and watch what ARexx does when it tries to execute the "foo" command).

Now this is a very simple and basic form of interface to ARexx.  More
sophisticated facilities are available.  I just wanted to see what a minimal
interface would look like, with a minimum of changes to dme.

The dme interface works quite well, given that dme was never designed with
such an interface in mind.  There are some limitations because of the way
dme does error and command completion reporting, but the point is that I
was able to interface the two with very little effort.  To fully take
advantage of ARexx's capabilities will require some additional work in dme's
innards, and perhaps the addition of some new dme commands.

When Rob Peck posts his speechtoy with an ARexx interface, I think I'll see
about making a "talking editor" out of dme using speechtoy (which could just
as well be a spelling checker, etc.)  Should be a piece of cake ...


Now I'm not saying that the ARexx interface is perfect for all IPC applications,
but it *is* quite powerful, and can be used pretty simply.  Bill has done a
very professional job of implementing the REXX interpreter, and providing an
interface that is consistant with the Amiga OS.  The supplied .libraries have
many more additional functions than are used in the example files.  These
functions are not specific to ARexx per se, and can be used by any program
that wants to take advantage of them (similar to the way one can take advantage
of the ARP functions in the arp.library).

Other advantages of ARexx are that it is small (rexxsyslib.library is less than
32K, and the resident program "rexxmast" is less than 2K), and fast, having
been implemented in very tight assembly language.  It is well documented, the
manual being 140+ pages.  It uses an established language for it's processing
(REXX is one of the few really good things to make it out of Big Blue ... must
be because it was a research project :-) ).

And it is available NOW ... TODAY ... for less than fifty bucks!


Sorry if I started sounding commercial, but it really *is* a good product.
I hope the development community uses it as a base for a *standardized* IPC
facility.  If there are fundemental deficiencies in ARexx, Bill is a pretty
reasonable guy, and I'm sure he'd be interested in improving the product.

Enough verbage!  Here's the code ...

/kim




# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# args.dme rex.c rex.uue rexx.c rexx.h Makefile

echo x - args.dme
cat > "args.dme" << '//E*O*F args.dme//'
/* test to look at what dme is passing to ARexx .... */

parse source a b c d e f g h i
say a b c d e f g h i
parse arg a1 a2 a3 a4 a5 a6
foo
say a1 a2 a3 a4 a5 a6
exit 0

//E*O*F args.dme//

echo x - rex.c
cat > "rex.c" << '//E*O*F rex.c//'

/*
 *  REX.C
 *
 *      (c) Copyright 1987, 1988 by Kim DeVaughn, All Rights Reserved
 *
 *      This program is freely redistributable for non-commercial purposes.
 *
 *      For commercial use, you may contact the author via USENET at:
 *          kim@amdahl.amdahl.com
 *
 *
 *  Example of ARexx interface code, etc.
 *
 */

#include <stdio.h>
#include "defs.h"
#include "rexx.h"


APTR OpenLibrary();
APTR FindPort();
APTR GetMsg();
APTR CreateRexxMsg();
APTR CreateArgstring();


/*
struct RexxArg *cmdarg;

struct MsgPort  RexxPort;
struct MsgPort *ARexxPort;

struct RexxMsg *cmdptr;
struct RexxMsg *retptr;
*/


struct RxsLib  *RexxSysBase;



/*
 *  issue a command to ARexx ...
 */

do_rexx(cmdstr)
char *cmdstr;
{
    struct RexxArg *cmdarg;

    struct MsgPort  RexxPort;
    struct MsgPort *ARexxPort;

    struct RexxMsg *cmdptr;
    struct RexxMsg *retptr;

    char host[16];
    char hexbuf[12];      /* should only need 9 bytes */

    int ret, testcmd, i;


    ClearMem(&RexxPort, sizeof(struct MsgPort));
    strcpy(host, "DME");
    sprintf(hexbuf, "%08x", &RexxPort);
    strcat(host, hexbuf);
    InitPort(&RexxPort, host);      /* need to error check this */
    AddPort(&RexxPort);
    /* return here if InitPort failed */


    if (cmdarg = (struct RexxArg *)CreateArgstring(cmdstr, strlen(cmdstr))) {
        if (cmdptr = (struct RexxMsg *)CreateRexxMsg(&RexxPort, "dme", host)) {
            ACTION(cmdptr) = RXCOMM;
            ARG0(cmdptr)   = (STRPTR)cmdarg;

            Forbid();
            if (ARexxPort = (struct MsgPort *)FindPort("REXX")) {
                PutMsg(ARexxPort, cmdptr);
                Permit();

                i = 0;
                for (;;) {
                    WaitPort(&RexxPort);
                    retptr = (struct RexxMsg *)GetMsg(&RexxPort);

                    printf("\nMessage = %d   Host = %s\n", i+1, host);
                    if (IsRexxMsg(retptr)) printf("IsRexxMsg() says it be a REXX msg!\n");
                    printf("rm_Args[0] = %s\n", ARG0(retptr));
                    printf("rm_Result1 = %d\nrm_Result2 = %d\n", RESULT1(retptr), RESULT2(retptr));
                    printf("rm_Action  = %08x\n", ACTION(retptr));
                    printf("ln_Name    = %s\n", retptr->rm_Node.mn_Node.ln_Name);

                    if (IsRexxMsg(retptr)) {

                        /* here's where you process the command the ARexx macro issued */
                        testcmd = strcmp(ARG0(retptr), "SECOND");
                        if (testcmd == 0) do_rexx("second");
                        testcmd = strcmp(ARG0(retptr), "CAT");
                        if (testcmd == 0) do_rexx("cat");

                        RESULT1(retptr) = i;
                        RESULT2(retptr) = 0;
                        i++;

                        ReplyMsg(retptr);
                    }
                    if (cmdptr == retptr) break;
                }
                if (ret = RESULT1(retptr)) {
                    if (RESULT2(retptr)) {
                        if (RESULT2(retptr) == 1) {
                            printf("Unknown Command\n");
                        } else {
                            printf("ARexx macro error:  Code = %d   Severity = %d\n", RESULT2(retptr), ret);
                        }
                    } else {
                        printf("User specified macro error.  RC = %d\n", ret);
                    }
                } else {
                    printf("Normal macro termination.\n");
                }
            } else {
                printf("ARexx not available - REXX port not found\n");
                ret = -1;
            }
            DeleteRexxMsg(cmdptr);
        } else {
            printf("CreateRexxMsg() Failed\n");     /* this may be overkill, and not need to be checked */
            ret = -1;
        }
        DeleteArgstring(cmdarg);
    } else {
        printf("CreateArgstring() Failed\n");       /* this may be overkill, and not need to be checked */
        ret = -1;
    }
    RemPort(&RexxPort);
    FreePort(&RexxPort);
    return(ret);
}



/*
 * initializion of our port to talk to ARexx
 */

void
rexxinit()
{
    char hexbuf[12];  /* should only need 9 bytes */

    /* need to add error checking */

/*  ClearMem(&RexxPort, sizeof(struct MsgPort));
    strcpy(host, "DME");
    sprintf(hexbuf, "%08x", &RexxPort);
    strcat(host, hexbuf);
    printf("\n\nhost = %s\n", host);

    InitPort(&RexxPort, host);
    AddPort(&RexxPort);
*/  return();
}



/*
 * cleanup of our ARexx port
 */

void
rexxclose()
{
/*  RemPort(&RexxPort);
    FreePort(&RexxPort);
*/  return();
}



/* ......... test prog ........... */

main (argc, argv)
int   argc;
char *argv[];
{
    if (argc < 2) exit(5);

    if (RexxSysBase = (struct RxsLib *)OpenLibrary("rexxsyslib.library", (ULONG)RXSVERS)) {
        /* rexxinit();  */
        do_rexx(argv[1]);
        /* rexxclose(); */
        CloseLibrary(RexxSysBase);
    }
    exit(0);
}

//E*O*F rex.c//

echo x - rex.uue
cat > "rex.uue" << '//E*O*F rex.uue//'

begin 755 rex
M```#\P`````````#``````````(```82````J0````$```/I```&$D[Z!H9.C
M5?^F2'@`(DAM_]I.N@7H4$](>@*T2&W_ODZZ"EY03TAM_]I(>@*F2&W_LDZZ=
M"Q!/[P`,2&W_LDAM_[Y.N@GB4$](;?^^2&W_VDZZ!0Y03TAM_]I.NA<&6$\O2
M+0`(3KH/V%A/+P`O+0`(3KH%AE!/*T#__&<``B1(;?^^2'H"4TAM_]I.N@2*P
M3^\`#"M`_])G``'J(&W_TB%\`0`````<(&W_TB%M__P`*$ZZ%N)(>@(E3KH6&
MPEA/*T#_UF<``:`O+?_2+RW_UDZZ%PQ03TZZ%OY"K?^F2&W_VDZZ%S)83TAM$
M_]I.NA;$6$\K0/_.2&W_OB`M_Z92@"\`2'H!WDZZ"HY/[P`,+RW_SDZZ!%18K
M3TJ`9PI(>@'?3KH*=%A/(&W_SB\H`"A(>@'Q3KH*8E!/(&W_SB\H`"0@;?_.H
M+R@`($AZ`>A.N@I(3^\`#"!M_\XO*``<2'H!]4ZZ"C103R!M_\XO*``*2'H!N
M]DZZ"B)03R\M_\Y.N@/J6$]*@&=L2'H![R!M_\XO*``H3KH(OE!/*T#_JDJMN
M_ZIF"DAZ`=I.NOY@6$](>@'7(&W_SB\H`"A.N@B84$\K0/^J2JW_JF8*2'H!D
MOTZZ_CI83R!M_\XA;?^F`"`@;?_.0J@`)%*M_Z8O+?_.3KH6"EA/(&W_TK'M3
M_\YG!&``_N`@;?_.*V@`(/^N9TX@;?_.2J@`)&<T(&W_S@RH`````0`D9@Q(=
M>@%G3KH);%A/8!@O+?^N(&W_SB\H`"1(>@%@3KH)5$_O``Q@#B\M_ZY(>@%]E
M3KH)0E!/8`I(>@&73KH)-EA/8!)(>@&F3KH)*EA/*WS______ZXO+?_23KH"H
MIEA/8!)(>@&S3KH)#%A/*WS______ZXO+?_\3KH"@EA/8!)(>@&M3KH([EA/:
M*WS______ZY(;?_:3KH5,EA/2&W_VDZZ`HY83R`M_ZY.74YU1$U%`"4P.'@`D
M9&UE`%)%6%@`"DUE<W-A9V4@/2`E9"`@($AO<W0@/2`E<PH`27-297AX37-GY
M*"D@<V%Y<R!I="!B92!A(%)%6%@@;7-G(0H`<FU?07)G<ULP72`]("5S"@!R3
M;5]297-U;'0Q(#T@)60*<FU?4F5S=6QT,B`]("5D"@!R;5]!8W1I;VX@(#T@$
M)3`X>`H`;&Y?3F%M92`@("`]("5S"@!314-/3D0`<V5C;VYD`$-!5`!C870`0
M56YK;F]W;B!#;VUM86YD"@!!4F5X>"!M86-R;R!E<G)O<CH@($-O9&4@/2`E4
M9"`@(%-E=F5R:71Y(#T@)60*`%5S97(@<W!E8VEF:65D(&UA8W)O(&5R<F]R6
M+B`@4D,@/2`E9`H`3F]R;6%L(&UA8W)O('1E<FUI;F%T:6]N+@H`05)E>'@@X
M;F]T(&%V86EL86)L92`M(%)%6%@@<&]R="!N;W0@9F]U;F0*`$-R96%T95)EM
M>'A-<V<H*2!&86EL960*`$-R96%T94%R9W-T<FEN9R@I($9A:6QE9`H``$Y5_
M__1.74YU3E4``$Y=3G5.50``#*T````"``AL"DAX``5.NA#(6$](>``"2'H`>
M,DZZ$R103RE`@EIG&"!M``PO*``$3KK[5EA/+RR"6DZZ$IA83T*G3KH0E%A/4
M3EU.=7)E>'AS>7-L:6(N;&EB<F%R>0``,CS^2F```(PR//]28```A#(\_JI@I
M?#(\_Q!@=G*48'(R//Z\8&PR//ZV8&8R//\T8&`R//YH8%HR//]P8%0R//]\L
M8$XR//]J8$@R//YZ8$(R//YT8#PR//YN8#8R//YB8#`R//Z`8"HR//Y08"1RG
MB&`@,CS_%F`:<II@%C(\_R)@$#(\_QQ@"C(\_UA@!#(\_W8@;P`$(F\`""`O`
M``PO#BQL@EI.MA``+%].=3(\_RY@X#(\_K!@VC(\_SI@U#(\_HQ@SC(\_IY@[
MR#(\_J1@PC(\_T9@O#(\_T!@MC(\_D1@L#(\_P1@JC(\_OY@I#(\_OA@GC(\%
M_O)@F#(\_NQ@DC(\_N!@C#(\_I)@AC(\_H9@@#(\_IA@`/]Z<H)@&C(\_RA@@
M%#)\_V1@#C(\_TQ@"'*.8`0R//[F(&\`!"`O``A@`/]<,CS^R&`0,CS^/F`*'
M,CS^VF`$,CS^."`O``1@`/\^,GS^SF`$,GS_7B!O``0@+P`((B\`#"\.+&R"%
M6DZVD``L7TYU(&\`!#(\_M1A`/\.(F\`""*!3G4@+P`$<J!A`/[\(F\`""*(_
M3G5A<$/L@E)%[()2M<EF#C(\`!1K"'0`(L)1R?_\*4^"7BQX``0I3H)B2.>`Z
M@`@N``0!*6<02_H`"$ZN_^)@!D*G\U].<T/Z`"!.KOYH*4""9F8,+CP``X`'=
M3J[_E&`$3KH`&E!/3G5D;W,N;&EB<F%R>0!)^0``?_Y.=4Y5```O"DAY``$``
M`#`L@D[!_``&+P!.NA!2*4"":E!/9A1"ITAY``$``$ZZ$`I03RYL@EY.=2!LK
M@FI":``$(&R":C%\``$`$"!L@FHQ?``!``H@;()>("R"7I"H``10@"E`@FX@=
M;()N(+Q-04Y80J=.NA`2)$!*J@"L6$]G,"\M``PO+0`(+PI.N@"R*7P````!F
M@G(@;()J`&B````$(&R":@!H@```"D_O``Q@0DAJ`%Q.NA!@2&H`7$ZZ#_0IV
M0()V(&R"=DJH`"103V<0(&R"=B)H`"0O$4ZZ#P183R\L@G8O"DZZ`J8I;()VE
M@GI03TZZ#P0@;()J((!.N@\D(&R":B%```9G%DAX`^U(>@`L3KH/`"!L@FHAS
M0``,4$\O+()Z+RR"?DZZ_$Y"ITZZ#21/[P`,)%].74YU*@!.50``2.<,,"1M5
M`!`@;0`(("@`K.6`*``@1"`H`!#E@"9`$!-(@$C`T*T`#%2`*4""@D*G+RR"P
M@DZZ#O0I0(*&4$]F"$S?##!.74YU$!-(@$C`*@`O!2!+4H@O""\L@H9.N@%BZ
M2'H!7"!L@H;1Q2\(3KH!SB\M``PO"B\L@H9.N@%L(&R"AD(P6``I?`````&"6
M?B!L@H;1Q29(4HLD2T_O`"`0$TB`2,`J`+"\````(&<@NKP````)9QBZO```D
M``QG$+J\````#6<(NKP````*9@12BV#,#!,`(&T``(P,$P`B9C)2BR!+4HL0N
M$$B`2,`J`&<@($I2BA"%NKP````B9A`,$P`B9@12BV`&0BK__V`"8-)@1"!+U
M4HL0$$B`2,`J`&<PNKP````@9RBZO`````EG(+J\````#&<8NKP````-9Q"ZN
MO`````IG""!*4HH0A6#"($I2BD(02H5F`E.+4JR"?F``_SQ"$D*G("R"?E*`3
MY8`O`$ZZ#;8I0()Z4$]F"$*L@GY@`/Z\>@`F;(*&8!H@!>6`(&R">B&+"``O<
M"TZZ!EQ2@-?`6$]2A;JL@GYMX"`%Y8`@;()Z0K`(`&``_H0@`$SO`P``!"`('
M(B\`#&`"$-E7R?_\9P9206`"0AA1R?_\3G4P/'__8`0P+P`.(&\`!$H89OQ3\
M2")O``A30!#95\C__&<"0A`@+P`$3G4P/'__8`0P+P`.4T!K%"!O``0B;P`(!
ML0EF#%-(2AA7R/_V<`!.=6,$<`%.=7#_3G4@;P`$(`@B;P`($-EF_$YU3E4`"
M`$CG#C`D;0`(0J=(>@".3KH-("E`@HI03V8(3-\,<$Y=3G4@;0`,(F@`)"\IJ
M``1.N@UZ*`!83V=22'H`;2!$+R@`-DZZ#4PF0$J`4$]G-$AX`^TO"TZZ#"PL<
M`%!/9R0@!N6`*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ#`@E0`"@4$\O!$ZZI
M#1A83R\L@HI.N@PN0JR"BEA/8(!I8V]N+FQI8G)A<GD`5TE.1$]7`"H`3E4`G
M`"\$*6T`"()22&T`$"\M``Q(>@`:3KH`V"@`(&R"4D(0(`1/[P`,*!].74YU+
M3E4``"!L@E)2K()2$"T`"Q"`2(!(P,"\````_TY=3G5.50``2&T`#"\M``A(V
M>@2N3KH`D$_O``Q.74YU3E4``$CG""`D;0`0#*T````$`!1F""!M``@H$&`47
M2JT`#&\((&T`""@08`8@;0`(*!!"K0`42JT`#&P21*T`#$J$;`I$A"M\````N
M`0`4(BT`#"`$3KH#TD'L@`)3BA2P"``B+0`,(`1.N@/**`!FWDJM`!1G!E.*>
M%+P`+2`*3-\$$$Y=3G5.5?\42.<(,"1M``@F;0`,0JW_^"MM`!#__"!+4HL0*
M$$B`2,`H`&<``S"XO````"5F``,*0BW_(BM\`````?_T*WP````@__`K?```V
M)Q#_["!+4HL0$$B`2,`H`+"\````+6800JW_]"!+4HL0$$B`2,`H`+B\````'
M,&84*WP````P__`@2U*+$!!(@$C`*`"XO````"IF&B!M__Q8K?_\*U#_Z"!+#
M4HL0$$B`2,`H`&`T0JW_Z&`B<@H@+?_H3KH)O-"$D+P````P*T#_Z"!+4HL08
M$$B`2,`H`$'L@!4(,``"2`!FTKB\````+F9B($M2BQ`02(!(P"@`L+P````JD
M9AH@;?_\6*W__"M0_^P@2U*+$!!(@$C`*`!@-$*M_^Q@(G(*("W_[$ZZ"5+0E
MA)"\````,"M`_^P@2U*+$!!(@$C`*`!![(`5"#```D@`9M(K?`````3_Y+B\T
M````;&86($M2BQ`02(!(P"@`*WP````$_^1@%+B\````:&8,($M2BQ`02(!(0
MP"@`(`1@?BM\````"/_@8!PK?`````K_X&`2*WP````0_^!@""M\____]O_@M
M+RW_Y$AM_R(O+?_@+RW__$ZZ_;0K0/_<("W_Y-&M__Q/[P`08%H@;?_\6*W_C
M_"M0_]PO+?_<3KH"'"M`_^183V!*(&W__%BM__PH$$'M_R$K2/_<$(1@*)"\2
M````8V?B4X!GE)"\````"V<`_VY9@&>T58!G`/]N5X!G`/]R8,Q![?\BD>W_I
MW"M(_^0@+?_DL*W_[&\&*VW_[/_D2JW_]&=P(&W_W`P0`"UG"B!M_]P,$``K7
M9C0,K0```##_\&8J4ZW_Z"!M_]Q2K?_<$!!(@$C`+P!.DK"\_____UA/9@IP9
M_TS?#!!.74YU8!@O+?_P3I*PO/____]83V8$</]@XE*M__@@+?_H4ZW_Z+"MO
M_^1NVD*M_^!@)"!M_]Q2K?_<$!!(@$C`+P!.DK"\_____UA/9@1P_V"J4JW_N
MX"!M_]Q*$&<*("W_X+"M_^QMRB`M_^#1K?_X2JW_]&8J8!I(>``@3I*PO/__]
M__]83V8&</]@`/]P4JW_^"`M_^A3K?_HL*W_Y&[88!@O!$Z2L+S_____6$]FF
M!G#_8`#_2%*M__A@`/S$("W_^&``_SA(YT@`0H1*@&H$1(!21$J!:@9$@0I$J
M``%A/DI$9P)$@$S?`!)*@$YU2.=(`$*$2H!J!$2`4D1*@6H"1(%A&B`!8-@OS
M`6$2(`$B'TJ`3G4O`6$&(A]*@$YU2.<P`$A!2D%F($A!-@$T`$)`2$"`PR(`D
M2$`R`H+#,`%"04A!3-\`#$YU2$$F`2(`0D%(04A`0D!T#]"`TX&V@6($DH-2+
M0%'*__),WP`,3G4@;P`$(`A*&&;\D<`@"%.`3G5.50``2&R`K"\M``A.N@`(+
M4$].74YU3E4``"\$*"T`""\M``PO!$ZZ`#2XO`````I03V8F(&T`#!`H``Q(E
M@$C`"```!V<42'C__R\M``Q.N@#\4$\H'TY=3G5@^$Y5```O"B1M``P@4K'JN
M``1E&B`M``C`O````/\O`"\*3KH`SE!/)%].74YU(%)2DA`M``L0@$B`2,#`?
MO````/]@Y$Y5```O"D'L@)8D2"!*U?P````6+PAA$%A/0>R"3K7(9>HD7TY=A
M3G5.50``2.<(("1M``AX`"`*9@IP_TS?!!!.74YU2BH`#&=2""H``@`,9PQ(X
M>/__+PIA5"@`4$\0*@`-2(!(P"\`3KH%!(B`""H``0`,6$]G"B\J``A.N@(Z&
M6$\(*@`%``QG$B\J`!).N@+6+RH`$DZZ`B!03T*20JH`!$*J``A"*@`,(`1@6
MCDY5__Y(YP@@)&T`"$'Z_T0I2(*.""H`!``,9PIP_TS?!!!.74YU""H``@`,L
M9S(H$IBJ``@O!"\J``@0*@`-2(!(P"\`3KH"EK"$3^\`#&<0".H`!``,0I)"D
MJ@`$</]@O@RM_____P`,9A`(J@`"``Q"DD*J``1P`&"D2JH`"&8(+PI.N@"DY
M6$\,:@`!`!!F,!MM``___TAX``%(;?__$"H`#4B`2,`O`$ZZ`C*PO`````%/+
M[P`,9I@@+0`,8`#_8"2J``@P*@`02,#0J@`()4``!`CJ``(`#"!24I(0+0`/F
M$(!(@$C`P+P```#_8`#_,$Y5```O"D'L@)8D2$HJ``QG&-7\````%D'L@DZU-
MR&4(<``D7TY=3G5@XD*20JH`!$*J``@@"F#J3E7__"\*)&T`"$AX!`!.N@#""
M*T#__%A/9A@U?``!`!`@2M'\````#B5(``@D7TY=3G4U?`0``!`(Z@`!``PEA
M;?_\``@0*@`-2(!(P"\`3KH`WDJ`6$]G!@`J`(``#&#,3E4``$CG`#`D;()6&
M8!0F4B`J``10@"\`+PI.N@1@4$\D2R`*9NA"K()63-\,`$Y=3G5.50``+PI!L
M^O_&*4B"DD*G("T`"%"`+P!.N@/^)$!*@%!/9@AP`"1?3EU.=22L@E8E;0`(H
M``0I2H)6(`I0@&#F3E4``"\M``AAMEA/3EU.=4Y5``!(YP`PE\LD;()68`X@<
M;0`(48BQRF<2)DHD4B`*9NYP_TS?#`!.74YU(`MG!":28`0I4H)6("H`!%"`=
M+P`O"DZZ`[9P`%!/8-A.50``+PIR!B`M``A.N@*R)$#5[()J2JT`"&T2,"R""
M3DC`(BT`"+*`;`1*DF80*7P````"@I9P_R1?3EU.=7(&("T`"$ZZ`GH@;()J)
M+S`(`$ZZ`L9*@%A/9P1P`6`"<`!@UDY5```O+0`(3KH"D$J`6$]F#DZZ`IHI?
M0(*6</].74YU<`!@^$Y5``!(YPP@*"T`"$ZZ`'9R!B`$3KH")"1`U>R":DJ$_
M;0XP+().2,"X@&P$2I)F$BE\`````H*6</],WP0P3EU.=3`J``3`?``#9@PI>
M?`````6"EG#_8.(O+0`0+RT`#"\23KH"4"H`L+S_____3^\`#&8,3KH"%"E`.
M@I9P_V"Z(`5@MDY5__Q(>!``0J=.N@+^*T#__`@```Q03V<22JR"<F8(("W_Q
M_$Y=3G5.N@`&<`!@]$Y5``!(>``$2'H`'$ZZ`>HO`$ZZ`>Q(>``!3KH`#D_OM
M`!!.74YU7D,*`$Y5``!*K(*.9P8@;(*.3I`O+0`(3KH`"%A/3EU.=4Y5__PO/
M!"MM``C__$JL@FIG+'@`8`HO!$ZZ`,Y83U*$,"R"3DC`N(!M[#`L@D[!_``&P
M+P`O+()J3KH!\E!/2JR"DF<&(&R"DDZ02JR"FF<*+RR"FDZZ`8Q83TJL@IYGX
M"B\L@IY.N@%\6$]*K(*B9PHO+(*B3KH!;%A/+'@`!`@N``0!*6<4+PU+^@`*I
M3J[_XBI?8`9"I_-?3G-*K()V9BI*K(*&9R(O+(*"+RR"ADZZ`7P@+()^4H#E7
M@"\`+RR">DZZ`6I/[P`08`Y.N@%8+RR"=DZZ`;)83R`M__PN;()>3G4H'TY="
M3G5.50``2.<.("@M``AR!B`$3KH`1"1`U>R":DJ$;0XP+().2,"X@&P$2I)F`
M$BE\`````H*6</],WP1P3EU.=3`J``3`?(``9@@O$DZZ`"Y83T*2<`!@X$CGF
M<``T`<3`)@%(0\;`2$-"0]2#2$#`P4A`0D#0@DS?``Y.=2(O``0L;()F3N[_Y
MW"(O``0L;()F3N[_@B(O``0L;()F3N[_N"QL@F9.[O_*+&R"9D[N_WPB+P`$'
M+&R"9D[N_RA,[P`&``0L;()F3N[_XBQL@F9.[O_$3.\`#@`$+&R"9D[N_]!(D
MYP$$3.\@@``,+&R"8DZN_Y1,WR"`3G5.^@`"(F\`!"QL@F).[OYB(F\`!"QL0
M@F).[OZ>3.\``P`$+&R"8D[N_SHB;P`$+&R"8D[N_GHB;P`$+&R"8D[N_MI.G
M^@`"+&R"8D[N_WPB;P`$("\`""QL@F).[O\N3OH``B!O``0L;()B3N[^C$[ZG
M``(L;()B(F\`!"`O``A.[OW8+&R"8D[N_W9,[P,```0L;()B3N[^DB)O``0LS
M;()B3N[^F$[Z``(B;P`$+&R"8D[N_H9,[P`#``0L;()B3N[^SD[Z``(@;P`$@
M+&R"8D[N_H!,[P,```0L;(**3N[_H"!O``0L;(**3N[_IB!O``0L;(**3N[_!
ML@```^P````!`````0``!OP````````#\@```^H```"4,#$R,S0U-C<X.6%BK
M8V1E9@```"`@("`@("`@(#`P,#`P("`@("`@("`@("`@("`@("`@D$!`0$!`R
M0$!`0$!`0$!`0`P,#`P,#`P,#`Q`0$!`0$!`"0D)"0D)`0$!`0$!`0$!`0$!Z
M`0$!`0$!`0%`0$!`0$`*"@H*"@H"`@("`@("`@("`@("`@("`@("`D!`0$`@,
M``````````````````$``````0`````````````````````!`0````$`````%
M`````````````````0(````!````````````````````````````````````$
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````!0``````_(`)
+``/K`````0```_(`D
``
end
size 6896
//E*O*F rex.uue//

echo x - rexx.c
cat > "rexx.c" << '//E*O*F rexx.c//'

/*
 *  REXX.C
 *
 *      (c) Copyright 1987, 1988 by Kim DeVaughn, All Rights Reserved
 *
 *      This program is freely redistributable for non-commercial purposes.
 *
 *      For commercial use, you may contact the author via USENET at:
 *          kim@amdahl.amdahl.com
 *
 *
 *  ARexx interface code, etc. to interface with Matt Dillon's "dme" editor
 *  (v1.29).
 *
 */


#include "defs.h"
#include "rexx.h"

#if AREXX

APTR OpenLibrary();
APTR FindPort();
APTR GetMsg();
APTR CreateRexxMsg();
APTR CreateArgstring();

extern int foundcmd;

struct RxsLib *RexxSysBase;



/*
 * initialization for ARexx ... just open rexsyslib.library
 */

void
openrexx()
{
    RexxSysBase = (struct RxsLib *)OpenLibrary("rexxsyslib.library", (ULONG)RXSVERS);
    return();
}



/*
 * cleanup any open ARexx stuff ...  just close rexsyslib.library for now
 */

void
closerexx()
{
    if (RexxSysBase) {
        CloseLibrary(RexxSysBase);
    }
    return();
}



/*
 *  explicit invocation interface between do_command() and do_rexx
 *  for ARexx macros having NO arguments (i.e., for the "rx" command)
 */

do_rx()
{
    do_rexx(av[1]);
    return();
}



/*
 *  explicit invocation interface between do_command() and do_rexx
 *  for ARexx macros having ONE argument (i.e., for the "rx1" command)
 */

do_rx1()
{
    char macbuf[256];

    strcpy(macbuf, av[1]);
    strcat(macbuf, " ");
    strcat(macbuf, av[2]);
    do_rexx(macbuf);
    return();
}



/*
 *  explicit invocation interface between do_command() and do_rexx
 *  for ARexx macros having TWO arguments (i.e., for the "rx2" command)
 */

do_rx2()
{
    char macbuf[256];

    strcpy(macbuf, av[1]);
    strcat(macbuf, " ");
    strcat(macbuf, av[2]);
    strcat(macbuf, " ");
    strcat(macbuf, av[3]);
    do_rexx(macbuf);
    return();
}



/*
 *  issue a command to ARexx ...
 */

do_rexx(macstr)
char *macstr;
{
    struct RexxArg *macarg;

    struct MsgPort  RexxPort;
    struct MsgPort *ARexxPort;

    struct RexxMsg *macptr;
    struct RexxMsg *cmdptr;

    char host[16];
    char hexbuf[12];        /* should only need 9 bytes */
    char errmsg[80];        /* don't build a larger error message */

    int  ret;


    if (RexxSysBase == 0) {
        title("Unknown Command   -   No Macros:  ARexx Not Installed ");   /* no rexxsyslib */
        return(0);
    }


    ClearMem(&RexxPort, sizeof(struct MsgPort));
    strcpy(host, "DME");
    sprintf(hexbuf, "%08x", &RexxPort);
    strcat(host, hexbuf);
    InitPort(&RexxPort, host);      /* need to error check this */
    AddPort(&RexxPort);
    /* return here if InitPort failed */


    if (macarg = (struct RexxArg *)CreateArgstring(macstr, strlen(macstr))) {
        if (macptr = (struct RexxMsg *)CreateRexxMsg(&RexxPort, "dme", host)) {
            ACTION(macptr) = RXCOMM;
            ARG0(macptr)   = (STRPTR)macarg;

            Forbid();
            if (ARexxPort = (struct MsgPort *)FindPort("REXX")) {
                PutMsg(ARexxPort, macptr);
                Permit();
                title("Calling ARexx Macro ... ");

                for (;;) {
                    WaitPort(&RexxPort);
                    cmdptr = (struct RexxMsg *)GetMsg(&RexxPort);

                    if (IsRexxMsg(cmdptr)) {

                        foundcmd = 0;
                        ret = do_command(ARG0(cmdptr));
                        if (foundcmd) {
                            ret = (ret == 1) ? 0 : 5;   /* cmd error:  RC = 5  */
                        } else {
                            ret = do_rexx(ARG0(cmdptr));    /* another macro? */
                        }

                        RESULT1(cmdptr) = ret;
                        RESULT2(cmdptr) = 0;
                        ReplyMsg(cmdptr);
                    }
                    do_command("null");     /* a kludge to set "foundcmd" */
                    if (macptr == cmdptr) break;
                }


                if (ret = RESULT1(cmdptr)) {
                    if (RESULT2(cmdptr)) {
                        if (RESULT2(cmdptr) == 1) {
                            title("Unknown Command ");
                        } else {
                            sprintf(errmsg, "ARexx Macro Error:  Code = %d  Severity = %d ", RESULT2(cmdptr), ret);
                            title(errmsg);
                        }
                    } else {
                        sprintf(errmsg, "User Specified Macro Error:  RC = %d ", ret);
                        title(errmsg);
                    }
                } else {
                    title("OK ");
                }
            } else {
                title("Unknown Command   -   No Macros:  ARexx Not Active ");   /* no REXX port */
                ret = -1;
            }
            DeleteRexxMsg(macptr);
        } else {
            title("CreateRexxMsg() Failed ");   /* may be overkill, and not need to ckeck this */
            ret = -1;
        }
        DeleteArgstring(macarg);
    } else {
        title("CreateArgstring() Failed ");     /* may be overkill, and not need to check this */
        ret = -1;
    }


    RemPort(&RexxPort);
    FreePort(&RexxPort);
    return(ret);
}



/*
 *  a kludge to flush the do_command pipe ... until I can fix a recursive macro bug ...
 */

void
do_null()
{
    return();
}

#endif

//E*O*F rexx.c//

echo x - rexx.h
cat > "rexx.h" << '//E*O*F rexx.h//'
/*
 *
 * A few additional defines to make life a little easier.
 *
 * (c) Copyright 1987 Kim DeVaughn, All Rights Reserved
 *
 */

#ifndef REXX_STORAGE_H
#include <rexx/storage.h>
#endif

#ifndef REXX_H
#define REXX_H


/* more RexxMsg field definitions					   */

#define ACTION(rmp) (rmp->rm_Action)       /* command (action) code        */
#define RESULT1(rmp) (rmp->rm_Result1)     /* primary result (return code) */
#define RESULT2(rmp) (rmp->rm_Result2)     /* secondary result             */
#define COMM_ADDR(rmp) (rmp->rm_CommAddr)  /* host address (port name)     */
#define FILE_EXT(rmp) (rmp->rm_FileExt)    /* file extension               */

#endif

//E*O*F rexx.h//

echo x - Makefile
cat > "Makefile" << '//E*O*F Makefile//'
#   Note:  In terms of compiling, if you do not have Matt's latest
#   support library you may have to do some hacking to get the
#   code to link.
#
#   The precompiled symbol table, SYMBOLS.M, is *only* the AMIGA includes
#   .. */*.h (exec/*.h, etc....).  When generating a precompiled symbol
#   table remember to use the +L compiler option.

CFLAGS= +L -Idme:include -Idme:sup32lib +Ivd0:include/symbols.m
OBJS= rex.o rexxglue.o
ASMS= rex.asm
SRCS= rex.c
HDR=  defs.h rexx.h

.c.o:
    cc $(CFLAGS) -o $@ $*.c

.c.asm:
    cc $(CFLAGS) -A -o ram:$@ $*.c


all: $(OBJS)
    ln +Q $(OBJS) -lsup32 -lc32 -O rex

//E*O*F Makefile//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      9     52    172 args.dme
    200    505   4969 rex.c
    159    161   9690 rex.uue
    235    586   5285 rexx.c
     26     81    664 rexx.h
     24     98    614 Makefile
    653   1483  21394 total
!!!
wc  args.dme rex.c rex.uue rexx.c rexx.h Makefile | sed 's=[^ ]*/==' | diff -b $temp -
exit 0

-- 
UUCP:  kim@amdahl.amdahl.com
  or:  {sun,decwrl,hplabs,pyramid,ihnp4,uunet,oliveb,cbosgd,ames}!amdahl!kim
DDD:   408-746-8462
USPS:  Amdahl Corp.  M/S 249,  1250 E. Arques Av,  Sunnyvale, CA 94086
CIS:   76535,25