home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 545b.lha / RexxHS / RexxHS.Article < prev    next >
Encoding:
Text File  |  1991-09-07  |  10.2 KB  |  273 lines

  1.  
  2. ARexx Command Hosts
  3. -------------------
  4.  
  5. Copyright (c)1991 by Eric Giguere
  6.  
  7. Permission is granted to distribute the text of the article
  8. providing this notice is left and said distribution is for
  9. non-commercial purposes.  The programs accompanying this
  10. article are in the public domain, however, so do what you
  11. want with them.
  12.  
  13.  
  14.  
  15.  
  16. Last issue we looked at the details involved in implementing
  17. an ARexx function host, which is an application that can
  18. accept function calls from ARexx programs.  This month
  19. we'll implement something similar: an ARexx command host,
  20. written in ARexx instead of C.  And as an experiment we'll
  21. also write a function host in ARexx.  To do all this,
  22. we need some help in the form of a new ARexx function library.
  23. But first let's refresh our memories...
  24.  
  25. Note:  This article assumes you have a basic understanding of
  26. the Amiga's interprocess communication facilities.  If not,
  27. please refer to my article in the second issue of the Tech Journal.
  28. Though Amiga shared libraries won't be discussed in much detail,
  29. you might also want to read Jim Fiore's article "Shared Libraries
  30. for the Lazy" from the first issue.  More details on the ARexx features
  31. described in this article (including instructions on how to implement
  32. function libraries) can be found in the Amiga Programmer's Guide to ARexx,
  33. available from Commodore-Amiga Technical Support.
  34.  
  35.  
  36.  
  37. Definitions
  38.  
  39. An ARexx command host (sometimes called a host application)
  40. is simply an application program that accepts and responds to
  41. ARexx command strings.  A command string can be sent with the
  42. ARexx ADDRESS instruction:
  43.  
  44.         address 'TURBOTEXT' 'move' line col
  45.  
  46. Command strings can be declared separately:
  47.  
  48.         address 'AMIGATEX'
  49.         'ToFront'
  50.         'TeXify' file
  51.  
  52. In either case, the first argument to the ADDRESS instruction
  53. identifies the application to which commands are to be sent.
  54. The argument is the name of a public message port which the
  55. application has created, often referred to as an "ARexx port".
  56. ARexx sends the command string to this port and waits for
  57. a reply.  The reply sets the RC variable (an integer return code)
  58. and in some cases the RESULT variable (a result string).
  59.  
  60. The messages that are passed between an ARexx program and
  61. a command host is a special structure based on an Exec Message
  62. and known as a RexxMsg.  A RexxMsg includes space for a
  63. command string, action flags, and results.  (The same structure
  64. is used to send messages to function hosts, though the fields
  65. in the structure are used a bit differently.)
  66.  
  67. An ARexx function library is a shared library (typically written
  68. in C or in assembler) that adds new functions to ARexx.  Like
  69. function hosts, function libraries are added to ARexx's Library List.
  70. When an ARexx program calls a function that is neither internal
  71. to the program or built-in to ARexx, ARexx will search through
  72. the entries in the Library List (ordered by priority) and ask
  73. each function library or function host if it supports the function.
  74. ARexx does this for function hosts by sending a message to an
  75. ARexx port.  No message-passing is involved with function libraries:
  76. ARexx loads the library into memory and calls it directly.
  77.  
  78.  
  79.  
  80. ARexx IPC Support
  81.  
  82. We can't implement a command host without routines for
  83. interprocess communication (IPC) --- creating an ARexx port,
  84. sending messages, and receiving messages.  Sending messages
  85. is easily done via the ADDRESS instruction.  Managing
  86. an ARexx port is done using routines from the ARexx support
  87. library, a function library that comes with ARexx.  To
  88. use functions from the support library, make sure the
  89. rexxsupport.library file exists in your LIBS: directory.
  90. Then execute the following statement from the CLI command line:
  91.  
  92.     rxlib rexxsupport.library 0 -30 0
  93.  
  94. Alternatively, you could place the following code at the
  95. beginning of any program that uses the support library:
  96.  
  97.     if( ~show( 'l', "rexxsupport.library" ) )then do
  98.         if( ~addlib( "rexxsupport.library", 0, -30, 0 ) )then do
  99.             say "Could not open rexxsupport.library"
  100.             exit 10
  101.         end
  102.     end
  103.  
  104. Both of these methods add the support library to ARexx's Library
  105. List, and if you use the support library very often you'll
  106. probably want to add the rxlib call to your Amiga's startup-sequence
  107. file.
  108.  
  109. Once the support library is installed, creating an ARexx port is
  110. simply a matter of calling the OpenPort() function with the name
  111. of the port as the first argument:
  112.  
  113.     if( OpenPort( "MYPORT" ) = Null() )then do
  114.         say "Could not open message port!"
  115.         exit 10
  116.     end
  117.  
  118. OpenPort() returns the address of the message port.  Compare
  119. the address to the value returned by the Null() function to make
  120. sure a message port was indeed created.  Port names are case-sensitive.
  121. Command hosts should always use uppercase letters in their port names.
  122.  
  123. Addresses in ARexx are four-byte strings that correspond to
  124. a C pointer.  These addresses aren't meant to be printed directly.
  125. Use one of the functions C2B(), C2D() or C2X() to print the values.
  126. For example, the line
  127.  
  128.     say c2x( Null() )
  129.  
  130. would print the string '0000 0000', which is what Null() always
  131. returns.
  132.  
  133. When you're done with a message port, use the ClosePort() function
  134. to delete it, passing the name of the port as the only argument:
  135.  
  136.     call ClosePort "MYPORT"
  137.  
  138. ARexx will automatically close all open ports when the program
  139. terminates, but it's a good habit to do it yourself.
  140.  
  141. You can check to see if a message packet has arrived at your port by
  142. using the GetPkt() function:
  143.  
  144.     packet = GetPkt( "MYPORT" )
  145.  
  146. If a packet has arrived, it is retrieved from the port and its
  147. address is returned.  If no messages are waiting, GetPkt() returns
  148. a null address and will compare true with Null().
  149.  
  150. If you want to simply wait for a message to arrive at your message
  151. port, use the WaitPkt() function:
  152.  
  153.     call WaitPkt "MYPORT"
  154.  
  155. The ARexx program will be suspended until one or more messages
  156. arrive.  Use the GetPkt() function as described above to retrieve
  157. the messages.
  158.  
  159. The strings in a packet can be accessed using the GetArg() function.
  160. A RexxMsg packet has sixteen slots for storing strings, numbered 0 to 15.
  161. The command string is always stored in slot 0:
  162.  
  163.     command = GetArg( packet, 0 )
  164.  
  165. You can ignore the other slots, since ARexx doesn't parse command
  166. strings for you --- that's up to you.
  167.  
  168. When you're done with a packet, you should reply to the sender
  169. of the packet with a return code and possibly a result string.
  170. The support library includes a Reply() function, but it only allows
  171. the return code to be set.  If we want to send a result string
  172. back we need a more flexible function, and that's where the
  173. RexxHS library comes in.
  174.  
  175.  
  176.  
  177. The RexxHS Library
  178.  
  179. The RexxHS (Rexx Host Support) library is a small function library
  180. you'll find on the diskette.  Copy the rexxhs.library file to your
  181. LIBS: directory and then add it to the Library List:
  182.  
  183.     rxlib rexxhs.library 0 -30 0
  184.  
  185. The RexxHS library adds four new functions to ARexx.  The first
  186. three take a message packet address as their only argument.  The
  187. ValidPkt() function returns 1 if the address is a valid RexxMsg
  188. structure (that is, it was received by GetPkt() but not yet
  189. replied to) and 0 otherwise.  The IsFunctionCall() function
  190. returns 1 if a message packet is a function call, 0 otherwise.
  191. The NumArgs() function returns the number of arguments
  192. (strings stored in slots 1 to 15) in a packet, 0 if there are
  193. no arguments.  An ARexx command string has no arguments.
  194.  
  195. The fourth function, ReplyToCall(), is a replacement for the
  196. Reply() function.  It replies to a packet but lets the user
  197. set a result string as well as a return code:
  198.  
  199.     call ReplyToCall packet, 0, "a result string"
  200.  
  201. The return code must be an integer.  The result string will only
  202. be sent back if the return code is zero (no error) and
  203. the calling ARexx program requested a result string by using
  204. the OPTIONS RESULTS instruction before making the call.
  205. If the return code is non-zero, the third argument can
  206. be omitted, but if present it must be an integer and
  207. will be stored in the secondary result field of the packet.
  208.  
  209. Building an ARexx function library isn't a simple task and
  210. is beyond the scope of this article.  Full source code to
  211. the RexxHS library (for both the Manx and SAS C compilers)
  212. can be found on the disk.
  213.  
  214.  
  215.  
  216. A Sample Command Host
  217.  
  218. We now have all the tools we need to write a command host
  219. in ARexx.  Most command hosts are real applications written
  220. in some other language and are there to provide access to
  221. the features of those applications, usually via short
  222. ARexx macros.  Our sample host is a bit unusual and doesn't
  223. do anything practical, but it illustrates the concepts very
  224. nicely.
  225.  
  226. Run the sample host by copying the samplehost.rexx file
  227. from the diskette into your REXX: directory and typing
  228.  
  229.         run rx samplehost
  230.  
  231. A startup message will be printed and the host will inform
  232. you that it is waiting for messages.  You can send it any
  233. message you want by sending a message to the SAMPLEHOST
  234. ARexx port.  From the CLI you could type:
  235.  
  236.         rx "address samplehost 'hello there'"
  237.  
  238. The sample host works like this:  it waits for a packet to
  239. arrive, retrieves it, retrieves the command string,
  240. parses the command string, acts on the command, then replies
  241. to the packet.  The sample host is dumb --- if it doesn't understand your
  242. command it just prints it to the screen.  But it does accept
  243. commands to set and get return codes and result strings --- see
  244. the file samplecalls.rexx for examples.  To tell the sample host
  245. to quit, just send it an exit command:
  246.  
  247.         rx "address samplehost 'exit'"
  248.  
  249. Commands are not case-sensitive.
  250.  
  251.  
  252.  
  253. A Function Host
  254.  
  255. The samplehost.rexx program can also act as a function host, though
  256. you should do this only as an experiment to familiarize yourself
  257. with function hosts.  In particular, you must make sure that
  258. the sample host is added to the Library List at a lower priority
  259. than any of the other libraries it uses, otherwise a deadlock
  260. situation could occur --- see the documentation on diskette for
  261. an explanation.
  262.  
  263.  
  264.  
  265. Final Comments
  266.  
  267. See how easy it is to write a command host?  Even in C it's fairly
  268. straightforward if you use a package like Mike Sinz's SimpleRexx
  269. to send and receive ARexx messages.  The hard part is deciding what
  270. commands to support and what their format should be --- consult the Amiga
  271. User Interface Style Guide for some recommendations.
  272.  
  273.