home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 310.lha / Rexx_4th / fancydemo.4th < prev    next >
Text File  |  1980-12-10  |  10KB  |  359 lines

  1. \ /****************************************************************************
  2. \    fancydemo.4th   -- converted from .....
  3. \    fancydemo.c - A fancy rexx host that can send and receive messages.
  4. \    Author - Gary Samad & Bill Hawes
  5. \    Revisions:
  6. \       7-Mar-88   Original version.
  7. \      16-Mar-88   Added result string return (WSH)
  8. \    This is truly Public Domain!!
  9. \
  10. \ Converted to CSI MultiForth 10/15/89 by Kerry Zimmerman [71470,1340]
  11. \ ****************************************************************************/
  12. 10000 minimum.vocab
  13. 6000  minimum.object
  14.  
  15. include" libraries/dos.f"
  16. include" libraries/dosextens.f"
  17. include" rexx/rexxcalls.4th"
  18.  
  19. anew fancymark
  20.  
  21. : createport()   compile createport  ; immediate
  22. : deleteport()   compile deleteport  ; immediate
  23. : putmsg()       compile eputmsg     ; immediate
  24. : getmsg()       compile egetmsg     ; immediate
  25. : ReplyMsg()     compile ereplymsg   ; immediate
  26. : Wait()         compile eWait       ; immediate
  27. : forbid()         exec 22 ;
  28. : permit()         exec 23 ;
  29. : findport()     !A1  exec@ 65 ;
  30.  
  31. 1 constant YES \ #define YES      1
  32. 0 constant NO  \ #define NO      0
  33.  
  34. 0 constant OK  \ #define OK      0
  35. 1 constant NOTOK \ #define NOTOK      1
  36.  
  37. 0 constant EOS  \ #define EOS      '\0'
  38.  
  39. : NO_REXX_MSG   
  40.   ." Rexx is not active.  Please run 'rexxmast' from another CLI." cr ;
  41.   
  42. \ : STARTUP_MSG   ." Type commands to rexx.  Type EOF (^\) to end." cr ;
  43. : STARTUP_MSG   0" Type commands to rexx.  Type EOF (^\) to end." ;
  44.  
  45. : CLOSING_MSG   
  46.     ." Ok, we're closing (after all rexx messages have returned)." cr ;
  47.  
  48. : WINDOW_SPEC   0" CON:0/10/600/60/Fancy Demo Input Window/c" ;
  49.  
  50. : HOST_PORT_NAME   0" FancyDemo" ;
  51.  
  52. : REXX_EXTENSION   0" rexx" ;
  53. : RXSDIR           0" REXX" ;
  54.  
  55. 100 constant BUFFLEN    \ #define BUFFLEN      100
  56.  
  57. global outstanding_rexx_commands  0 to outstanding_rexx_commands
  58.  
  59. global window_file_handle  0 to window_file_handle
  60. global dos_reply_port      0 to dos_reply_port
  61. global dos_message         0 to dos_message
  62. global rexx_port           0 to rexx_port
  63.  
  64. BUFFLEN 1 1array buff \ used for reading user input
  65.  
  66. : close_window()  ( file_handle -- )
  67.    Close
  68. ;
  69.  
  70. : shutdown_rexx_port() ( rexx_port -- )
  71.    DeletePort()
  72. ;
  73.  
  74. : shutdown_dos_reply_port()  ( dos_reply_port -- )
  75.    DeletePort
  76. ;
  77.  
  78. : free_dos_message() ( dos_message -- )
  79.    to.heap
  80. ;
  81.  
  82. : close_up_shop() ( value -- )
  83.    window_file_handle ?dup if  close_window()  then
  84.    dos_reply_port  ?dup if shutdown_dos_reply_port() then
  85.    rexx_port  ?dup if  shutdown_rexx_port()  then
  86.    dos_message  ?dup if  free_dos_message()  then
  87.    ( value )  ." exit value = " . cr abort
  88. ;
  89.  
  90. \ /**** These are dos functions for getting and displaying user input ****/
  91. : open_window()  ( -- file_handle )
  92.    WINDOW_SPEC  new.file dup to window_file_handle
  93. ;
  94.  
  95. : setup_dos_reply_port() ( -- port )
  96.    NULL 0 CreatePort
  97. ;
  98.  
  99. : setup_dos_message() ( -- new_packet )
  100.    0 locals| new_packet |
  101.  
  102.    \ /* get a packet */
  103.    StandardPacket from.heap  dup to new_packet  if
  104.      \ /* required AmigaDOS Kludge */
  105.      new_packet @ +spPkt   new_packet @ +spMsg +mnNode +lnName ! 
  106.      new_packet @ +spMsg   new_packet @ +spPkt +dpLink !
  107.    then
  108.  
  109.    new_packet
  110. ;
  111.  
  112. : send_read_packet() ( dos_message\window_file_handle\dos_reply_port\buff -- )
  113.   0
  114.   locals| ]file_handle ]buff ]dos_reply_port ]window_file_handle ]dos_message |
  115.  
  116.    \ /* change a BPTR to a REAL pointer */
  117.    ]window_file_handle  2 scale   to ]file_handle
  118.  
  119.    \ /* setup the packet for reading */
  120.    ]file_handle +fhArgs @   ]dos_message  +spPkt +dpArg1 !
  121.    ]buff                    ]dos_message  +spPkt +dpArg2 !
  122.    BUFFLEN                  ]dos_message  +spPkt +dpArg3 !
  123.    ACTION_READ              ]dos_message  +spPkt +dpType !
  124.    ]dos_reply_port          ]dos_message  +spPkt +dpPort !
  125.    ]dos_reply_port          ]dos_message  +spMsg +mnReplyPort !
  126.  
  127.    \ /* now send it */
  128.    ]file_handle +fhType @   ]dos_message   PutMsg()
  129. ;
  130.  
  131. \ /******** This is the REXX stuff ********/
  132. : setup_rexx_port()  ( -- the_port )
  133.    locals|  the_port  | 
  134.  
  135.    Forbid()
  136.  
  137.    \ /* look for someone else that looks just like us! */
  138.    HOST_PORT_NAME  FindPort()  if
  139.      Permit()
  140.      ." A public port called " 
  141.      HOST_PORT_NAME dup 0$len type 
  142.      ."  already exists!" cr
  143.      0 to the_port
  144.    else
  145.         \ /* allocate the port */
  146.         HOST_PORT_NAME  0  CreatePort()  to the_port
  147.         Permit()
  148.    then
  149.      
  150.    the_port
  151. ;
  152.  
  153. : send_rexx_command()  ( buff -- result )
  154.    0 0 locals|   rexx_command_message  rexxport buff  |
  155.  
  156.    \ /* lock things temporarily */
  157.    Forbid()
  158.  
  159.    \ /* if rexx is not active, just return NOTOK */
  160.    RXSDIR FindPort()  dup to rexxport  0= if
  161.      Permit()
  162.      NOTOK exit
  163.    then
  164.  
  165.    \ /* allocate a message packet for our command */
  166.    \ /* note that this is a very important call.  Much flexibility is */
  167.    \ /* available to you here by using multiple host port names, etc. */
  168.    rexx_port REXX_EXTENSION rexx_port +mpNode +lnName @  CreateRexxMsg
  169.    dup to rexx_command_message  0= if
  170.      Permit()
  171.      NOTOK exit
  172.    then
  173.  
  174.    \ /* create an argument string and install it in the message */
  175.    buff dup strlen  CreateArgstring  dup   rexx_command_message +rm_Args !
  176.    0= if
  177.      DeleteRexxMsg
  178.      Permit()
  179.      NOTOK exit
  180.    then
  181.  
  182.    \ /* tell rexx that this is a COMMAND, not a FUNCTION, etc. */
  183.    RXCOMM   rexx_command_message +rm_Action !
  184.  
  185.    \ /* and now the EASY part! */
  186.    rexxport rexx_command_message   PutMsg()
  187.  
  188.    \ /* keep a count of outstanding messages for graceful cleanup */
  189.    outstanding_rexx_commands  1+  to outstanding_rexx_commands
  190.  
  191.    \ /* we're done hogging */
  192.    Permit()
  193.    
  194.    \ /* successful, finally... */
  195.    OK
  196. ;
  197.  
  198. : free_rexx_command()  ( rexxmessage -- )
  199.    \ /* delete the argument that we originally sent */
  200.    dup ( rexxmessage ) +rm_Args @  DeleteArgstring
  201.  
  202.    \ /* delete the extended message */
  203.    DeleteRexxMsg
  204.  
  205.    \ /* decrement the count of outstanding messages */
  206.    outstanding_rexx_commands 1-  to outstanding_rexx_commands
  207. ;
  208.  
  209. \ /* Replies a REXX message, filling in the appropriate codes.  If the macro
  210. \  * program has requested a result string, the return argstring is allocated
  211. \  * and installed in the rm_Result2 slot.
  212. \  *
  213. \  * A result is returned ONLY IF REQUESTED AND THE PRIMARY RESULT == 0.
  214. \  */
  215.  
  216. : reply_rexx_command()   ( rexxmessage\primary\secondary\result -- )
  217.     locals| result secondary primary rexxmessage |
  218.    
  219.    \ /* set an error code */
  220.    primary 0=     
  221.    rexxmessage +rm_Action @  1 RXFB_RESULT scale   and
  222.    and if
  223.       result if
  224.         result dup strlen CreateArgString
  225.       else
  226.         0
  227.       then
  228.       to secondary
  229.    then
  230.    
  231.    primary    rexxmessage +rm_Result1 !
  232.    secondary  rexxmessage +rm_Result2 !
  233.    
  234.    rexxmessage  ReplyMsg()
  235. ;
  236.  
  237. : execute_command()   ( rexxmessage -- )
  238.    0 0 locals| primary secondary rexxmessage |
  239.  
  240.    ." got "
  241.    rexxmessage +rm_Args @  dup 0$len type
  242.    ."  from rexx" cr
  243.  
  244.    rexxmessage +rm_Args @  0" BAD" 3 StrcmpN 0= if
  245.      10 to primary
  246.    then
  247.  
  248.    rexxmessage primary secondary 0" A Test"  reply_rexx_command()
  249. ;
  250.  
  251. : main
  252.    NO 0 NO 
  253.    locals|  packet_out rexxmessage close_down  |
  254.  
  255.    \ /* open a window to talk to the user through */
  256.    open_window() 0= if
  257.      ." sorry, couldn't open a CON: window" cr
  258.      10 close_up_shop()
  259.    then
  260.  
  261.    \ /* set up a port for dos replys */
  262.    setup_dos_reply_port() dup to dos_reply_port   0= if
  263.      ." sorry, couldn't set up a dos_reply_port" cr
  264.      11 close_up_shop()
  265.    then
  266.    
  267.    \ /* set up a public port for rexx to talk to us later */
  268.    setup_rexx_port() dup to rexx_port   0= if
  269.      ." sorry, couldn't set up our public rexx port" cr
  270.      12 close_up_shop()
  271.    then
  272.    
  273.    \ /* set up a dos packet for the asynchronous read from the window */
  274.    setup_dos_message() dup to dos_message  0= if
  275.      ." sorry, not enough memory for a dos packet" cr
  276.      13 close_up_shop()
  277.    then
  278.    
  279.     \ /* write instructions to user in the input window */
  280.     STARTUP_MSG  dup strlen   window_file_handle  write
  281.     CRLF 1+           1       window_file_handle  write
  282.     
  283.    \ /* loop until quit and no messages outstanding */
  284.    begin
  285.      close_down NO =   outstanding_rexx_commands  or
  286.    while
  287.      
  288.      \ /* if the packet (for user input) has not been sent out, send it */
  289.      packet_out NO =  close_down NO =  and if
  290.        \ /* send a packet to dos asking for user keyboard input */
  291.        dos_message @ window_file_handle dos_reply_port 0 buff 
  292.           send_read_packet()
  293.        YES to packet_out
  294.      then
  295.      
  296.      \ /* now wait for something to come from the user or from rexx */
  297.      \ Wait((1L<<dos_reply_port->mp_SigBit) | (1L<<rexx_port->mp_SigBit));
  298.      1 dos_reply_port +mpSigBit c@ scale 
  299.      1 rexx_port      +mpSigBit c@ scale or  Wait()
  300.  
  301.      \ /* got something!! */
  302.      \ /* is it a command from the user? */
  303.      dos_reply_port  Getmsg() if
  304.        
  305.        \ /* not out any more */
  306.        NO to packet_out
  307.  
  308.        \ /* if EOF (either the close gadget was hit or ^\) */
  309.        dos_message @ +spPkt +dpRes1 @ 0= if
  310.          YES to close_down
  311.          CLOSING_MSG
  312.        else
  313.          \ /* NULL terminate the string (thanks again DOS!) */
  314.          EOS   dos_message @ +spPkt +dpRes1 @ 1- buff c!
  315.  
  316.          \ /* send the command directly to rexx */
  317.          0 buff send_rexx_command()  OK  = NOT if
  318.            NO_REXX_MSG
  319.          then
  320.        then
  321.      then
  322.  
  323.      \ /* did we get something from rexx? */
  324.      begin
  325.         rexx_port GetMsg() dup to rexxmessage
  326.      while
  327.  
  328.        \ /* is this a reply to a previous message? */
  329.        rexxmessage +rm_Node +mnNode +lnType c@  NT_REPLYMSG = if
  330.          ." the command "
  331.          rexxmessage +rm_Args @  dup 0$len type
  332.          ."  has terminated with code "
  333.          rexxmessage +rm_Result1 @ .
  334.          ." , "  rexxmessage +rm_Result2 @ .  cr
  335.          rexxmessage free_rexx_command()
  336.        else
  337.          
  338.          \ /* a rexx macro has sent us a command, deal with it */
  339.          \ /* THE MESSAGE WILL HAVE BEEN REPLIED INSIDE OF execute_command */
  340.          rexxmessage execute_command()
  341.        then
  342.      repeat \ while get rexxmessage
  343.    repeat \ while (!close_down || outstanding_rexx_commands)
  344.  
  345.    \ /* clean up */
  346.    0 close_up_shop()
  347. ;
  348.  
  349. : cleanup  0 close_up_shop() ;
  350.  
  351. openrexxlib drop
  352.  
  353. ." done compiling" cr cr
  354. ." enter  MAIN  to begin" cr
  355. abort
  356.