home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / jade-3.0.lha / Jade / src / amiga_minrexx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-20  |  9.3 KB  |  396 lines

  1. /* amiga_minrexx.c -- ARexx interface
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. This file is part of Jade.
  5.  
  6. Jade is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. Jade is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with Jade; see the file COPYING.    If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Originally by Radical Eye Software, modified by me.
  22.  */
  23.  
  24. static char *blurb = "Radical Eye MinRexx 0.4.jsh";
  25.  
  26. #include "jade.h"
  27. #include "jade_protos.h"
  28.  
  29. #include <clib/exec_protos.h>
  30. #ifdef _DCC
  31. # define RexxSysBase_DECLARED
  32. #endif
  33. #include <clib/rexxsyslib_protos.h>
  34. #include <string.h>
  35.  
  36. _PR void rexx_init(void);
  37. _PR void rexx_kill(void);
  38.  
  39. _PR VALUE do_sync_rexx(u_char *, bool);
  40. _PR void disp_rexx_port(void);
  41. static struct RexxMsg *send_rexx_cmd(u_char *, int(*)(), u_char *, u_char *, u_char *, long);
  42. _PR struct RexxMsg *sync_rexx_cmd(u_char *, bool, struct RexxMsg *);
  43. _PR struct RexxMsg *async_rexx_cmd(u_char *);
  44. _PR struct RexxMsg *async_rexx_string(u_char *);
  45. _PR void reply_rexx_cmd(struct RexxMsg *, long, long, u_char *);
  46. static void close_rexx_lib(void);
  47. static bool open_rexx_lib(void);
  48. static void reply_to_it(struct RexxMsg *);
  49.  
  50. _PR u_long RexxSig;
  51.     u_long RexxSig;
  52.  
  53. static struct MsgPort *RexxPort;
  54. static bool BringerDown;
  55. static long StillNeedReplies;
  56. static struct RexxMsg *oRexxMsg;
  57. static VALUE RexxName;
  58.  
  59. struct RxsLib *RexxSysBase;
  60.  
  61. #define RX_EXTEN "jade"
  62.  
  63. #define MAXRXOUTSTANDING (300)
  64. #define RXERRORIMGONE (100)
  65. #define RXERRORNOCMD (30)
  66.  
  67. _PR VALUE cmd_rexx_async_macro(VALUE name);
  68. DEFUN("rexx-async-macro", cmd_rexx_async_macro, subr_rexx_async_macro, (VALUE name), V_Subr1, DOC_rexx_async_macro) /*
  69. ::doc:rexx_async_macro::
  70. (rexx-async-macro NAME) <AMIGA-ONLY>
  71. Asynchronously invokes the ARexx macro called NAME.
  72. ::end:: */
  73. {
  74.     DECLARE1(name, STRINGP);
  75.     if(async_rexx_cmd(VSTR(name)))
  76.     return(sym_t);
  77.     return(sym_nil);
  78. }
  79.  
  80. _PR VALUE cmd_rexx_async_str(VALUE str);
  81. DEFUN("rexx-async-str", cmd_rexx_async_str, subr_rexx_async_str, (VALUE str), V_Subr1, DOC_rexx_async_str) /*
  82. ::doc:rexx_async_str::
  83. (rexx-async-str STRING) <AMIGA-ONLY>
  84. Gets ARexx to asynchronously interpret the string of REXX code STRING.
  85. ::end:: */
  86. {
  87.     DECLARE1(str, STRINGP);
  88.     if(async_rexx_string(VSTR(str)))
  89.     return(sym_t);
  90.     return(sym_nil);
  91. }
  92.  
  93. _PR VALUE cmd_rexx_sync_macro(VALUE name);
  94. DEFUN("rexx-sync-macro", cmd_rexx_sync_macro, subr_rexx_sync_macro, (VALUE name), V_Subr1, DOC_rexx_sync_macro) /*
  95. ::doc:rexx_sync_macro::
  96. (rexx-sync-macro NAME) <AMIGA-ONLY>
  97. Invokes the ARexx macro NAME synchronously, returning its value when it
  98. exits (this will either be a number or a string.
  99. ::end:: */
  100. {
  101.     DECLARE1(name, STRINGP);
  102.     return(do_sync_rexx(VSTR(name), TRUE));
  103. }
  104.  
  105. _PR VALUE cmd_rexx_sync_str(VALUE str);
  106. DEFUN("rexx-sync-str", cmd_rexx_sync_str, subr_rexx_sync_str, (VALUE str), V_Subr1, DOC_rexx_sync_str) /*
  107. ::doc:rexx_sync_str::
  108. (rexx-sync-str STRING) <AMIGA-ONLY>
  109. Synchronously executes the string of ARexx commands STRING, returning their
  110. exit value.
  111. ::end:: */
  112. {
  113.     DECLARE1(str, STRINGP);
  114.     return(do_sync_rexx(VSTR(str), FALSE));
  115. }
  116.  
  117. _PR VALUE var_rexx_port_name(VALUE val);
  118. DEFUN("rexx-port-name", var_rexx_port_name, subr_rexx_port_name, (VALUE val), V_Var, DOC_rexx_port_name) /*
  119. ::doc:rexx_port_name::
  120. Variable holding the name of our ARexx port. (Amiga only).
  121. ::end:: */
  122. {
  123.     if(val)
  124.     return(NULL);
  125.     return(RexxName ? RexxName : sym_nil);
  126. }
  127.  
  128. void
  129. rexx_init(void)
  130. {
  131.     int i;
  132.     static UBYTE name[32];
  133.     name[0] = V_StaticString;
  134.     Forbid();
  135.     for(i = 1;; i++)
  136.     {
  137.     sprintf(VSTR(name), "JADE.%d", i);
  138.     if(!FindPort(VSTR(name)))
  139.     {
  140.         RexxPort = CreateMsgPort();
  141.         if(RexxPort)
  142.         {
  143.         RexxPort->mp_Node.ln_Name = VSTR(name);
  144.         RexxPort->mp_Node.ln_Pri = 1;
  145.         AddPort(RexxPort);
  146.         RexxSig = 1 << RexxPort->mp_SigBit;
  147.         RexxName = name;
  148.         }
  149.     }
  150.     break;
  151.     }
  152.     Permit();
  153.     ADD_SUBR(subr_rexx_async_macro);
  154.     ADD_SUBR(subr_rexx_async_str);
  155.     ADD_SUBR(subr_rexx_sync_macro);
  156.     ADD_SUBR(subr_rexx_sync_str);
  157.     ADD_SUBR(subr_rexx_port_name);
  158. }
  159.  
  160. void
  161. rexx_kill(void)
  162. {
  163.     if(RexxPort)
  164.     {
  165.     RemPort(RexxPort);
  166.     BringerDown = TRUE;
  167.     if(oRexxMsg)
  168.     {
  169.         oRexxMsg->rm_Result1 = RXERRORIMGONE;
  170.         ReplyMsg((struct Message *)oRexxMsg);
  171.         oRexxMsg = NULL;
  172.     }
  173.     while(StillNeedReplies)
  174.     {
  175.         WaitPort(RexxPort);
  176.         disp_rexx_port();
  177.     }
  178.     close_rexx_lib();
  179.     DeleteMsgPort(RexxPort);
  180.     RexxPort = NULL;
  181.     }
  182.     RexxSig = 0;
  183. }
  184.  
  185. /*
  186.  * This function [hopefully] performs a synchronous REXX call, from
  187.  * which we get the result :)
  188.  */
  189. VALUE
  190. do_sync_rexx(u_char *arg, bool isMac)
  191. {
  192.     VALUE result = sym_nil;
  193.     if(RexxPort && open_rexx_lib())
  194.     {
  195.     struct MsgPort *rp;
  196.     if(rp = CreateMsgPort())
  197.     {
  198.         struct RexxMsg *rm;
  199.         if(rm = CreateRexxMsg(rp, RX_EXTEN, RexxPort->mp_Node.ln_Name))
  200.         {
  201.         rm->rm_Action |= RXFF_RESULT;
  202.         if(send_rexx_cmd(arg, reply_to_it, (char *)rm, NULL, NULL, (isMac ? 0 : RXFF_STRING) | RXFF_RESULT))
  203.         {
  204.             u_long rpsigmask = 1 << rp->mp_SigBit;
  205.             u_long sigs;
  206.  
  207.             do {
  208.             sigs = Wait(rpsigmask | RexxSig);
  209.             disp_rexx_port();
  210.             } while(!(sigs & rpsigmask));
  211.  
  212.             if(GetMsg(rp))
  213.             {
  214.             if(!rm->rm_Result1 && rm->rm_Result2)
  215.             {
  216.                 result = valstrdup((u_char *)rm->rm_Result2);
  217.                 if(open_rexx_lib())
  218.                 DeleteArgstring((u_char *)rm->rm_Result2);
  219.             }
  220.             else
  221.                 result = newnumber(rm->rm_Result1);
  222.             }
  223.         }
  224.         if(open_rexx_lib())
  225.             DeleteRexxMsg(rm);
  226.         }
  227.         DeleteMsgPort(rp);
  228.     }
  229.     close_rexx_lib();
  230.     }
  231.     return(result);
  232. }
  233.  
  234. static void
  235. close_rexx_lib(void)
  236. {
  237.     if((!StillNeedReplies) && RexxSysBase)
  238.     {
  239.     CloseLibrary((struct Library *)RexxSysBase);
  240.     RexxSysBase = NULL;
  241.     }
  242. }
  243.  
  244. void
  245. disp_rexx_port(void)
  246. {
  247.     struct RexxMsg *rexxmsg;
  248.     u_char *cmd;
  249.  
  250.     if(!RexxPort)
  251.     return;
  252.  
  253.     while(rexxmsg = (struct RexxMsg *)GetMsg(RexxPort))
  254.     {
  255.     if(rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  256.     {
  257.         if (rexxmsg->rm_Args[1])
  258.         {
  259.         ((int (*)(struct RexxMsg *))(rexxmsg->rm_Args[1]))(rexxmsg);
  260.         }
  261.         DeleteArgstring(rexxmsg->rm_Args[0]);
  262.         DeleteRexxMsg(rexxmsg);
  263.         StillNeedReplies--;
  264.         close_rexx_lib();
  265.     }
  266.     else
  267.     {
  268.         cmd = (u_char *)rexxmsg->rm_Args[0];
  269.         while (*cmd > 0 && *cmd <= ' ')
  270.         cmd++;
  271.         rexxmsg->rm_Result1 = 0;
  272.         rexxmsg->rm_Result2 = 0;
  273.  
  274.         if(BringerDown)
  275.         rexxmsg->rm_Result1 = RXERRORIMGONE;
  276.         else
  277.         {
  278.         VALUE res;
  279.         oRexxMsg = rexxmsg ;
  280.         cursor(CurrVW, CURS_OFF);
  281.         res = evalstring(cmd, FALSE);
  282.         if(res)
  283.         {
  284.             if(STRINGP(res))
  285.             reply_rexx_cmd(rexxmsg, 0, 0, VSTR(res));
  286.             else if(NUMBERP(res))
  287.             {
  288.             u_char buf[32];
  289.             sprintf(buf, "%d", VNUM(res));
  290.             reply_rexx_cmd(rexxmsg, 0, 0, buf);
  291.             }
  292.             else if(res == sym_nil)
  293.             reply_rexx_cmd(rexxmsg, 5, 0, NULL);
  294.             else
  295.             reply_rexx_cmd(rexxmsg, 0, 0, NULL);
  296.         }
  297.         else
  298.             rexxmsg->rm_Result1 = RXERRORNOCMD;
  299.         cursor(CurrVW, CURS_ON);
  300.         }
  301.         oRexxMsg = NULL ;
  302.         ReplyMsg((struct Message *)rexxmsg);
  303.     }
  304.     }
  305.     refreshworldcurs();
  306. }
  307.  
  308. static bool
  309. open_rexx_lib(void)
  310. {
  311.     if(RexxSysBase || (RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L)))
  312.     return(TRUE);
  313.     return(FALSE);
  314. }
  315.  
  316. static struct RexxMsg *
  317. send_rexx_cmd(u_char *s, int(*f)(), u_char *p1, u_char *p2, u_char *p3, long m)
  318. {
  319.     struct MsgPort *rexxport;
  320.     struct RexxMsg *rexxmsg;
  321.  
  322.     if((!RexxPort) || (StillNeedReplies > MAXRXOUTSTANDING-1))
  323.     return(FALSE);
  324.     rexxmsg = NULL;
  325.     if(open_rexx_lib()
  326.        && (rexxmsg = CreateRexxMsg(RexxPort, RX_EXTEN, RexxPort->mp_Node.ln_Name))
  327.        && (rexxmsg->rm_Args[0] = CreateArgstring(s, (long)strlen(s))))
  328.     {
  329.     rexxmsg->rm_Action = RXCOMM | m;
  330.     rexxmsg->rm_Args[1] = (u_char *)f;
  331.     rexxmsg->rm_Args[2] = p1;
  332.     rexxmsg->rm_Args[3] = p2;
  333.     rexxmsg->rm_Args[4] = p3;
  334.     rexxmsg->rm_Node.mn_Node.ln_Name = RXSDIR;
  335.     Forbid();
  336.     if(rexxport = FindPort(RXSDIR))
  337.         PutMsg(rexxport, (struct Message *)rexxmsg);
  338.     Permit();
  339.     if(rexxport)
  340.     {
  341.         StillNeedReplies++;
  342.         return(rexxmsg);
  343.     }
  344.     else
  345.         DeleteArgstring(rexxmsg->rm_Args[0]);
  346.     }
  347.     if(rexxmsg)
  348.     DeleteRexxMsg(rexxmsg);
  349.     close_rexx_lib();
  350.     return(FALSE);
  351. }
  352.  
  353. struct RexxMsg *
  354. async_rexx_cmd(u_char *s)
  355. {
  356.     return(send_rexx_cmd(s, NULL, NULL, NULL, NULL, 0));
  357. }
  358.  
  359. struct RexxMsg *
  360. async_rexx_string(u_char *s)
  361. {
  362.     return(send_rexx_cmd(s, NULL, NULL, NULL, NULL, RXFF_STRING));
  363. }
  364.  
  365. static void
  366. reply_to_it(struct RexxMsg *msg)
  367. {
  368.     struct RexxMsg *omsg = (struct RexxMsg *)(msg->rm_Args[2]);
  369.     reply_rexx_cmd(omsg, msg->rm_Result1, msg->rm_Result2,
  370.            (u_char *)msg->rm_Result2);
  371.     ReplyMsg((struct Message *)omsg);
  372. }
  373.  
  374. struct RexxMsg *
  375. sync_rexx_cmd(u_char *s, bool isMac, struct RexxMsg *msg)
  376. {
  377.     return(send_rexx_cmd(s, reply_to_it, (u_char *)msg, NULL, NULL,
  378.              isMac ? 0 : RXFF_STRING));
  379. }
  380.  
  381. void
  382. reply_rexx_cmd(struct RexxMsg *msg, long primary, long secondary,
  383.            u_char *string)
  384. {
  385.     if(!primary && (msg->rm_Action & (1L << RXFB_RESULT)))
  386.     {
  387.     if(string && open_rexx_lib())
  388.         secondary = (long)CreateArgstring(string, (long)strlen(string));
  389.     else
  390.         secondary = 0L;
  391.     }
  392.     msg->rm_Result1 = primary;
  393.     msg->rm_Result2 = secondary;
  394.     close_rexx_lib();
  395. }
  396.