home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 14 Text / 14-Text.zip / rexxpg.zip / REXXPG.INF (.txt)
OS/2 Help File  |  1997-08-12  |  306KB  |  9,543 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. About This Information ΓòÉΓòÉΓòÉ
  3.  
  4. The Object REXX Programming Guide describes the Object-based REstructured 
  5. eXtended eXecutor, or Object REXX programming language. (When not comparing it 
  6. to its traditional predecessor, we just call it REXX.) REXX is an integral part 
  7. of IBM Operating System/2 (OS/2). 
  8.  
  9. This information is aimed at developers familiar with OS/2 who want to use REXX 
  10. to do object-oriented programming--or some mix of traditional and 
  11. object-oriented programming--with the shortest learning curve possible. 
  12.  
  13. This information assumes you are already familiar with the techniques of 
  14. traditional structured programming, and uses them as a springboard for quickly 
  15. understanding REXX and, in particular, Object REXX. This "no frills" approach 
  16. is designed to help experienced programmers get involved quickly with the REXX 
  17. language, exploit its virtues, and become productive fast. 
  18.  
  19.  
  20. ΓòÉΓòÉΓòÉ 1.1. What You Should Know before Reading This Information ΓòÉΓòÉΓòÉ
  21.  
  22. To most effectively use this information, you should know: 
  23.  
  24.      How to program with a traditional language like C, Basic, or Pascal 
  25.      How to use basic OS/2 commands for manipulating files, such as COPY, 
  26.       DELETE, DIR, and so on; of course, the more familiar you are with OS/2, 
  27.       the better 
  28.  
  29.  You should also have the Object REXX Reference on hand. 
  30.  
  31.  
  32. ΓòÉΓòÉΓòÉ 1.2. Who Should Read This Information ΓòÉΓòÉΓòÉ
  33.  
  34. Anyone interested in getting a basic understanding of object-oriented concepts 
  35. should read this information. Using this information, experienced programmers 
  36. can learn about the REXX language and how it is like and unlike other 
  37. structured programming languages. Programmers who want to broaden their 
  38. programming knowledge can learn object-oriented programming with REXX. Users 
  39. already experienced with REXX can learn about object-oriented programming (OO) 
  40. in general, and OO programming with REXX in particular. 
  41.  
  42. Programmers who want to make their applications (typically coded in C) 
  43. scriptable by REXX, extend the REXX language, or control REXX scripts from 
  44. other applications should consult the application programming interface (API) 
  45. information in the appendixes presented here. For those who want to control 
  46. REXX from OS/2 applications, additional information on the OSA Scripting 
  47. Components API is available in the OSA Guide and Reference. 
  48.  
  49.  
  50. ΓòÉΓòÉΓòÉ 2. Meet Object REXX ΓòÉΓòÉΓòÉ
  51.  
  52. If you already know how to write conventional programs in a high-level language 
  53. like Basic, C, or Pascal, the following information could be for you. Maybe you 
  54. are familiar with REXX, maybe not. Maybe you have done some object-oriented 
  55. programming and maybe you haven't. But if you want to learn more about 
  56. object-oriented (OO) programming using one of the simplest, most powerful, most 
  57. popular languages ever made available, you have come to the right place. 
  58.  
  59.  
  60. ΓòÉΓòÉΓòÉ 2.1. A Language with Something for Everyone ΓòÉΓòÉΓòÉ
  61.  
  62. It's easy to get excited about REXX. REXX is a versatile, free-format language 
  63. that is an integral part of the OS/2 operating system. Its simplicity makes it 
  64. a good first language for beginners. For more experienced users and computer 
  65. professionals, REXX offers powerful functions and the ability to issue commands 
  66. to multiple environments. 
  67.  
  68.  
  69. ΓòÉΓòÉΓòÉ 2.1.1. The Main Attractions ΓòÉΓòÉΓòÉ
  70.  
  71. The following aspects of REXX round out its versatility and function. 
  72.  
  73.  
  74. ΓòÉΓòÉΓòÉ 2.1.1.1. Object-Oriented Programming ΓòÉΓòÉΓòÉ
  75.  
  76. Object-oriented extensions have been added to traditional REXX, but its 
  77. existing functions and instructions have not changed. The Object REXX 
  78. interpreter is actually an enhanced version of its predecessor, but with new 
  79. support for: 
  80.  
  81.      Classes, objects, and methods 
  82.      Messaging and polymorphism 
  83.      Inheritance and multiple inheritance 
  84.      CORBA-compliant access to OS/2 System Object Model (SOM) objects (CORBA 
  85.       is the Common Object Request Broker Architecture) 
  86.  
  87.  Object REXX supplies the user with a base set of classes. These are ALARM, 
  88.  CLASS, ARRAY, LIST, QUEUE, TABLE, SET, DIRECTORY, RELATION, BAG, MESSAGE, 
  89.  METHOD, MONITOR, STEM, STREAM, STRING, and SUPPLIER. Object REXX is fully 
  90.  compatible with earlier versions of REXX that were not object-based. 
  91.  
  92.  
  93. ΓòÉΓòÉΓòÉ 2.1.1.2. An English-like Language ΓòÉΓòÉΓòÉ
  94.  
  95. To make REXX easier to learn and use, many of its instructions are meaningful 
  96. English words. Unlike some programming languages that use abbreviations, REXX 
  97. instructions are common words such as SAY, PULL, IF...THEN...ELSE, DO...END, 
  98. and EXIT. 
  99.  
  100.  
  101. ΓòÉΓòÉΓòÉ 2.1.1.3. Fewer Rules ΓòÉΓòÉΓòÉ
  102.  
  103. REXX has relatively few rules about format. A single instruction can span many 
  104. lines, and you can include multiple instructions on a single line. Instructions 
  105. need not begin in a particular column and you can type them in uppercase, 
  106. lowercase, or mixed case. You can skip spaces in a line or entire lines. There 
  107. is no line numbering. 
  108.  
  109.  
  110. ΓòÉΓòÉΓòÉ 2.1.1.4. Interpreted, Not Compiled ΓòÉΓòÉΓòÉ
  111.  
  112. REXX is an interpreted language. When a REXX program runs, its language 
  113. processor reads each statement from the source file and runs it, one statement 
  114. at a time. Languages that are not interpreted must be compiled into object code 
  115. before they can be run. 
  116.  
  117.  
  118. ΓòÉΓòÉΓòÉ 2.1.1.5. Built-In Functions and Methods ΓòÉΓòÉΓòÉ
  119.  
  120. REXX has built-in functions and methods that perform various processing, 
  121. searching, and comparison operations for text and numbers and provide 
  122. formatting capabilities and arithmetic calculations. 
  123.  
  124.  
  125. ΓòÉΓòÉΓòÉ 2.1.1.6. Typeless Variables ΓòÉΓòÉΓòÉ
  126.  
  127. REXX regards all data as objects of various kinds. Variables can hold any kind 
  128. of object, so you need not declare variables as strings or as numbers. 
  129.  
  130.  
  131. ΓòÉΓòÉΓòÉ 2.1.1.7. String Handling ΓòÉΓòÉΓòÉ
  132.  
  133. REXX includes capabilities for manipulating character strings. This allows 
  134. programs to read and separate characters, numbers, and mixed input. REXX 
  135. performs arithmetic operations on any string that represents a valid number, 
  136. including those in exponential formats. 
  137.  
  138.  
  139. ΓòÉΓòÉΓòÉ 2.1.1.8. Clear Error Messages and Powerful Debugging ΓòÉΓòÉΓòÉ
  140.  
  141. REXX displays messages with meaningful explanations when a REXX program 
  142. encounters an error. In addition, the TRACE instruction provides a powerful 
  143. debugging tool. 
  144.  
  145.  
  146. ΓòÉΓòÉΓòÉ 2.1.2. REXX and the OS/2 Operating System ΓòÉΓòÉΓòÉ
  147.  
  148. The most vital role REXX plays is as a programming language for OS/2. A REXX 
  149. program can serve as a script for the OS/2 operating system to follow. Using 
  150. REXX, you can reduce long, complex, or repetitious tasks to a single command or 
  151. program. 
  152.  
  153. REXX is a built-in feature of OS/2, so programs are run directly from a 
  154. windowed or full-screen command prompt. There is no installation process or 
  155. separate environment. You can run a REXX program anywhere that you can use an 
  156. OS/2 command or batch file. 
  157.  
  158.  
  159. ΓòÉΓòÉΓòÉ 2.2. A Classic Language Gets Classier ΓòÉΓòÉΓòÉ
  160.  
  161. Object-oriented extensions have been added to traditional REXX without changing 
  162. its existing functions and instructions. So you can continue to use REXX's 
  163. procedural instructions, and incorporate objects as you become more comfortable 
  164. with the technology. In general, your current REXX programs will work without 
  165. change. But because Object REXX catches more errors at translate time than 
  166. traditional REXX, you may have to fix these. 
  167.  
  168. In object-oriented technology, objects are used in programs to model the real 
  169. world. Similar objects are grouped into classes, and the classes themselves are 
  170. arranged in hierarchies. 
  171.  
  172. As an object-oriented programmer, you solve problems by identifying and 
  173. classifying objects related to the problem. Then you determine what actions or 
  174. behaviors will be required of those objects. Finally, you write the 
  175. instructions to generate the classes, create the objects, and implement the 
  176. actions. Your main program consists of instructions that send messages to 
  177. objects. 
  178.  
  179. A billing application, for example, might have an Invoice class and a Receipt 
  180. class. These two classes might be members of a Forms class. Individual invoices 
  181. are objects that are instances of the Invoice class. 
  182.  
  183.  
  184. Objects in a billing application
  185.  
  186.  
  187.                 Forms class
  188.                    Γöé
  189.            ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  190.            Γöé                Γöé
  191.         Invoice class          Receipt class
  192.  
  193.         invoice #1343
  194.         invoice #1344
  195.         invoice #1345
  196.  
  197. Each instance contains all the data associated with it (such as customer name, 
  198. descriptions and prices of items purchased, and so on). To get at the data, you 
  199. write instructions that send messages to the objects. These messages activate 
  200. coded actions called methods. For an invoice object, you might want CREATE, 
  201. DISPLAY, PRINT, UPDATE, and ERASE methods. 
  202.  
  203.  
  204. ΓòÉΓòÉΓòÉ 2.2.1. From Traditional REXX to Object REXX ΓòÉΓòÉΓòÉ
  205.  
  206. How was it possible to add object-orientation to traditional REXX while 
  207. maintaining compatibility? The trick was in the handling of variables. In 
  208. traditional (or "classic") REXX, all data was stored as strings. The strings 
  209. represented character data as well as numeric data. From an object-oriented 
  210. perspective, we might say that traditional REXX had one kind of objects: 
  211. strings. In object-oriented terminology, each string variable was an object 
  212. that was an instance of the String class. 
  213.  
  214. We changed REXX so that variables could reference objects other than strings. 
  215. In addition to a string class, REXX now includes classes for creating arrays, 
  216. queues, streams, and many others useful objects. Objects in these new REXX 
  217. classes are manipulated by methods instead of traditional functions. To 
  218. activate a method, you just send the object a message. 
  219.  
  220. For example, instead of using the SUBSTR function on a string variable Name, 
  221. you send a SUBSTR message to the string object. Here is the old way: 
  222.  
  223. s=substr(name,2,3)
  224.  
  225. And here is the new way: 
  226.  
  227. s=name~substr(2,3)
  228.  
  229. The tilde (~) character is the REXX message send operator. We call it the 
  230. twiddle. The object receiving the message is to the left of the twiddle. The 
  231. message is to the right. In this example, the Name object is sent the SUBSTR 
  232. message. The numbers in parentheses (2,3) are arguments sent as part of the 
  233. message. The SUBSTR method is run for the Name object, and the result is 
  234. assigned to the s string object. 
  235.  
  236. For the new classes (array, queue, and so on), methods are provided, but not 
  237. equivalent functions. For example, suppose you want to use the new REXX array 
  238. object instead of the traditional string-based stem variables (such as text.1, 
  239. text.2, and so on). To create an array object of five elements, you would send 
  240. a NEW message to the array class as follows: 
  241.  
  242. myarray=.array~new(5)
  243.  
  244. A new instance, named Myarray, of the Array class is created. (A period 
  245. precedes a built-in class name in an expression, so .ARRAY is correct, not just 
  246. ARRAY.) The Myarray array object has five elements. Some of the other methods, 
  247. besides NEW, for array objects are PUT, AT, REMOVE, SIZE, [], and []=. 
  248.  
  249. By adding object technology to its repertoire of traditional programming 
  250. techniques, REXX has evolved into an object-oriented language, like Smalltalk. 
  251. Object REXX accommodates the programming techniques of traditional REXX while 
  252. adding new ones. With Object REXX, you can use the new technology as much or as 
  253. little as you like, at whatever pace you like. You can use classic and object 
  254. techniques together. You can ease into the object world gradually, building on 
  255. the REXX skills and knowledge you already have. 
  256.  
  257.  
  258. ΓòÉΓòÉΓòÉ 2.3. The Object Advantage ΓòÉΓòÉΓòÉ
  259.  
  260. If you are unsure about whether to employ REXX's object-oriented features, here 
  261. are some tips to help you decide. 
  262.  
  263. Object-oriented technology reinforces sound programming practices: hide your 
  264. data from code that doesn't have to use it (encapsulation and polymorphism); 
  265. partition your program in small, manageable units (classification and data 
  266. abstraction); reuse code wherever possible and change it in one place 
  267. (inheritance and functional decomposition), and so on. 
  268.  
  269. Other advantages often associated with object technology are: 
  270.  
  271.      Simplified design through modeling with objects 
  272.      Greater code reuse 
  273.      Rapid prototyping 
  274.      The higher quality of proven components 
  275.      Easier and reduced maintenance 
  276.      Cost-savings potential 
  277.      Increased adaptability and scalability 
  278.  
  279.  Of course, with Object REXX in particular you get REXX usability in an 
  280.  object-oriented language. You also get access to SOM technologies and 
  281.  frameworks like the OS/2 Workplace Shell, IBM Multimedia Presentation Manager, 
  282.  the OpenDoc architecture, and objects written in other SOM-enabled languages. 
  283.  
  284.  If you want to import or use OS/2 SOM objects, import or extensively 
  285.  manipulate the OS/2 Workplace Shell (manipulations of a subset of objects can 
  286.  be accomplished procedurally using REXX utilities), script OpenDoc parts, or 
  287.  create composite applications from REXX-enabled programs, Object REXX is a 
  288.  good way to go. It's a state-of-the-art scripting language. And OS/2 TCP/IP 
  289.  now provides an OS/2 Sockets API and an OS/2 FTP API for REXX, so you can 
  290.  script Object REXX clients and servers, and even run them on the Internet. If 
  291.  you've been waiting to test the waters of object-oriented programming, there 
  292.  couldn't be a better time or more accommodating language. 
  293.  
  294.  
  295. ΓòÉΓòÉΓòÉ 2.4. The Next Step ΓòÉΓòÉΓòÉ
  296.  
  297. If you already know traditional REXX and want to go straight to the basic 
  298. concepts of object-oriented programming, jump to Into the Object World. 
  299.  
  300. If you are unfamiliar with traditional REXX, continue on to A Quick Tour of 
  301. Traditional REXX. 
  302.  
  303.  
  304. ΓòÉΓòÉΓòÉ 3. A Quick Tour of Traditional REXX ΓòÉΓòÉΓòÉ
  305.  
  306. Because this guide is for OS/2 programmers, we expect you are already familiar 
  307. with the programming techniques of at least one other language. To speed up 
  308. your involvement with REXX, this section will quickly cover the basic rules and 
  309. show you how REXX is like or unlike other languages you may already know. The 
  310. idea is to help you assimilate REXX more quickly and make you productive fast. 
  311.  
  312. If more detail is what you want, consult the Object REXX Reference. It contains 
  313. a full description of the REXX language. You may want to keep a copy nearby or 
  314. online to look up any instruction or function not completely defined here. 
  315. Think of the Object REXX Reference as a "technical dictionary for REXX" and 
  316. this guide as "a get-you-going digest of REXX rules, key OO concepts, 
  317. programming approaches, and examples." 
  318.  
  319.  
  320. ΓòÉΓòÉΓòÉ 3.1. What Is a REXX Program? ΓòÉΓòÉΓòÉ
  321.  
  322. A REXX program is a text file, typically created using a text editor or word 
  323. processor, that contains a list of instructions for your computer. REXX 
  324. programs on OS/2 are interpreted, which means the program is processed line by 
  325. line (like a batch file). Consequently, you don't need to compile and link REXX 
  326. programs. To run a REXX program, all you need is OS/2 and the ASCII text file 
  327. containing the program. 
  328.  
  329. If you are familiar with programming languages such as C, Pascal, or Basic, you 
  330. will find that REXX is similar. An important difference is that REXX variables 
  331. have no data type and are not declared. Instead, REXX determines from context 
  332. whether the variable is a string, for instance, or a number. Moreover, a 
  333. variable that was treated as a number in one instruction can be treated as a 
  334. string in the next. 
  335.  
  336. REXX's flexibility in variable handling makes it easy for you to write programs 
  337. quickly. Much of the boiler-plate instructions found in other languages is not 
  338. needed. REXX keeps track of variables for you. It allocates and deallocates 
  339. memory as necessary. 
  340.  
  341. Another important difference is that you can execute OS/2 commands and other 
  342. applications from a REXX program. This is similar to what you can do with an 
  343. OS/2 Batch facility program. REXX, however, provides a more robust interface. 
  344. Not only can you execute the command, you can also receive a return code from 
  345. the command and use any displayed output in your REXX program. (The output 
  346. normally displayed by a DIR command, for example, can be intercepted by a REXX 
  347. program and used in subsequent processing.) 
  348.  
  349. In addition, REXX can direct commands to environments other than the OS/2 
  350. operating system. Some applications provide an environment to which REXX can 
  351. direct subcommands of the application. Some applications also provide functions 
  352. that can be called from a REXX program. In these situations, REXX acts as a 
  353. macro language for the application. The OS/2 Enhanced Editor is an example of 
  354. an application that supports the use of REXX as a macro language. 
  355.  
  356.  
  357. ΓòÉΓòÉΓòÉ 3.2. Running a REXX Program ΓòÉΓòÉΓòÉ
  358.  
  359. REXX programs on OS/2 should have a file extension of CMD, just like Batch 
  360. facility files. Here is a typical REXX program named GREETING.CMD. It prompts 
  361. the user to type in a name and then displays a personalized greeting: 
  362.  
  363. /* GREETING.CMD -- a REXX program to display a greeting. */
  364. say 'Please enter your name.'    /* Display a message    */
  365. pull name                        /* Read response        */
  366. say 'Hello' name                 /* Display greeting     */
  367. exit 0                   /* Exit with a return code of 0 */
  368.  
  369. Notice that the program begins with a comment. In OS/2, the first line of a 
  370. REXX program must start with a comment in column 1. If you omit the comment, 
  371. OS/2 thinks the program is a Batch facility program, and will try to run it as 
  372. such. Naturally, all sorts of errors will result. 
  373.  
  374. SAY is a REXX instruction that displays a message (like PRINT in Basic or 
  375. printf in C). The message to be displayed follows the SAY keyword. The single 
  376. quotes are necessary to delimit a character string. In this case, the character 
  377. string is Please enter your name. You can use double quotes (") instead of 
  378. single quotes if you wish. 
  379.  
  380. The PULL instruction reads a line of text from the standard input (the 
  381. keyboard), and returns the text in the variable specified on the instruction. 
  382. In our example, the text is returned in the variable name. 
  383.  
  384. The next SAY instruction provides a glimpse of what can be done with REXX 
  385. strings. It displays the word "Hello" followed by the name of the user, which 
  386. is stored in variable name. REXX substitutes the value of name in the 
  387. expression and displays the resulting string. You do not need a separate format 
  388. string as you do with C or Basic. 
  389.  
  390. The final instruction, EXIT, ends the REXX program. Control returns to OS/2. 
  391. EXIT can also return a value. In our example, zero is returned. The EXIT 
  392. instruction is optional. 
  393.  
  394. You run a REXX program just as you would run a Batch facility program. Type the 
  395. file name of the program at an OS/2 command prompt. OS/2 follows its usual 
  396. search rules when trying to find the program. That is, OS/2 looks for the 
  397. program in the current directory. If OS/2 cannot find the command, it searches 
  398. the directories listed in the PATH environment variable. 
  399.  
  400. You can stop a REXX program by pressing the Control (Ctrl)+Break keys. REXX 
  401. stops running the program and control returns to OS/2. 
  402.  
  403.  
  404. ΓòÉΓòÉΓòÉ 3.3. Elements of REXX ΓòÉΓòÉΓòÉ
  405.  
  406. REXX programs are made up of clauses. Each clause is a complete REXX 
  407. instruction. 
  408.  
  409. REXX instructions include the obligatory program control verbs (IF, SELECT, DO, 
  410. CALL, RETURN) as well as some verbs that are unique to REXX (such as PARSE, 
  411. GUARD, and EXPOSE). In all, there are about 30 instructions. Many REXX programs 
  412. use only a small subset of the instructions. 
  413.  
  414. Complementing the instruction set is wide variety of built-in functions (over 
  415. 75 of them). Many functions manipulate strings (SUBSTR, WORDS, POS, SUBWORD, 
  416. and more). Other functions perform stream I/O (CHARIN, CHAROUT, LINEIN, 
  417. LINEOUT, and more). Still other functions perform data conversion (X2B, X2C, 
  418. D2X, C2D, and more). A quick glance through the functions section of the Object 
  419. REXX Reference will give you an idea of the scope of capabilities available to 
  420. you. 
  421.  
  422. The functions that are built into the REXX language are available in REXX 
  423. implementations on other operating systems. In addition to these 
  424. system-independent functions, REXX on OS/2 includes a set of functions for 
  425. working with OS/2 itself. These functions, known as the REXX Utilities, let you 
  426. work with resources managed by OS/2, such as the display, the Workplace 
  427. desktop, and the file system. 
  428.  
  429. Instructions and functions are the building blocks of traditional REXX 
  430. programs. To convert REXX into an object-oriented language, two more elements 
  431. were needed: classes and methods. Classes and methods are covered in later 
  432. sections. In the rest of this section we'll look at the traditional building 
  433. blocks of REXX. 
  434.  
  435.  
  436. ΓòÉΓòÉΓòÉ 3.4. Writing Your Program ΓòÉΓòÉΓòÉ
  437.  
  438. You can create REXX programs using any editor that can write straight ASCII 
  439. files without hidden format controls. The OS/2 system editor or the Enhanced 
  440. Editor are two editors that you can use. 
  441.  
  442. REXX is a free-format programming language. You can indent lines and insert 
  443. blank lines for readability if you wish. But even free-format languages have 
  444. some rules about how language elements are used. REXX's rules center around 
  445. it's basic language element: the clause. 
  446.  
  447. Usually, there is one clause on each line of the program, but you can put 
  448. several on a line if you wish. Just separate each clause with a semicolon (;): 
  449.  
  450. say "Hello"; say "Goodbye"  /* Two clauses on one line */
  451.  
  452. To continue a clause on a second line, put a comma at the end of the line: 
  453.  
  454. say,             /* Continuation */
  455. "It isn't so"
  456.  
  457. If you need to continue a literal string, do it like this: 
  458.  
  459. say,                /* Continuation of literal strings */
  460. "This is a long string that we want to continue",
  461. "on another line."
  462.  
  463. You'll notice that we broke the string at a convenient place (where a blank was 
  464. expected). REXX automatically adds a blank. If you need to split a string, but 
  465. don't want to have a blank inserted when REXX puts the string back together, 
  466. use the REXX concatenation operator (||): 
  467.  
  468. say 'I do not want REXX to in'||,   /* Continuation with concatenation */
  469. 'sert a blank!'
  470.  
  471.  
  472. ΓòÉΓòÉΓòÉ 3.5. Testing Your Program ΓòÉΓòÉΓòÉ
  473.  
  474. When writing your program, you can conveniently test statements as you go along 
  475. using the REXXTRY command from the OS/2 command prompt. REXXTRY is a kind of 
  476. REXX mini-interpreter that checks REXX statements one at a time. If you run it 
  477. with no parameter, or with a question mark as a parameter, REXXTRY will also 
  478. briefly describe itself. 
  479.  
  480. From your current OS/2 window, just open another window and from the command 
  481. prompt type: 
  482.  
  483. rexxtry
  484.  
  485. REXXTRY will describe itself and ask you for a REXX statement to test. Enter 
  486. your statement; REXXTRY will run it and return any information, or display an 
  487. error message if a problem is encountered. REXXTRY remembers any previous 
  488. statements you have entered during the session, so to continue just type the 
  489. next line in your program and REXXTRY will check it for you. 
  490.  
  491. Enter an equal sign (=) to repeat your previous statement, or a question mark 
  492. (?) to invoke system-provided online information about the REXX language. 
  493.  
  494. When you're done, type: 
  495.  
  496. exit
  497.  
  498. and press Enter to leave REXXTRY. 
  499.  
  500. You can also enter a REXX statement directly on the command line for immediate 
  501. processing and exit: 
  502.  
  503. rexxtry call show
  504.  
  505. In this case, entering CALL SHOW displays the user variables provided by 
  506. REXXTRY. 
  507.  
  508. Whereas REXXTRY runs and debugs one REXX statement at a time, you can use 
  509. PMREXX to do the same for an entire REXX procedure. PMREXX is a windowed 
  510. application that shows, in a PMREXX window, any results displayed by your REXX 
  511. procedure. You can scroll through the window using its scroll bar to view all 
  512. the output. 
  513.  
  514. PMREXX also provides a single line input field, so that you can supply input to 
  515. the REXX procedure or to any commands called by it. 
  516.  
  517. PMREXX is an OS/2 installation option; it is available if you select it during 
  518. OS/2 installation. Assuming you've done this and PMREXX is available, you start 
  519. it by entering PMREXX from an OS/2 command prompt, followed by the name of a 
  520. REXX procedure you want to run; for example: 
  521.  
  522. pmrexx myprog
  523.  
  524. You can also supply arguments for the REXX procedure. In the next example, 
  525. PMREXX will run the procedure MYPROG and pass MYPROG the argument 
  526. c:\test\test.data: 
  527.  
  528. pmrexx myprog c:\test\test.data
  529.  
  530. PMREXX will run the REXX procedure and display any output generated by it in a 
  531. scrollable output box that is part of the PMREXX window. If the procedure 
  532. prompts for input, the prompt is displayed in the output box. You would then 
  533. type the response in the smaller input box near the top of the PMREXX window. 
  534.  
  535. To try it, start an OS/2 session and create this REXX procedure: 
  536.  
  537. /* DIRTEST.CMD -- displays directory contents */
  538. do forever
  539.    say 'Enter the name of a directory'
  540.    parse upper pull response
  541.    if response='QUIT' then leave
  542.    'dir' response
  543. end
  544. exit
  545.  
  546. Then start PMREXX again for the DIRTEST procedure: 
  547.  
  548. pmrexx dirtest
  549.  
  550. When the PMREXX window is displayed, you'll see the prompt in the output box. 
  551. Position the cursor in the input box, type the name of a directory, and press 
  552. Enter. The contents of the directory will be listed in the output box, and 
  553. another prompt will be displayed. 
  554.  
  555. When the amount of displayed output exceeds the size of the output box, a 
  556. slider box appears in the scroll bar. 
  557.  
  558. To end the DIRTEST program, type: 
  559.  
  560. quit
  561.  
  562. in the input box and press Enter. 
  563.  
  564. When you run your REXX programs with PMREXX, you can use a function called 
  565. RxMessageBox to display messages. This example uses it to display an error 
  566. message: 
  567.  
  568. /* ERROR.CMD -- Check the input parameter */
  569. arg count
  570. if count~datatype('Whole') <> 0 then do
  571.   RxMessageBox("Argument" count "is not a whole number")
  572.   exit
  573. end
  574.  
  575. RxMessageBox displays a Presentation Manager message box titled Error! and an 
  576. OK button. The REXX program waits until you click OK. 
  577.  
  578. You can change the message box title and buttons, and add a colorful icon to 
  579. the message box: 
  580.  
  581. /* FILECHK.CMD -- Does the file exist? */
  582. if file~Query('Exists') <> ''
  583.   then do
  584.     reply = RxMessageBox("Do you want to replace file",,
  585.         "Replace File?", "YesNo", "Question")
  586.     if reply = 7 then exit         /* user pressed 'No' */
  587.   end
  588.  
  589. FILECHK.CMD displays a question in a message box with a question-mark icon and 
  590. two buttons, labeled Yes and No. Clicking Yes or No gives your program the 
  591. number of the button you chose. (Yes is 6 and No is 7.) 
  592.  
  593. To use PMREXX as a miniature development environment for your procedures, run 
  594. PMREXX in one OS/2 session and an editor in another session. Use the editor to 
  595. change and save the procedure being developed. Then switch to the PMREXX 
  596. session to run the modified procedure. 
  597.  
  598. You can restart a procedure from PMREXX by selecting Trace from the action bar 
  599. in the PMREXX window. If the procedure is running, select Halt procedure to 
  600. stop it, then select Restart from the menu. Otherwise, just select Restart. The 
  601. latest version of the procedure will run again. 
  602.  
  603. PMREXX includes several functions useful for debugging your procedures. You 
  604. can, for instance, start an interactive trace from PMREXX without having to add 
  605. a TRACE instruction to your procedure. Select Trace on the action bar, and then 
  606. select Interactive trace on. A check mark on the menu shows that interactive 
  607. tracing is on. To stop the interactive trace, just select Interactive trace on 
  608. again. One advantage of using the interactive trace from PMREXX is that you can 
  609. turn the trace on and off while the program is running. 
  610.  
  611. Once tracing is active, you can step through your procedure one clause at a 
  612. time, re-do a clause that was just processed, or enter a line of REXX clauses 
  613. for immediate processing. The ability to enter REXX clauses is especially 
  614. useful if you want to try a fix to a problem interactively or if you want to 
  615. test instruction paths that are otherwise difficult to trigger. 
  616.  
  617. For example, you might want to test some error handling instructions, but 
  618. cannot easily create the condition that would cause the error. By using the 
  619. interactive trace, you can add REXX instructions at the right moment to fake 
  620. the conditions that would cause the error handling instructions to be 
  621. processed. 
  622.  
  623. To process a line of one or more REXX clauses, type the line in the PMREXX 
  624. input box when tracing is active and press Enter. For example, you could enter: 
  625.  
  626. do i=1 to 10; say 'hello' i; end
  627.  
  628. The line is processed before the next REXX clause in the program is processed. 
  629. If you simply want to step ahead to the next clause, press Enter without typing 
  630. anything in the input area. You can also step ahead by selecting Trace next 
  631. clause from the Trace menu. If you want to process the last REXX clause again, 
  632. select Re-do last clause from the Trace menu. 
  633.  
  634. To stop tracing, select Trace off from the Trace menu. This item is not 
  635. selectable when the REXX procedure is waiting for user input. In this case 
  636. select Interactive trace on again to stop the trace. 
  637.  
  638.  
  639. ΓòÉΓòÉΓòÉ 3.6. Variables, Constants, and Literal Strings ΓòÉΓòÉΓòÉ
  640.  
  641. Comprehensive rules for variables, constants, and literal strings are contained 
  642. in the Object REXX Reference. If you've programmed in Basic or C, you won't 
  643. find anything too surprising about REXX's implementation. 
  644.  
  645. You can name variables almost anything you want. REXX imposes few rules. A 
  646. variable name can be any symbol (group of characters), containing up to 250 
  647. characters, with the following restrictions: 
  648.  
  649.      The first character must be A-Z, a-z, !, ?, or _ . REXX translates 
  650.       lowercase letters to uppercase before using them. 
  651.  
  652.      The rest of the characters may be A-Z, a-z, !, ?, or _, ., or 0-9. 
  653.  
  654.      The period (.) has a special meaning for REXX variables. Do not use it in 
  655.       a variable name until you understand the rules for forming compound 
  656.       symbols. 
  657.  
  658.  Literal strings in REXX are delimited by quotation marks (either ' or "). 
  659.  Examples of literal strings are: 
  660.  
  661.   'Hello'
  662.   "Final result:"
  663.  
  664.  If you need to use quotation marks within a literal string, use quotation 
  665.  marks of the other type to delimit the string. For example: 
  666.  
  667.   "Don't panic"
  668.   'He said, "Bother"'
  669.  
  670.  There's another way to do this. Within a literal string, a pair of quotation 
  671.  marks (the same type that delimits the string) is interpreted as one of that 
  672.  type. For example: 
  673.  
  674.   'Don''t panic'                 (same as "Don't panic"      )
  675.   "He said, ""Bother"""          (same as 'He said, "Bother"')
  676.  
  677.  
  678. ΓòÉΓòÉΓòÉ 3.7. Assignments ΓòÉΓòÉΓòÉ
  679.  
  680. Assignments in REXX usually take this form: 
  681.  
  682. name = expression
  683.  
  684. For name, specify any valid variable name. For expression specify the 
  685. information to be stored, such as a number, a string, or some calculation. Here 
  686. are some examples: 
  687.  
  688. a=1+2
  689. b=a*1.5
  690. c="This is a string assignment. No memory allocation needed!"
  691.  
  692. The PARSE instruction and its variants PULL and ARG also assign values to 
  693. variables. PARSE assigns data from various sources to one or more variables 
  694. according to the rules of parsing. PARSE PULL, for example, is often used to 
  695. read data from the keyboard: 
  696.  
  697. /* Using PARSE PULL to read the keyboard                              */
  698. say 'Enter your first name and last name'   /* prompt user            */
  699. parse pull response       /* read keyboard and put result in RESPONSE */
  700. say response              /* possibly displays 'John Smith'           */
  701.  
  702. Other operands of PARSE indicate the source of the data. PARSE ARG retrieves 
  703. command line arguments. PARSE VERSION retrieves the information about the 
  704. version of the REXX interpreter being used. There are several other data 
  705. sources that PARSE can access. 
  706.  
  707. The most powerful feature of PARSE, however, is its ability to parse data 
  708. according to a template that you supply. The various pieces of data are 
  709. assigned to variables that are part of the template. The following example 
  710. prompts the user for a date, and assigns the month, day, and year to different 
  711. variables. (In a real application, you would want to add instructions to verify 
  712. the input.) 
  713.  
  714. /* PARSE example using a template */
  715. say 'Enter a date in the form MM/DD/YY'
  716. parse pull month '/' day '/' year
  717. say month
  718. say day
  719. say year
  720.  
  721. The template in the above example contains two literal strings ('/'). The PARSE 
  722. instruction uses these literals to determine how to split up the data. 
  723.  
  724. The PULL and ARG instructions are short forms of the PARSE instruction. See the 
  725. Object REXX Reference for lots more on REXX parsing. 
  726.  
  727.  
  728. ΓòÉΓòÉΓòÉ 3.8. Comments ΓòÉΓòÉΓòÉ
  729.  
  730. In OS/2, the first line of a REXX program must start with a comment in column 
  731. 1. This tells OS/2 your program is written in REXX, and not its built-in Batch 
  732. facility. Both Batch facility and REXX programs can use the file name extension 
  733. CMD. Each requires its own special processing, so OS/2 checks the first line to 
  734. see which type of program it is. If it finds a REXX comment, the program is 
  735. processed as REXX. Use /* and */ to mark the start and end of a comment: 
  736.  
  737. /* This is the required column-1 comment. */
  738.  
  739. say ...  /* This is a comment on the same line as an instruction */
  740.  
  741. /* Comments may
  742.    occupy more
  743.    than one line. */
  744.  
  745. /*************************************
  746. *  Comments may be boxed as headers: *
  747. *                                    *
  748. *  HELLO.CMD written by J. Smith     *
  749. *        November 15, 1994           *
  750. * A program to greet a user by name. *
  751. *************************************/
  752.  
  753. For a column-1 comment it is enough to use /* */, but more often one uses this 
  754. space to give a brief description of the program. 
  755.  
  756. When REXX finds a /*, it stops interpreting the program until a */ is found, 
  757. which may be a few words or several lines later. 
  758.  
  759.  
  760. ΓòÉΓòÉΓòÉ 3.9. Using Functions ΓòÉΓòÉΓòÉ
  761.  
  762. REXX functions can be used in any expression. In this example, the built-in 
  763. function WORD is used to return the third blank-delimited word in a string: 
  764.  
  765. /* Example of function use                                     */
  766. myname="John Q. Public"   /* assign a literal string to MYNAME */
  767. surname=word(myname,3)    /* assign WORD result to SURNAME     */
  768. say surname               /* display surname                   */
  769.  
  770. Literal strings can be supplied as arguments to functions, so the above program 
  771. can be rewritten as follows: 
  772.  
  773. /* Example of function use                                            */
  774. surname=word("John Q. Public",3) /* assign WORD result to SURNAME     */
  775. say surname                      /* display surname                   */
  776.  
  777. Since an expression can be used on the SAY instruction, you can further reduce 
  778. the program to: 
  779.  
  780. /* Example of function use                                            */
  781. say word("John Q. Public",3)
  782.  
  783. Functions can be nested. Suppose you wanted to display only the first two 
  784. letters of the third word, Public. The LEFT function can return the first two 
  785. letters, but you need to give it the third word. LEFT expects the input string 
  786. as its first argument and the number of characters to return as its second 
  787. argument: 
  788.  
  789. /* Example of function use               */
  790.  
  791. /* Here is how to do it without nesting  */
  792. thirdword=word("John Q. Public",3)
  793. say left(thirdword,2)
  794.  
  795. /* And here is how to do it with nesting */
  796. say left(word("John Q. Public",3),2)
  797.  
  798.  
  799. ΓòÉΓòÉΓòÉ 3.10. Program Control ΓòÉΓòÉΓòÉ
  800.  
  801. REXX has instructions such as DO, IF, and SELECT for program control. Here is a 
  802. typical REXX IF instruction: 
  803.  
  804. if a>1 & b<0 then do
  805.     say "Whoops, A is greater than 1 while B is less than 0!"
  806.     say "I'm ending with a return code of 99."
  807.     exit 99
  808. end
  809.  
  810. C programmers will notice that the REXX relational operator for a logical AND 
  811. is different from the operator in C (which is &&). Other relational operators 
  812. differ as well, so you'll want to review the appropriate section in the Object 
  813. REXX Reference. For now, here's a list of some common comparison operators and 
  814. operations: 
  815.  
  816.  =            True if the terms are equal (numerically, when padded, and so on) 
  817.  \=, ╨║=       True if the terms are not equal (inverse of =) 
  818.  >            Greater than 
  819.  <            Less than 
  820.  <>           Greater than or less than (same as not equal) 
  821.  >=           Greater than or equal to 
  822.  <=           Less than or equal to 
  823.  ==           True if terms are strictly equal (identical) 
  824.  \==, ╨║==     True if the terms are NOT strictly equal (inverse of ==) 
  825.  
  826.  Note:  Throughout the language, the NOT character, ╨║, is synonymous with the 
  827.         backslash (\). You can use the two characters interchangeably, 
  828.         according to availability and personal preference. The backslash can 
  829.         appear in the \ (prefix not), \=, and \== operators. 
  830.  
  831.  A character string is taken to have the value false if it is 0, and true if it 
  832.  is 1. The logical operators take one or two such values (values other than 0 
  833.  or 1 are not allowed) and return 0 or 1 as appropriate: 
  834.  
  835.  &            AND 
  836.               Returns 1 if both terms are true. 
  837.  
  838.  |            Inclusive OR 
  839.               Returns 1 if either term is true. 
  840.  
  841.  &&           Exclusive OR 
  842.               Returns 1 if either (but not both) is true. 
  843.  
  844.  Prefix \,╨║   Logical NOT 
  845.               Negates; 1 becomes 0, and 0 becomes 1. 
  846.  
  847.  Note:  On ASCII systems (for example, IBM PS/2 systems), REXX recognizes the 
  848.         ASCII character encoding 124 as the logical OR character. Depending on 
  849.         the code page or keyboard you are using for your particular country, 
  850.         the logical OR character may be shown as a solid vertical bar (|) or a 
  851.         split vertical bar (Γûî). The appearance of the character on your screen 
  852.         may not match the character engraved on the key. If you are receiving 
  853.         error 13, invalid character in program, on an instruction including a 
  854.         vertical bar character, make sure this character is ASCII character 
  855.         encoding 124. 
  856.  
  857.  Using the wrong relational or comparison operator is a common mistake when 
  858.  switching between C and REXX. You'll also notice that the familiar C language 
  859.  braces { } are not used in REXX for blocks of instructions. Instead, REXX uses 
  860.  DO/END pairs. The THEN keyword is always required. 
  861.  
  862.  Here is an IF instruction with an ELSE: 
  863.  
  864.   if a>1 & b<0 then do
  865.       say "Whoops, A is greater than 1 while B is less than 0!"
  866.       say "I'm ending with a return code of 99."
  867.       exit 99
  868.   end
  869.   else do
  870.       say "A and B are okay."
  871.       say "On with the rest of the program."
  872.   end  /* if */
  873.  
  874.  You can omit the DO/END pairs if only one clause follows the THEN or ELSE 
  875.  keyword: 
  876.  
  877.   if words(myvar) > 5 then
  878.      say "Variable MYVAR has more than five words."
  879.   else
  880.      say "Variable MYVAR has fewer than six words."
  881.  
  882.  REXX also supports an ELSE IF construction: 
  883.  
  884.   count=words(myvar)
  885.   if count > 5 then
  886.      say "Variable MYVAR has more than five words."
  887.   else if count >3 then
  888.      say "Variable MYVAR has more than three, but fewer than six words."
  889.   else
  890.      say "Variable MYVAR has fewer than four words."
  891.  
  892.  The SELECT instruction in REXX is similar to the SELECT CASE statement in 
  893.  Basic and the switch statement in C. SELECT executes a block of statements 
  894.  based on the value of an expression. REXX's SELECT differs from the equivalent 
  895.  statements in Basic and C in that there isn't an expression following the 
  896.  SELECT keyword itself. Instead, expressions are placed on WHEN clauses: 
  897.  
  898.   select
  899.   when name='Bob' then
  900.     say "It's Bob!"
  901.   when name='Mary' then
  902.     say "Hello, Mary."
  903.   otherwise
  904.   end /* select */
  905.  
  906.  The WHEN clauses are evaluated in order. When one of the expressions is true, 
  907.  the statement (or block of statements) is executed. All the other blocks are 
  908.  skipped, even if their WHEN clauses would have evaluated to true. (C 
  909.  programmers take note: statements like C's break statement are not needed.) 
  910.  
  911.  Notice that an OTHERWISE keyword is used even though no instructions follow 
  912.  it. REXX doesn't require an OTHERWISE clause. However, if none of the WHEN 
  913.  clauses evaluates to true and you omit OTHERWISE, an error occurs. You can 
  914.  reduce the risk of errors by making a habit of including an OTHERWISE. 
  915.  
  916.  As with the IF instruction, you can use DO/END pairs for multiple clauses 
  917.  within SELECT cases. You don't need a DO/END pair if multiple clauses follow 
  918.  the OTHERWISE keyword: 
  919.  
  920.   select
  921.   when name='Bob' then
  922.      say "It's Bob"
  923.   when name='Mary' then do
  924.      say "Hello Mary"
  925.      marycount=marycount+1
  926.      end
  927.   otherwise
  928.      say "I'm sorry.  I don't know you."
  929.      anonymous=anonymous+1
  930.   end /* select */
  931.  
  932.  Many Basic implementations have several different instructions for loops. In 
  933.  REXX, there is only the DO/END pair. All of the traditional looping variations 
  934.  are incorporated into the DO instruction: 
  935.  
  936.   do i=1 to 10           /* Simple loop            */
  937.      say i
  938.   end
  939.  
  940.   do i=1 to 10 by 2      /* Increment count by two */
  941.      say i
  942.   end
  943.  
  944.   b=3; a=0             /* DO WHILE -- the conditional expression */
  945.   do while a<b         /* is evaluated before the instructions   */
  946.     say a              /* in the loop are executed.  If the      */
  947.     a=a+1              /* expression isn't true at the outset,   */
  948.   end                  /* instructions are not executed at all.  */
  949.  
  950.   a=5                  /* DO UNTIL -- like many other languages, */
  951.   b=4                  /* a REXX DO UNTIL block is executed at   */
  952.   do until a>b         /* least once.  The expression is         */
  953.      say "Until loop"  /* evaluated at the end of the loop.      */
  954.   end
  955.  
  956.  REXX also has a FOREVER keyword. Use the LEAVE, RETURN, or EXIT instructions 
  957.  to break out of the loop: 
  958.  
  959.   /* Program to emulate your 5 year old child */
  960.   num=random(1,10)  /* To emulate a three year old, move this inside the loop! */
  961.   do forever
  962.     say "What number from 1 to 10 am I thinking?"
  963.     pull guess
  964.     if guess=num then do
  965.        say "That's correct"
  966.        leave
  967.     end
  968.     say "No, guess again..."
  969.   end
  970.  
  971.  REXX also includes an ITERATE instruction that's quite handy. It skips the 
  972.  rest of the instructions in that iteration of the loop: 
  973.  
  974.   do i=1 to 100
  975.      /* Iterate when the 'special case' value is reached    */
  976.      if i=5 then iterate
  977.  
  978.      /* Instructions used for all other cases would be here */
  979.  
  980.   end
  981.  
  982.  You can use loops in IF or SELECT statements: 
  983.  
  984.   /* Say hello ten times if I is equal to 1 */
  985.   if i=1 then
  986.      do j=1 to 10
  987.         say "Hello!"
  988.      end
  989.  
  990.  Basic programmers may be wondering if there is an equivalent to the GOTO 
  991.  statement. There is. You can use a REXX SIGNAL instruction. SIGNAL causes 
  992.  control to branch to a label: 
  993.  
  994.   Signal fred;  /* Transfer control to label FRED below */
  995.     ....
  996.     ....
  997.   Fred: say 'Hi!'
  998.  
  999.  As with GOTO, you need to be careful about how you're using SIGNAL. In 
  1000.  particular, you should not try to signal into the middle of a DO/END block or 
  1001.  into a SELECT structure. 
  1002.  
  1003.  
  1004. ΓòÉΓòÉΓòÉ 3.11. Subroutines and Procedures ΓòÉΓòÉΓòÉ
  1005.  
  1006. In REXX you can write routines that make all variables accessible to the called 
  1007. routine. You can also write routines that hide the caller's variables. 
  1008.  
  1009. Let's start with an example of a routine in which all variables are accessible: 
  1010.  
  1011. /* Routine example                     */
  1012. i=10               /* Initialize I     */
  1013. call myroutine     /* Call routine     */
  1014. say i              /* Displays 22      */
  1015. exit               /* End main program */
  1016.  
  1017. myroutine:         /* Label            */
  1018.    i=i+12          /* Increment I      */
  1019. return
  1020.  
  1021. The CALL instruction calls routine MYROUTINE. A label (note the colon) marks 
  1022. the start of the routine. A RETURN instruction ends the routine. Notice that an 
  1023. EXIT statement is required in this case to end the main program. If EXIT is 
  1024. omitted, REXX assumes that the following instructions are part of your main 
  1025. program and will execute those instructions, producing interesting yet 
  1026. undesirable results. The SAY instruction displays 22 instead of 10 because the 
  1027. caller's variables are accessible to the routine. 
  1028.  
  1029. You can return a result to the caller by placing an expression on the RETURN 
  1030. instruction, like this: 
  1031.  
  1032. /* Routine with result                 */
  1033. i=10               /* Initialize I     */
  1034. call myroutine     /* Call routine     */
  1035. say result         /* Displays 22      */
  1036. exit               /* End main program */
  1037.  
  1038. myroutine:         /* Label            */
  1039. return i+12        /* Increment I      */
  1040.  
  1041. The returned result is available to the caller in the special variable RESULT, 
  1042. as shown above. If your routine returns a result, you can call it as a 
  1043. function: 
  1044.  
  1045. /* Routine with result called as function  */
  1046. i=10               /* Initialize I         */
  1047. say myroutine()    /* Displays 22          */
  1048. exit               /* End main program     */
  1049.  
  1050. myroutine:         /* Label                */
  1051. return i+12        /* Increment I          */
  1052.  
  1053. You can pass arguments to this sort of routine, although there isn't much to be 
  1054. gained by doing so. All variables are available to the routine anyway. 
  1055.  
  1056. Let's move on to routines that separate the caller's variables from the 
  1057. routine's variables. Except for the smallest programs, you'll want to use this 
  1058. format. It eliminates the risk of accidentally writing over a variable used by 
  1059. the caller or by some other unprotected routine. To get protection, use the 
  1060. PROCEDURE instruction, as follows: 
  1061.  
  1062. /* Routine example using PROCEDURE instruction                             */
  1063. headcount=0
  1064. tailcount=0
  1065. /* Toss a coin 100 times, report results */
  1066. do i=1 to 100
  1067.    call cointoss                                     /* Flip the coin      */
  1068.    if result='HEADS' then headcount=headcount+1      /* Increment counters */
  1069.    else tailcount=tailcount+1
  1070.                                                      /* Report results     */
  1071.    say "Toss is" result ||".  Heads=" headcount  "Tails=" tailcount
  1072. end /* do */
  1073. exit                                                 /* End main program   */
  1074.  
  1075. cointoss: procedure             /* Use PROCEDURE to protect caller         */
  1076.    i=random(1,2)                /* Pick a random number: 1 or 2            */
  1077.    if i=1 then return "HEADS"   /* Return English string                   */
  1078. return "TAILS"
  1079.  
  1080. In the above example, the variable I is used in both the main program and in 
  1081. the routine. When the PROCEDURE instruction is placed after the routine label, 
  1082. the routine's variables become local variables. They are isolated from all 
  1083. other variables in the program. Without the PROCEDURE instruction in the above 
  1084. example, the program would loop indefinitely. On each iteration the value of I 
  1085. would be reset to some value less than 100, which means the loop would never 
  1086. end. (If a programming error causes your procedure to loop indefinitely, use 
  1087. Ctrl+Break or close the OS/2 session to end the procedure.) 
  1088.  
  1089. To access variables outside of the routine, add an EXPOSE operand to the 
  1090. PROCEDURE instruction. List the desired variables after the EXPOSE keyword: 
  1091.  
  1092. /* Routine example using PROCEDURE instruction with EXPOSE operand         */
  1093. headcount=0
  1094. tailcount=0
  1095. /* Toss a coin 100 times, report results                                   */
  1096. do i=1 to 100
  1097.    call cointoss                                     /* Flip the coin      */
  1098.    say "Toss is" result ||".  Heads=" headcount  "Tails=" tailcount
  1099. end /* do */
  1100. exit                                                 /* End main program   */
  1101.  
  1102. cointoss: procedure expose headcount tailcount /* Expose the counter variables */
  1103.    if random(1,2)=1 then do                    /* Pick a random number: 1 or 2 */
  1104.       headcount=headcount+1                    /* Bump counter...              */
  1105.       return "HEADS"                           /* ...and return English string */
  1106.    end
  1107.    else
  1108.       tailcount=tailcount+1
  1109. return "TAILS"
  1110.  
  1111. To pass arguments to a routine, separate the arguments with commas on the call: 
  1112.  
  1113. call myroutine arg1, "literal arg", arg3   /* Call as subroutine */
  1114. myrc=myroutine(arg1, "literal arg", arg3)  /* Call as function   */
  1115.  
  1116. In the routine, use the PARSE ARG instruction to retrieve the argument. 
  1117.  
  1118.  
  1119. ΓòÉΓòÉΓòÉ 4. Into the Object World ΓòÉΓòÉΓòÉ
  1120.  
  1121. Object REXX includes features typical of an object-oriented language--features 
  1122. like subclassing, polymorphism, and data encapsulation. As we said at the 
  1123. outset, Object REXX is an extension of the traditional REXX language, which has 
  1124. been expanded to include classes, objects, and methods. These extensions do not 
  1125. replace traditional REXX functions, or preclude the development or running of 
  1126. traditional REXX programs. You can program as before, program with objects, or 
  1127. intermix objects with regular REXX instructions. You decide when to use REXX's 
  1128. object-oriented features. The REXX programming concepts that support these 
  1129. features are the subject of this section. 
  1130.  
  1131.  
  1132. ΓòÉΓòÉΓòÉ 4.1. What Is Object-Oriented Programming? ΓòÉΓòÉΓòÉ
  1133.  
  1134. Object-oriented programming is a way to write computer programs by focusing not 
  1135. on the instructions and operations a program uses to manipulate data, but on 
  1136. the data itself. First, the program simulates, or models, objects in the 
  1137. physical world as closely as possible. Then the objects interact with each 
  1138. other to bring the desired result. 
  1139.  
  1140. It is not unusual for computer data to represent things in the physical 
  1141. world--a company's employees, money in a bank account, a report. Real-world 
  1142. objects are stored as data so the computer can act upon it to some purposeful 
  1143. end. For example, when you "PRINT a report," PRINT is the action and report is 
  1144. the object acted upon. Often multiple actions apply; you could also SEND the 
  1145. report or ERASE the report. 
  1146.  
  1147.  
  1148. ΓòÉΓòÉΓòÉ 4.2. Modularizing Data ΓòÉΓòÉΓòÉ
  1149.  
  1150. In conventional, structured programming, actions like PRINT are often isolated 
  1151. from the data by placing them in subroutines or modules. A module typically 
  1152. contains an operation for implementing one simple action. You might have a 
  1153. PRINT module, a SEND module, an ERASE module. These actions are independent of 
  1154. the data they operate on. 
  1155.  
  1156.  
  1157. Modular program with isolated data
  1158.  
  1159.  
  1160.       PROGRAM ...
  1161.       ___________________________
  1162.       ___________________________
  1163.         PRINT _________________             |
  1164.         _______________________             |
  1165.         _______________________             |           data
  1166.         _______________________             |      data     data
  1167.       ___________________________           |    data  data
  1168.       ___________________________           |      data data    data
  1169.       ___________________________           |      data     data
  1170.         SEND __________________             |         data data
  1171.         _______________________             |          data
  1172.         _______________________             |
  1173.         _______________________             |
  1174.       ___________________________
  1175.       ___________________________
  1176.       ___________________________
  1177.         ERASE _________________
  1178.         _______________________
  1179.         _______________________
  1180.         _______________________
  1181.  
  1182. But with object-oriented programming, it is the data that is modularized. And 
  1183. each data module includes its own operations for performing actions directly 
  1184. related to its data. 
  1185.  
  1186.  
  1187. Modular data--a report object
  1188.  
  1189.  
  1190. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇP R I N TΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1191. Γöé             Γöé
  1192. Γöé             Γöé
  1193. Γöé      Report     Γöé
  1194. Γöé      ------     Γöé
  1195. S      data      F
  1196. E      data      I
  1197. N      data      L
  1198. D      data      E
  1199. Γöé      data      Γöé
  1200. Γöé             Γöé
  1201. Γöé             Γöé
  1202. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇE R A S EΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1203.  
  1204. In the case of report, the report object would contain its own built-in PRINT, 
  1205. SEND, ERASE, and FILE operations. 
  1206.  
  1207. Object-oriented programming lets you model real-world objects--potentially very 
  1208. complex ones--precisely and elegantly. As a result, object manipulation becomes 
  1209. easier within the computer's programming. Computer instructions become simpler, 
  1210. and can be modified later with minimal effort. 
  1211.  
  1212. Object-oriented programming hides any information that need not be known in 
  1213. order to act on an object, thereby concealing the object's complexities. 
  1214. Complex tasks can then be initiated simply, at a very high level. It's like 
  1215. moving your arm. To do so, you do not have to know about the many electrical, 
  1216. chemical, and mechanical interactions that must occur in the bones, muscles, 
  1217. tissues, and systems involved. These operations occur at lower levels. You just 
  1218. move your arm. 
  1219.  
  1220.  
  1221. ΓòÉΓòÉΓòÉ 4.3. Objects Model Things in the Real World ΓòÉΓòÉΓòÉ
  1222.  
  1223. In object-oriented programming, objects are modeled to real-world objects. A 
  1224. real-world object has: 
  1225.  
  1226.      Actions related to it 
  1227.      Characteristics of its own 
  1228.  
  1229.  Take a ball, for instance. A ball can be acted on--rolled, tossed, thrown, 
  1230.  bounced, caught. But it also has its own physical characteristics--size, 
  1231.  shape, composition, weight, color, speed, position. An accurate data model of 
  1232.  a real ball would define not just the physical characteristics of size, shape, 
  1233.  and the rest. Rather, this is what conventional programming would do. Instead 
  1234.  it would define all related actions and characteristics in one complete 
  1235.  "package." 
  1236.  
  1237.  
  1238.   A ball object
  1239.  
  1240.  
  1241.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇBOUNCEΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1242.   Γöé             Γöé
  1243.   Γöé             Γöé
  1244.   Γöé      Size      |
  1245.   T      Shape      C
  1246.   H      Comp      A
  1247.   R      Weight     T
  1248.   O      Color      C
  1249.   W      Speed      H
  1250.   Γöé      Pos       |
  1251.   Γöé             Γöé
  1252.   Γöé             Γöé
  1253.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇROLLΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇTOSSΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1254.  
  1255.  In object-oriented programming, objects are the basic building blocks--the 
  1256.  fundamental units of data. 
  1257.  
  1258.  There are many kinds of objects; for example, character strings, collections, 
  1259.  and input and output streams. An object--such as a character string--always 
  1260.  consists of two parts: the possible actions or operations related to it, and 
  1261.  its characteristics, or variables (a variable has a variable name, and an 
  1262.  associated data value that can change over time). These actions and 
  1263.  characteristics are so closely associated that they cannot be separated. 
  1264.  
  1265.  
  1266.   Ball object with variable names and values
  1267.  
  1268.  
  1269.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇBOUNCEΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1270.   Γöé             Γöé
  1271.   Γöé             Γöé
  1272.   Γöé     Size=3      |
  1273.   T    Shape=round    C
  1274.   H     Comp=rubber    A
  1275.   R    Weight=2      T
  1276.   O    Color=yellow    C
  1277.   W    Speed=32      H
  1278.   Γöé     Pos=4      |
  1279.   Γöé             Γöé
  1280.   Γöé             Γöé
  1281.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇROLLΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇTOSSΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1282.  
  1283.  To access an object's data, you always need to specify an action. For example, 
  1284.  suppose the object is the number 5. Its actions might include addition, 
  1285.  subtraction, multiplication, and division. Each of these actions is an 
  1286.  interface to the object's data. The data is said to be encapsulated because 
  1287.  the only way to access it is through one of these surrounding actions. The 
  1288.  encapsulated internal characteristics of an object are its variables. 
  1289.  Variables are associated with an object and exist for the lifetime of that 
  1290.  object. 
  1291.  
  1292.  
  1293.   Encapsulated 5 object
  1294.  
  1295.  
  1296.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇSUBTRACTIONΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1297.   Γöé             Γöé
  1298.   A             D
  1299.   D             I
  1300.   D             V
  1301.   I             I
  1302.   T       5       S
  1303.   I             I
  1304.   O             O
  1305.   N             N
  1306.   Γöé             Γöé
  1307.   Γöé             Γöé
  1308.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇMULTIPLICATIONΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1309.  
  1310.  REXX comes with a basic set of classes for creating objects (see The Basics of 
  1311.  Classes). Therefore, you can devise objects that exactly match the needs of a 
  1312.  particular application. 
  1313.  
  1314.  
  1315. ΓòÉΓòÉΓòÉ 4.4. How Objects Interact ΓòÉΓòÉΓòÉ
  1316.  
  1317. You have seen that the actions within an object are its only interface to other 
  1318. objects. Actions form a kind of "wall" that encapsulates the object, and 
  1319. shields its internal information from outside objects. This shielding is called 
  1320. information hiding. Information hiding protects an object's data from 
  1321. corruption by outside objects, and also protects outside objects from relying 
  1322. on another object's private data, which may change without warning. Because an 
  1323. object's actions are its only interface to the outside, one object can act upon 
  1324. another (or cause it to act) only by calling that object's actions. How do they 
  1325. do it? They send messages. 
  1326.  
  1327. OO programming in REXX, then, consists of sending messages to objects. 
  1328.  
  1329. Objects respond to these messages by performing an action, returning some data, 
  1330. or both. A message to an object must specify: 
  1331.  
  1332.      A receiving object 
  1333.  
  1334.      The "message send" symbol (~), sometimes called the "twiddle" 
  1335.  
  1336.      The action and, optionally in parentheses, any parameters it needs to 
  1337.       perform its function 
  1338.  
  1339.  So the message format looks like this: 
  1340.  
  1341.   object~action(parameters)
  1342.  
  1343.  Say the object is the string !iH. Sending it a message to use its REVERSE 
  1344.  action: 
  1345.  
  1346.   '!iH'~reverse
  1347.  
  1348.  returns the string object Hi!. 
  1349.  
  1350.  
  1351. ΓòÉΓòÉΓòÉ 4.5. Methods Are "Coded Actions" ΓòÉΓòÉΓòÉ
  1352.  
  1353. Sending a message to an object results in performing some action; that is, it 
  1354. results in running some underlying code. The action-generating code is called a 
  1355. method. When you send a message to an object, you specify its method name in 
  1356. the message. (Method names are simply character strings, like "REVERSE.") Doing 
  1357. this runs the method with the corresponding name. In the preceding example, 
  1358. sending the reverse message to the !iH object causes it to run the REVERSE 
  1359. method. Most objects are capable of more than one action, and so have a number 
  1360. of available methods. 
  1361.  
  1362. The classes REXX provides include their own predefined methods. The Message 
  1363. class, for example, has the COMPLETED, INIT, NOTIFY, RESULT, SEND, and START 
  1364. methods. When you create your own classes, you can write new methods for them 
  1365. in REXX code. Much of the object programming in REXX is writing the code for 
  1366. the methods you create. 
  1367.  
  1368.  
  1369. ΓòÉΓòÉΓòÉ 4.6. Polymorphism ΓòÉΓòÉΓòÉ
  1370.  
  1371. REXX lets you send the same message to objects that may be dissimilar: 
  1372.  
  1373. '!iH'~reverse  /* Reverses the characters "!iH" to form "Hi!"  */
  1374. pen~reverse     /* Reverses the direction of a plotter pen      */
  1375. ball~reverse    /* Reverses the direction of a moving ball      */
  1376.  
  1377. As long as the dissimilar objects (like the preceding !iH-string, pen, and 
  1378. ball) each have their own REVERSE method corresponding with the message, 
  1379. REVERSE will run even though the programming implementation may be very 
  1380. different for each object. This ability to hide different functions behind a 
  1381. common interface is called polymorphism. As a result of information hiding, 
  1382. each object in the above example knows only its own version of REVERSE. And 
  1383. even though the objects are dissimilar, each will reverse itself as dictated by 
  1384. its own code. 
  1385.  
  1386. Although the !iH object's REVERSE code is different from the plotter pen's, the 
  1387. method name can be the same because REXX keeps track of the methods each object 
  1388. owns. The ability to reuse the same method name so that one message can 
  1389. initiate more than one function is another feature of polymorphism. You don't 
  1390. need to have multiple message names like REVERSE_STRING, REVERSE_PEN, 
  1391. REVERSE_BALL, REVERSE_anyobject. This keeps method-naming schemes simpler and 
  1392. makes complex programs easier to follow and modify. 
  1393.  
  1394. The ability to hide the various implementations of a method while leaving the 
  1395. interface the same illustrates polymorphism at its lowest level. On a higher 
  1396. level, polymorphism permits extensive code reuse. 
  1397.  
  1398.  
  1399. ΓòÉΓòÉΓòÉ 4.7. Classes and Instances ΓòÉΓòÉΓòÉ
  1400.  
  1401. In REXX, objects are organized into classes. The reason is not unlike why 
  1402. biologists categorize living things in hierarchies--to organize them by their 
  1403. similarities and lines of inheritance. Classes are like templates; they define 
  1404. the methods and variables a group of similar objects have in common. Rather 
  1405. than replicate the same methods and variables over and over for each similar 
  1406. object in your program, classes provide an efficient way to store these common 
  1407. actions and characteristics in one place. 
  1408.  
  1409. If you were writing a program to manipulate some screen icons, for example, you 
  1410. might create an Icon class. In that Icon class you could include all the icon 
  1411. objects with similar actions and characteristics: 
  1412.  
  1413.  
  1414. A simple class
  1415.  
  1416.  
  1417.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  1418.   Γöé
  1419.   Γöé
  1420. Icon class
  1421.  
  1422. OS/2 system icon instance
  1423. shredder icon instance
  1424. information icon instance
  1425. .
  1426. .
  1427. .
  1428.  
  1429. All the icon objects might use common methods like DRAW or ERASE. They might 
  1430. contain common variables like position or color or size. What makes each icon 
  1431. object different from one another is the data assigned in its variables. 
  1432. Perhaps for the OS/2 system icon, position='20,20', while for shredder it's 
  1433. '20,30' and for information it's '20,40': 
  1434.  
  1435.  
  1436. Icon class
  1437.  
  1438.  
  1439.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  1440.   Γöé
  1441.   Γöé
  1442. Icon class
  1443.  
  1444. OS/2 system icon instance
  1445.  (position='20,20')
  1446.  
  1447. shredder icon instance
  1448.  (position='20,30')
  1449.  
  1450. information icon instance
  1451.  (position='20,40')
  1452.  
  1453. Objects that belong to a class are called instances of that class. As instances 
  1454. of the Icon class, the OS/2 system icon, shredder icon, and information icon 
  1455. acquire the methods and variables of that class. The instance objects behave 
  1456. exactly as if they each had their own separate methods and variables of the 
  1457. same names. All the instances actually store, however, are their own unique 
  1458. properties--the data associated with the variables. Everything else can be 
  1459. retained at the class level. 
  1460.  
  1461.  
  1462. Instances of the Icon class
  1463.  
  1464.  
  1465.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  1466.   Γöé
  1467.   Γöé
  1468. Icon class
  1469.  (position=)
  1470.  
  1471. OS/2 system icon instance
  1472.  ('20,20')
  1473.  
  1474. shredder icon instance
  1475.  ('20,30')
  1476.  
  1477. information icon instance
  1478.  ('20,40')
  1479.  
  1480. A very useful thing about this arrangement is that, should it become necessary 
  1481. to update or change a particular method, you would only have to change it in 
  1482. one place, at the class level. This single update would then be acquired by 
  1483. every new instance that used the method. In cases where a class has hundreds of 
  1484. instances, the efficiency of this approach is clear. 
  1485.  
  1486. A class that can create instance objects is called an object class. Our 
  1487. hypothetical Icon class is an object class you can use to create other objects 
  1488. with like properties. In the future you may want to create an application icon 
  1489. or a drives icon. 
  1490.  
  1491. An object class can produce objects as a cookie cutter produces cookies. It is 
  1492. like a factory for producing objects. In particular, these are a class's 
  1493. instance objects. 
  1494.  
  1495.  
  1496. ΓòÉΓòÉΓòÉ 4.8. Data Abstraction ΓòÉΓòÉΓòÉ
  1497.  
  1498. The ability to create new, high-level data types and organize them into a 
  1499. meaningful class structure is called data abstraction. Data abstraction is at 
  1500. the heart of object-oriented programming. Once you model objects with 
  1501. real-world properties from the basic data types, you can continue creating, 
  1502. assembling, and combining them into more and more complex objects at will. Then 
  1503. you can use these objects as if they were part of the original programming 
  1504. language. You can do most of your coding in a high-level, real-world context 
  1505. (roll the ball, reverse the pen), instead of the typical low-level, built-in 
  1506. data-type format (using numbers, characters, and symbols) of conventional 
  1507. programming. 
  1508.  
  1509.  
  1510. ΓòÉΓòÉΓòÉ 4.9. Subclasses, Superclasses, and Inheritance ΓòÉΓòÉΓòÉ
  1511.  
  1512. When you write your first object-oriented program, you do not have to begin 
  1513. your real-world modeling from scratch. REXX has done some of this up-front work 
  1514. for you, providing predefined classes and methods. From there you can create 
  1515. additional classes and methods of your own, as you need them. 
  1516.  
  1517. REXX classes are hierarchical. Any subclass (classes below a class in the 
  1518. hierarchy) will inherit, or be able to use, the methods and variables of one or 
  1519. more superclasses (classes above a class in the hierarchy). 
  1520.  
  1521.  
  1522. Superclass and subclasses
  1523.  
  1524.  
  1525.        Superclass
  1526.          Γöé
  1527.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1528.   Γöé       Γöé       Γöé
  1529. Subclass    Subclass    Subclass
  1530.  
  1531. You can add a class to an existing superclass. For example, you might add the 
  1532. Icon class to the Screen-Object superclass: 
  1533.  
  1534.  
  1535. The Screen-Object superclass
  1536.  
  1537.  
  1538.       Screen-Object class
  1539.           Γöé
  1540.    ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1541.    Γöé       Γöé       Γöé
  1542.  Icon class  Window class  Bitmap class
  1543.  
  1544. Doing this lets the subclass inherit additional methods from the superclass. 
  1545. Sometimes a class may have more than one superclass. (Subclass Bitmap might 
  1546. have superclasses Screen-Object and Art-Object.) Acquiring methods and 
  1547. variables from more than one superclass is known as multiple inheritance. 
  1548.  
  1549.  
  1550. Multiple inheritance
  1551.  
  1552.  
  1553.       Screen-Object    Art-Object
  1554.          Γöé         Γöé
  1555.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ  Γöé
  1556.   Γöé       Γöé       Γöé  Γöé
  1557.  Icon      Window     Bitmap
  1558.  
  1559.  
  1560. ΓòÉΓòÉΓòÉ 5. The Basics of Classes ΓòÉΓòÉΓòÉ
  1561.  
  1562. For programming efficiency, similar objects in REXX are grouped into classes, 
  1563. forming a hierarchy. REXX gives you a basic class hierarchy to start with. All 
  1564. of the classes in the hierarchy are described in detail in the Object REXX 
  1565. Reference. But briefly, here are the classes REXX provides (there may be others 
  1566. in the system). The classes are indented to show subclassing. Classes in the 
  1567. list that are described later in this section are highlighted in bold type: 
  1568.  
  1569. Object 
  1570.  
  1571.       Alarm 
  1572.       Class 
  1573.       Collection classes 
  1574.            Array 
  1575.            List 
  1576.            Queue 
  1577.            Table 
  1578.                 Set 
  1579.            Directory 
  1580.            Relation 
  1581.                 Bag 
  1582.       Message 
  1583.       Method 
  1584.       Monitor 
  1585.       Stem 
  1586.       Stream 
  1587.       String 
  1588.       Supplier 
  1589.  
  1590.  
  1591. ΓòÉΓòÉΓòÉ 5.1. REXX Classes for Programming ΓòÉΓòÉΓòÉ
  1592.  
  1593. The class framework REXX provides is the starting point for object-oriented 
  1594. programming. Some key classes that you are likely to work with are described in 
  1595. the next sections. 
  1596.  
  1597.  
  1598. ΓòÉΓòÉΓòÉ 5.1.1. The Alarm Class ΓòÉΓòÉΓòÉ
  1599.  
  1600. The Alarm class is for creating objects with timing and notification 
  1601. capability. An alarm object is able send any message to any object at any 
  1602. future time, and until then, you can cancel the alarm. 
  1603.  
  1604.  
  1605. ΓòÉΓòÉΓòÉ 5.1.2. The Collection Classes ΓòÉΓòÉΓòÉ
  1606.  
  1607. Some potentially very useful classes for programmers are those for defining 
  1608. collections of objects that require manipulation. A collection is an object 
  1609. that contains a number of items, which can be any objects. These manipulations 
  1610. might include counting objects, organizing them, or assigning them a supplier 
  1611. (for example, to indicate that a specific assortment of baked goods is supplied 
  1612. by the Pie-by-Night Bakery). The classes that enable such manipulations are 
  1613. called collection classes. 
  1614.  
  1615. REXX includes classes for arrays, lists, queues, tables, directories, and the 
  1616. like. Every item stored in a REXX collection has an associated index that you 
  1617. can use to retrieve the item from the collection with the AT or [] (left and 
  1618. right bracket) methods, and each collection defines its own acceptable index 
  1619. types: 
  1620.  
  1621.  Array A sequenced collection of objects ordered by whole number indexes. 
  1622.  
  1623.  List A sequenced collection that lets you add new items at any position in the 
  1624.      sequence. A list generates and returns an index value for each item placed 
  1625.      in the list. The returned index remains valid until the item is removed 
  1626.      from the list. 
  1627.  
  1628.  Queue A sequenced collection with the items ordered as a queue. You can remove 
  1629.      items from the head of the queue and add at either its tail or its head. 
  1630.      Queues index the items with whole number indexes, in the order in which 
  1631.      the items would be removed. The current head of the queue has index 1, the 
  1632.      item after the head item has index 2, up to the number of items in the 
  1633.      queue. 
  1634.  
  1635.  Table A collection with indexes that can be any object. For example, string 
  1636.      objects, array objects, alarm objects, or any user-created object can be a 
  1637.      table index.  The Table class determines index match by using the == 
  1638.      comparison method to test for strict equality. A table contains no 
  1639.      duplicate indexes. 
  1640.  
  1641.  Directory A collection with character string indexes. Index comparisons are 
  1642.      performed using the string == comparison method to test for strict 
  1643.      equality. 
  1644.  
  1645.  Relation A collection with indexes that can be any object (as with the Table 
  1646.      class). A relation can contain duplicate indexes. 
  1647.  
  1648.  Set A collection where the indexes and the values are the same object. Set 
  1649.      indexes can be any object (as with the Table class) and each index is 
  1650.      unique. 
  1651.  
  1652.  Bag A collection where the index and the value are the same object. Bag 
  1653.      indexes may be any object (as with the Table class) and each index may 
  1654.      appear more than once. 
  1655.  
  1656.  
  1657. ΓòÉΓòÉΓòÉ 5.1.3. The Message Class ΓòÉΓòÉΓòÉ
  1658.  
  1659. It is useful to be able to manipulate message objects. For this you use the 
  1660. Message class. Methods created for this class are used to send a message, 
  1661. notify the sender object when an error occurs or when message processing is 
  1662. complete, return the results of that processing to the sender or to some other 
  1663. object, process the message object concurrently with the sender object, and so 
  1664. on. 
  1665.  
  1666.  
  1667. ΓòÉΓòÉΓòÉ 5.1.4. The Monitor Class ΓòÉΓòÉΓòÉ
  1668.  
  1669. The Monitor class provides a way to forward messages to a specified 
  1670. destination. Monitor methods let you initialize a monitor object, specify a 
  1671. destination object (or use a previously specified one), and obtain the name of 
  1672. the current destination object. 
  1673.  
  1674.  
  1675. ΓòÉΓòÉΓòÉ 5.1.5. The Stem Class ΓòÉΓòÉΓòÉ
  1676.  
  1677. A stem is a symbol that must start with a letter and end with a period, like 
  1678. "FRED."or "A.". The value of a stem is a stem object by default. A stem object 
  1679. is a collection with unique indexes that are character strings. Stem objects 
  1680. are automatically created when a REXX stem variable or REXX compound variable 
  1681. is used. In addition to the items assigned to the collection indexes, a stem 
  1682. object also has a default value that is used for all uninitialized indexes of 
  1683. the collection. You can assign a default value to a stem object and later 
  1684. retrieve this value. 
  1685.  
  1686.  
  1687. ΓòÉΓòÉΓòÉ 5.1.6. The Stream Class ΓòÉΓòÉΓòÉ
  1688.  
  1689. Input and output streams let REXX communicate with external objects--people, 
  1690. files, queues, serial interfaces, displays, networks, and the like. In 
  1691. programming there are many useful stream actions that could be coded as methods 
  1692. for manipulating the various stream objects. These methods and objects are 
  1693. organized in the Stream class. 
  1694.  
  1695. The methods are used to open streams for reading or writing, close streams at 
  1696. the end of an operation, move the line-read or line-write position within, say, 
  1697. a file stream, or get information about a stream. Methods are also provided to 
  1698. get character strings from a stream or send them to a stream, count characters 
  1699. in a stream, flush buffered data to a stream, query path specifications, time 
  1700. stamps, size, and other information from a stream, or do any other I/O stream 
  1701. manipulation one might find necessary or useful (see Input and Output for 
  1702. examples). 
  1703.  
  1704.  
  1705. ΓòÉΓòÉΓòÉ 5.1.7. The String Class ΓòÉΓòÉΓòÉ
  1706.  
  1707. Strings are data values that can have any length and contain any characters. 
  1708. The ability to manipulate strings in multiple ways is just as useful as the 
  1709. ability to manipulate I/O streams. There is the need to compare strings: is one 
  1710. string equal to, greater than, or less than another? 
  1711.  
  1712. Strings are subject to logical operations like AND, OR, exclusive OR, and 
  1713. logical NOT. We need to concatenate and copy strings, reverse them, join them 
  1714. together and split them apart. When strings are numeric, there is the need to 
  1715. perform arithmetic operations on them or find their absolute value or convert 
  1716. them from binary to hex, and vice versa. All this and more can be accomplished 
  1717. using the String class of objects. 
  1718.  
  1719.  
  1720. ΓòÉΓòÉΓòÉ 5.1.8. The Supplier Class ΓòÉΓòÉΓòÉ
  1721.  
  1722. Some collections have suppliers: a bakery, for example, may supply certain 
  1723. breads, cookies, cakes and pies; a financial report may supply certain data, 
  1724. statistics, tables, and reports. The  Supplier class is used to enumerate items 
  1725. that a collection contained at the time of the supplier's creation. For 
  1726. example, this class contains methods to verify if an item is available from a 
  1727. supplier (Does the Pie-by-Night Bakery sell chocolate cake?). Another method 
  1728. returns the index of the current item in a collection (What is the position of 
  1729. the apple pie record?). Others return the current collection item in a 
  1730. collection object, and the next item in the collection. 
  1731.  
  1732.  
  1733. ΓòÉΓòÉΓòÉ 5.2. REXX Classes for Organizing Objects ΓòÉΓòÉΓòÉ
  1734.  
  1735. REXX provides several key classes that form the basis for building class 
  1736. hierarchies. While you may not invoke them in everyday programming, you may 
  1737. want to understand them conceptually. 
  1738.  
  1739.  
  1740. ΓòÉΓòÉΓòÉ 5.2.1. The Object Class ΓòÉΓòÉΓòÉ
  1741.  
  1742. Because the topmost class in the hierarchy is the Object class, everything 
  1743. below it is an object. Objects, to interact with each other, require their own 
  1744. actions, called methods. Those methods that encode actions needed by all 
  1745. objects belong to the Object class. 
  1746.  
  1747. As methods of the top class, every other class in the hierarchy inherits them. 
  1748. For now, think of inheritance as the handing down of methods from a "parent" 
  1749. class--called a superclass--to all of its "descendent" classes--called 
  1750. subclasses. Finally, instances acquire methods from their classes. The Object 
  1751. class, then, is the topmost, or root class, of the class hierarchy. Any method 
  1752. created for the Object class is made available to every other class in the 
  1753. hierarchy. From the programmer's standpoint, this happens automatically; it is 
  1754. handled by the REXX language itself. 
  1755.  
  1756.  
  1757. ΓòÉΓòÉΓòÉ 5.2.2. The "Class" Class ΓòÉΓòÉΓòÉ
  1758.  
  1759. Within its class hierarchy REXX includes a class for generating new classes, 
  1760. and this the Class class. If a class is like a factory for producing instances, 
  1761. Class is like a factory for producing factories. Class is the parent of every 
  1762. new class in the hierarchy, and these all inherit Class-like characteristics. 
  1763. The Class-like characteristics take the form of methods and related variables, 
  1764. which reside in Class, to be used by all classes. 
  1765.  
  1766. A class that can be used to create another class is called a metaclass. The 
  1767. Class class is unique among REXX classes in that it is the only metaclass REXX 
  1768. provides (see Metaclasses). As such, Class's methods not only make new classes, 
  1769. they make methods for use by the new class and its instances. They also make 
  1770. methods that only the new class itself can use, apart from its instances. These 
  1771. are called class methods. They give a new class some powers that its instances 
  1772. are denied. 
  1773.  
  1774. Because each instance of Class is another class, or factory, that factory 
  1775. inherits Class's instance methods as class methods. Think of the instance 
  1776. methods of the Class factory as factory-running actions. Thus if Class 
  1777. generates a Pizza factory instance, the factory-running actions (Class's 
  1778. instance methods) become the class methods of the Pizza factory. Factory 
  1779. operations are class methods, and any new methods created to manipulate pizzas 
  1780. would be instance methods: 
  1781.  
  1782.  
  1783. How subclasses inherit instance methods from the Class class
  1784.  
  1785.  
  1786.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  1787.   Γöé
  1788.   Γöé
  1789.   Γöé
  1790. "Class" class
  1791.   Γöé
  1792.   Γöé
  1793.   Γöé  Class's class methods
  1794.   Γöé  ---------------------
  1795.   Γöé   Factory-creating
  1796.   Γöé   actions
  1797.   Γöé
  1798.   Γöé  Class's instance methods ΓöÇΓöÇΓöÇΓöÉ
  1799.   Γöé  ------------------------   Γöé
  1800.   Γöé   Factory-running      Γöé
  1801.   Γöé   actions          Γöé
  1802.   Γöé                Γöé
  1803.   Γöé                Γöé
  1804. Pizza class             Γöé
  1805.                   Γöé
  1806.     Pizza's class methods   ΓöÇΓöÇΓöÿ
  1807.     ---------------------
  1808.      Factory-running
  1809.      actions
  1810.  
  1811.     Pizza's instance methods
  1812.     ------------------------
  1813.      pizza-making
  1814.      actions
  1815.  
  1816.  
  1817.  
  1818. As a programmer, you will typically create classes by using directives, rather 
  1819. than the methods of the Class class. In particular, you'll use the ::CLASS 
  1820. directive, described later in this section. The ::CLASS directive is a kind of 
  1821. REXX clause that allows class definitions to be saved permanently, in a file, 
  1822. where they can be reused by other programs. Creating classes "on the fly," by 
  1823. using Class methods sent as messages, is not recommended when permanency or 
  1824. reuse is required. At any rate, directives have class-creating powers similar 
  1825. to the Class methods. 
  1826.  
  1827.  
  1828. ΓòÉΓòÉΓòÉ 5.3. REXX Classes: The Big Picture ΓòÉΓòÉΓòÉ
  1829.  
  1830. The following figure diagrams the supplied REXX classes, along with their 
  1831. methods. 
  1832.  
  1833.  
  1834. Classes and the inheritance of methods
  1835.  
  1836.  
  1837. ΓòÉΓòÉΓòÉ 5.4. Creating Your Own Classes Using Directives ΓòÉΓòÉΓòÉ
  1838.  
  1839. By analyzing your problem in terms of objects, you can determine what classes 
  1840. need to be created and begin to take advantage of object-oriented technology. 
  1841. You can create a class using messages or directives. Directives are a new kind 
  1842. of REXX clause, and they are preferred over messages because the code is easier 
  1843. to read and understand, especially in large programs. They also provide an easy 
  1844. way for you to save your class definitions and share them with others using the 
  1845. PUBLIC option. Because of these advantages, directives is the technique we will 
  1846. use here. 
  1847.  
  1848.  
  1849. ΓòÉΓòÉΓòÉ 5.4.1. What Are Directives? ΓòÉΓòÉΓòÉ
  1850.  
  1851. A REXX program is made up of one or more executable units. Directives separate 
  1852. these units, which themselves are REXX programs. REXX processes all directives 
  1853. first to set up any classes, methods, or routines needed by the program. Then 
  1854. it runs any code that exists before the first directive. The first directive in 
  1855. a program marks the end of the executable part of the program. A directive is a 
  1856. kind of clause that begins with a double-colon (::) and is non-executable (a 
  1857. directive cannot appear in the expression of an INTERPRET instruction, for 
  1858. example). 
  1859.  
  1860.  
  1861. ΓòÉΓòÉΓòÉ 5.4.2. The Directives REXX Provides ΓòÉΓòÉΓòÉ
  1862.  
  1863. The following is a short summary of all the REXX directives. See the Object 
  1864. REXX Reference for more details on, or examples of, any of these REXX 
  1865. directives. 
  1866.  
  1867.  
  1868. ΓòÉΓòÉΓòÉ 5.4.2.1. The ::CLASS Directive ΓòÉΓòÉΓòÉ
  1869.  
  1870. Use the ::CLASS directive to create a class. Programs can then use the new 
  1871. class by specifying it as a REXX environment symbol (the class name preceded by 
  1872. a period) in the program. For example, in A Sample Program Using Directives, 
  1873. the Savings class is created using the ::CLASS directive. Then a program uses 
  1874. the new class by specifying it as an environment symbol, ".savings". 
  1875.  
  1876. The new class that you create acquires any methods defined by subsequent 
  1877. ::METHOD directives within the program, until either another ::CLASS directive 
  1878. or the end of the program is reached. 
  1879.  
  1880. You can use the ::CLASS directive's SUBCLASS option to make the new class the 
  1881. subclass of another. In A Sample Program Using Directives, the Savings class is 
  1882. made a subclass of the Account class. A subclass inherits instance and class 
  1883. methods from its specified superclass; in the sample, Savings inherits from 
  1884. Account. 
  1885.  
  1886. Additional ::CLASS directive options are available for: 
  1887.  
  1888.      Creating classes using SOM or DSOM information (the EXTERNAL option) 
  1889.  
  1890.      Inheriting instance methods from a specified metaclass as class methods 
  1891.       of the new class (the METACLASS option); for more on metaclasses, see 
  1892.       Metaclasses 
  1893.  
  1894.      Making the new class available to programs outside its containing REXX 
  1895.       program (the PUBLIC option); the outside program must reference the new 
  1896.       class by using a ::REQUIRES directive 
  1897.  
  1898.      Subclassing the new class to a mixin class for purposes of inheriting its 
  1899.       instance and class methods (the MIXINCLASS option) 
  1900.  
  1901.      Adding the instance and class methods of a mixin class to the new class, 
  1902.       without subclassing it (the INHERIT option) 
  1903.  
  1904.  When you create a new class, it is always a subclass of an existing class. If 
  1905.  you do not specify the SUBCLASS or MIXINCLASS option on the ::CLASS directive, 
  1906.  the superclass for the new class is the Object class, and it is not a mixin 
  1907.  class. 
  1908.  
  1909.  Your class definition may be in a file of its own, with no executable code 
  1910.  preceding it. This is often the case when you are defining classes and methods 
  1911.  to be shared by several programs. You put the executable code in another file 
  1912.  and refer to the class file using a ::REQUIRES directive. 
  1913.  
  1914.  REXX processes ::CLASS directives in the order they appear, unless there is a 
  1915.  dependency on some later directive's processing. Two classes cannot be created 
  1916.  having the same class name in one program. If multiple programs contain 
  1917.  classes with duplicate names, the last ::CLASS directive processed will be 
  1918.  used. 
  1919.  
  1920.  
  1921. ΓòÉΓòÉΓòÉ 5.4.2.2. The ::METHOD Directive ΓòÉΓòÉΓòÉ
  1922.  
  1923. After writing a ::CLASS directive, use a ::METHOD directive to create a method 
  1924. for that class and define the method's attributes. The next directive in the 
  1925. program, or the end of the program, will end the method. 
  1926.  
  1927. Some classes you define will have an INIT method. INIT is called whenever a NEW 
  1928. message is sent to a class. The INIT method should contain whatever code is 
  1929. needed to initialize the object. 
  1930.  
  1931. While it is not required that a ::METHOD directive be preceded by a ::CLASS 
  1932. directive, without it the method is only accessible to the executable part of 
  1933. the program through REXX's .METHODS environment symbol. This symbol identifies 
  1934. a directory of methods that you can refer to by name. Only one method directive 
  1935. can appear for any method name not associated with a class. 
  1936.  
  1937. As with the ::CLASS directive, the ::METHOD directive has a number of useful 
  1938. options; in this case they are used for: 
  1939.  
  1940.      Creating a class method for the most-recent ::CLASS directive (the CLASS 
  1941.       option) 
  1942.  
  1943.      Creating a private method; that is, a method that works like a subroutine 
  1944.       and can only be activated by the object it belongs to--otherwise the 
  1945.       method is public by default, and any sender can activate it (the PRIVATE 
  1946.       option) 
  1947.  
  1948.      Creating a method that can be called while other methods are active on 
  1949.       the same object, as described in Activating Methods (the UNGUARDED 
  1950.       option) 
  1951.  
  1952.      Creating a pair of instance methods, method_name and method_name=, for 
  1953.       the preceding ::CLASS directive (the ATTRIBUTE option) 
  1954.  
  1955.  
  1956. ΓòÉΓòÉΓòÉ 5.4.2.3. The ::ROUTINE Directive ΓòÉΓòÉΓòÉ
  1957.  
  1958. Use the ::ROUTINE directive to create a named routine within a program. The 
  1959. ::ROUTINE directive starts the named routine and another directive (or the end 
  1960. of the program) ends the routine. 
  1961.  
  1962. The ::ROUTINE directive is useful for defining lower-level routines that are 
  1963. called by several methods. These methods might be in unrelated classes or in 
  1964. different applications. Use ::ROUTINE when you have some useful utility that 
  1965. you don't want to surface as a method. 
  1966.  
  1967. The ::ROUTINE directive includes a PUBLIC option for making the routine 
  1968. available to programs outside its containing REXX program, and the outside 
  1969. program must reference the routine by using a ::REQUIRES directive. 
  1970.  
  1971. Only one ::ROUTINE directive can appear for any routine name within a program. 
  1972.  
  1973.  
  1974. ΓòÉΓòÉΓòÉ 5.4.2.4. The ::REQUIRES Directive ΓòÉΓòÉΓòÉ
  1975.  
  1976. Use the ::REQUIRES directive when a program needs access to the classes and 
  1977. objects of another program, program_name. This directive takes the form: 
  1978.  
  1979. ::REQUIRES program_name
  1980.  
  1981. The ::REQUIRES directive must precede all other directives, and the order of 
  1982. the ::REQUIRES directives determines the search order for the classes and 
  1983. routines defined in the named programs. 
  1984.  
  1985. REXX uses local routine definitions within a program over routines of the same 
  1986. name accessed through ::REQUIRES directives. Local class definitions within a 
  1987. program override classes of the same name in other programs accessed through 
  1988. ::REQUIRES directives. Another directive (or the end of the program) must 
  1989. follow a ::REQUIRES directive. 
  1990.  
  1991.  
  1992. ΓòÉΓòÉΓòÉ 5.4.3. How Directives Are Processed ΓòÉΓòÉΓòÉ
  1993.  
  1994. You place any directives (and their method code) after all other program code. 
  1995. When you run a program containing directives, REXX: 
  1996.  
  1997.    1. Processes the directives first, to set up the program's classes, methods, 
  1998.       and routines. 
  1999.  
  2000.    2. Runs any program code preceding the first directive. This code can use 
  2001.       any classes, methods, and routines set up by the directives. 
  2002.  
  2003.       Once REXX has processed the code preceding the directive, any public 
  2004.       classes and objects the program defines are available for other programs 
  2005.       (having the appropriate ::REQUIRES directive) to use. 
  2006.  
  2007.  
  2008. ΓòÉΓòÉΓòÉ 5.4.4. A Sample Program Using Directives ΓòÉΓòÉΓòÉ
  2009.  
  2010. Here is a program that uses directives to create some new classes and methods: 
  2011.  
  2012. asav = .savings~new              /* executable code begins */
  2013. say asav~type                    /* executable code        */
  2014. asav~name= 'John Smith'          /* executable code ends   */
  2015.  
  2016. ::class Account                  /* directives begin ...   */
  2017.  
  2018.   ::method 'TYPE'
  2019.     return "an account"
  2020.  
  2021.   ::method 'NAME='
  2022.     expose name
  2023.     use arg name
  2024.  
  2025. ::class Savings subclass Account
  2026.  
  2027.   ::method 'TYPE'
  2028.     return "a savings account"   /* ... directives end     */
  2029.  
  2030. The preceding program uses the ::CLASS directive to create two classes, the 
  2031. Account class and its Savings subclass. In the ::class Account expression, the 
  2032. ::CLASS directive precedes name of the new class, Account. 
  2033.  
  2034. The example program also uses the ::METHOD directive to create TYPE and NAME= 
  2035. methods for Account. In the ::method 'TYPE' expression, the ::METHOD directive 
  2036. precedes the method name, and is immediately followed by the code for the 
  2037. method. Methods for any new class follow its ::CLASS directive in the program, 
  2038. and precede the next ::CLASS directive. 
  2039.  
  2040. In the ::method 'NAME=' method, the USE ARG instruction retrieves the argument. 
  2041. The EXPOSE instruction (which must immediately follow the ::METHOD directive) 
  2042. makes the value (here, "John Smith") available for use by other methods. A 
  2043. variable on an EXPOSE instruction is called an object variable. 
  2044.  
  2045. You don't have to do anything (like define an object handle) to associate 
  2046. object variables with a specific object. REXX keeps track of object variables 
  2047. for you. Whenever you send a message to savings account Asav, which points to 
  2048. the Name object, REXX knows what internal object value to use. If you assign 
  2049. another value to Asav (such as "Mary Smith"), REXX will delete the object that 
  2050. was associated with Asav ("John Smith") as part of its normal 
  2051. garbage-collection operations. 
  2052.  
  2053. In the Savings subclass, a second TYPE method is created that supersedes the 
  2054. TYPE method Savings would otherwise have inherited from Account. Note that the 
  2055. directives appear after all the other program code. 
  2056.  
  2057.  
  2058. ΓòÉΓòÉΓòÉ 5.4.5. Another Sample Program ΓòÉΓòÉΓòÉ
  2059.  
  2060. We mentioned that a directive is non-executable code that begins with a 
  2061. double-colon (::) and follows all the other program code. The ::CLASS directive 
  2062. creates a class; in this sample, the Dinosaur class. The sample provides two 
  2063. methods for the Dinosaur class, INIT and DIET. These are added to the Dinosaur 
  2064. class using ::METHOD directives. After the line containing the ::METHOD 
  2065. directive, the code for the method is specified. Methods are ended either by 
  2066. the start of the next directive or by the end of the program. 
  2067.  
  2068. Since directives must follow the executable code in your program, you put that 
  2069. code first. In this case, the executable code creates a new dinosaur, Dino, 
  2070. that is an instance of the Dinosaur class. REXX then runs the INIT method (REXX 
  2071. runs any INIT method automatically whenever the NEW message is received). Here 
  2072. the INIT method is used to identify the type of dinosaur. Next the program runs 
  2073. the DIET method to determine whether the dinosaur eats meat or veggies. The 
  2074. information returned by INIT and DIET is saved by REXX as variables in the Dino 
  2075. object. 
  2076.  
  2077. In the example, the Dinosaur class and its two methods are defined following 
  2078. the executable program code: 
  2079.  
  2080.  
  2081. dino=.dinosaur~new         /* Create a new dinosaur instance and initialize variables */
  2082. dino~diet                  /* Run the DIET method                                     */
  2083. exit
  2084.  
  2085. ::class Dinosaur           /* Create the Dinosaur class  */
  2086.  
  2087.   ::method init            /* Create the INIT method     */
  2088.     expose type
  2089.     say "Enter a type of dinosaur."
  2090.     pull type
  2091.     return
  2092.  
  2093.   ::method diet            /* Create the DIET method     */
  2094.     expose type
  2095.     select
  2096.     when type="T-REX" then string="Meat-eater"
  2097.     when type="TYRANNOSAUR" then string="Meat-eater"
  2098.     when type="TYRANNOSAURUS REX" then string="Meat-eater"
  2099.     when type="DILOPHOSAUR" then string="Meat-eater"
  2100.     when type="VELICORAPTOR" then string="Meat-eater"
  2101.     when type="RAPTOR" then string="Meat-eater"
  2102.     when type="ALLOSAUR" then string="Meat-eater"
  2103.     when type="BRONTOSAUR" then string="Plant-eater"
  2104.     when type="BRACHIOSAUR" then string="Plant-eater"
  2105.     when type="STEGOSAUR" then string="Plant-eater"
  2106.     otherwise string="Type of dinosaur or diet unknown"
  2107.     end
  2108.     say string
  2109.     return 0
  2110.  
  2111.  
  2112. ΓòÉΓòÉΓòÉ 5.5. Creating Classes Using Messages ΓòÉΓòÉΓòÉ
  2113.  
  2114. We mentioned that you can create a class using messages as well as directives. 
  2115. Though classes are available only to the program that creates them, there are 
  2116. occasions when this is useful and public availability is not required. Hence we 
  2117. demonstrate the message technique here, using the Savings Account example we 
  2118. showed using directives. 
  2119.  
  2120.  
  2121. ΓòÉΓòÉΓòÉ 5.5.1. Defining a New Class ΓòÉΓòÉΓòÉ
  2122.  
  2123. To define a new class using messages, you send a SUBCLASS message to the new 
  2124. class's superclass. That is, send the message to the class that will be 
  2125. immediately above the new class in the hierarchy. So, to define a subclass of 
  2126. the Object class called Account, enter: 
  2127.  
  2128. account = .object~subclass('Account')
  2129.  
  2130. Here, .object is a reference to the REXX Object class. .Object is an 
  2131. environment symbol indicating the intention to create a new class that is a 
  2132. subclass of the Object class. Environment symbols represent objects in a 
  2133. directory of public objects, called the Environment object. These public 
  2134. objects are available to all other objects, and include all the classes that 
  2135. REXX provides. Environment symbols begin with a period and are followed by the 
  2136. class name. Thus the Object class is represented by .object, the Alarm class by 
  2137. .alarm, the Array class by .array, and so on. 
  2138.  
  2139. The "twiddle" (~) is the "message send" symbol, subclass is a method of Class, 
  2140. and the string identifier in parentheses is an argument of SUBCLASS that names 
  2141. the new class, Account. 
  2142.  
  2143.  
  2144. ΓòÉΓòÉΓòÉ 5.5.2. Adding a Method to a Class ΓòÉΓòÉΓòÉ
  2145.  
  2146. Use the DEFINE method to define methods for your new class. To define a TYPE 
  2147. method and a NAME= method, enter: 
  2148.  
  2149. account~define('TYPE', 'return "an account"')
  2150. account~define('NAME=', 'expose name; use arg name')
  2151.  
  2152.  
  2153. ΓòÉΓòÉΓòÉ 5.5.3. Defining a Subclass of the New Class ΓòÉΓòÉΓòÉ
  2154.  
  2155. Using the SUBCLASS method, you can define a subclass for your new class and 
  2156. then a method for that subclass. To define a Savings subclass for the Account 
  2157. class, and a TYPE method for Savings, enter: 
  2158.  
  2159. savings = account~subclass('Savings Account')
  2160. savings~define('TYPE', 'return "a savings account"')
  2161.  
  2162.  
  2163. ΓòÉΓòÉΓòÉ 5.5.4. Defining an Instance ΓòÉΓòÉΓòÉ
  2164.  
  2165. Use the NEW method to define an instance of the new class, and then call 
  2166. methods that the instance inherited from its superclass. To define an instance 
  2167. of the Savings class named "John Smith," and send John Smith the TYPE and NAME= 
  2168. messages to call the related methods, enter: 
  2169.  
  2170. newaccount = savings~new
  2171. say asav~type
  2172. asav~name = 'John Smith'
  2173.  
  2174. Now that you've read how to create your own classes, what types of classes 
  2175. might you want to create? The next section explains what you can do using the 
  2176. different types of classes. 
  2177.  
  2178.  
  2179. ΓòÉΓòÉΓòÉ 5.6. Types of Classes ΓòÉΓòÉΓòÉ
  2180.  
  2181. In REXX there are three class types: 
  2182.  
  2183.      Object classes 
  2184.      Abstract classes 
  2185.      Mixin classes 
  2186.  
  2187.  An object class (the default) can create instance objects in response to 
  2188.  receiving a NEW or ENHANCED message. An abstract class serves mainly to 
  2189.  organize other classes in the hierarchy and define their message interface, 
  2190.  rather than create objects. A mixin class, through multiple inheritance, can 
  2191.  be designated as an additional superclass to a class. The mixin class 
  2192.  typically possesses methods useful to the class that inherits it, but these 
  2193.  must be specifically added because they lie outside the class's normal line of 
  2194.  inheritance. 
  2195.  
  2196.  The following sections explain these class types in more detail. 
  2197.  
  2198.  
  2199. ΓòÉΓòÉΓòÉ 5.6.1. Object Classes ΓòÉΓòÉΓòÉ
  2200.  
  2201. An object class is like a factory for producing instances. An object class 
  2202. creates instances and provides methods that these instances can use. At the 
  2203. time of its creation, an instance acquires all instance methods of the class it 
  2204. belongs to. If a class adds new methods later, existing instances do not 
  2205. acquire them. Instances created after the new methods do acquire them. 
  2206.  
  2207. Because classes define methods for their instances, and methods define the 
  2208. variables instances use, object classes are a complete blueprint for creating 
  2209. REXX instances. The Array class is an example of an object class. 
  2210.  
  2211.  
  2212. ΓòÉΓòÉΓòÉ 5.6.2. Abstract Classes ΓòÉΓòÉΓòÉ
  2213.  
  2214. An abstract class defines methods its subclasses can inherit, but typically has 
  2215. no instances. Rather, it serves to organize other classes in the hierarchy. An 
  2216. abstract class can be used to "filter out" a group of shared methods from a 
  2217. number of subclasses, so they do not have to exist in two places. 
  2218.  
  2219. An abstract class pushes common elements farther up the hierarchy, thus 
  2220. providing a higher level of organization. By filtering out and moving common 
  2221. methods upwards, the abstract class refines the message interface for its 
  2222. subclasses. This lays the groundwork for polymorphism, creating well-defined 
  2223. interfaces for users of the hierarchy. Abstract classes inherit the instance 
  2224. methods of the Class class. 
  2225.  
  2226. You can create a new abstract class the same way you create an object class. 
  2227. Just use a simple ::CLASS directive; no options are required. While abstract 
  2228. classes are not intended for creating instances, REXX does not prevent you from 
  2229. doing so. 
  2230.  
  2231.  
  2232. ΓòÉΓòÉΓòÉ 5.6.3. Mixin Classes ΓòÉΓòÉΓòÉ
  2233.  
  2234. The mixin class lets you optionally add a set of instance and class methods to 
  2235. one or more other classes using inheritance. You use mixins, therefore, to 
  2236. extend the scope of a class beyond the usual lines of inheritance defined by 
  2237. the hierarchy. Think of it as widening a class's inheritance to accept methods 
  2238. from a sibling or cousin, as well as a parent. When a class inherits from more 
  2239. than just its parent superclass, we call this multiple inheritance. 
  2240.  
  2241. You can add mixin methods to a class by using the INHERIT option on the ::CLASS 
  2242. directive. The class to be inherited must be a mixin class. During class 
  2243. creation and multiple inheritance, subclasses inherit both class and instance 
  2244. methods from their superclasses. 
  2245.  
  2246. A mixin's first non-mixin superclass is its base class. Any subclass of a 
  2247. mixin's base class can directly or indirectly inherit a mixin; other classes 
  2248. cannot. 
  2249.  
  2250. To create a new mixin class, use the ::CLASS directive with the MIXINCLASS 
  2251. option. A mixin class is also an object class and so can create its own 
  2252. instances. 
  2253.  
  2254.  
  2255. ΓòÉΓòÉΓòÉ 5.7. Metaclasses ΓòÉΓòÉΓòÉ
  2256.  
  2257. A metaclass is a class you can use to create another class. REXX provides just 
  2258. one metaclass, the "Class" class. We've said that a class is a factory for 
  2259. creating instances, and the "Class" class is a factory for creating factories. 
  2260. Whenever you create a new factory, or class, the new class is an instance of 
  2261. Class. The instance methods of Class provide the operations needed to run the 
  2262. new factories. These instance methods are inherited by the new factory as its 
  2263. class methods. 
  2264.  
  2265. The classes REXX provides do not permit changes or additions to their method 
  2266. definitions. As a result, all new factories inherit these unchangeable actions 
  2267. from the "Class" class, and thus operate the same way. So if you want to create 
  2268. a new class--a new factory--that behaves differently from the others, you can 
  2269. do one of two things: 
  2270.  
  2271.    1. Write additional class methods for the new class, using the ::METHOD 
  2272.       directive with the CLASS option 
  2273.  
  2274.    2. Use a metaclass 
  2275.  
  2276.  You can always do 1, and most of the time you will only want to do 1. But if 
  2277.  you plan to create many factories with the same operational changes, you might 
  2278.  elect to do 2. 
  2279.  
  2280.  Any metaclass you create will be a subclass of the Class class. To make your 
  2281.  own metaclass, specify class as a SUBCLASS option in the ::CLASS directive: 
  2282.  
  2283.   /* Create a new metaclass  */
  2284.   ::class your_metaclass subclass class
  2285.  
  2286.  The instance methods of your_metaclass will ultimately become the class 
  2287.  methods for any new class created using your_metaclass. For example, you could 
  2288.  create a metaclass called InstanceCounter that includes instance methods for 
  2289.  tracking how many instances the class creates: 
  2290.  
  2291.   /* Create a new metaclass that will count its instances        */
  2292.   ::class InstanceCounter subclass class
  2293.     ::method init
  2294.      .
  2295.      .
  2296.      .
  2297.  
  2298.  Now, instead of having to add instance-counting class methods to other new 
  2299.  classes you write, you can make InstanceCounter their metaclass. When you 
  2300.  create the new class, just specify InstanceCounter as a METACLASS option in 
  2301.  the ::CLASS directive. If you were creating a Point class, it might look like 
  2302.  this: 
  2303.  
  2304.   /* Create a public Point class using the InstanceCounter metaclass  */
  2305.   ::class point public metaclass InstanceCounter
  2306.     ::method init
  2307.      .
  2308.      .
  2309.      .
  2310.  
  2311.  Instance methods in your new InstanceCounter metaclass will become the class 
  2312.  methods of the Point class, and any other classes you create using a similar 
  2313.  directive. Here is a complete example: 
  2314.  
  2315.   /* a metaclass example */
  2316.  
  2317.   a = .point~new(1,1)                   /* Create point instances       */
  2318.   say 'Created point instance' a        /* a, b, and c                  */
  2319.   b = .point~new(2,2)
  2320.   say 'Created point instance' b
  2321.   c = .point~new(3,3)
  2322.   say 'Created point instance' c
  2323.  
  2324.                                         /* Ask the Point class how many */
  2325.                                         /* instances it has created     */
  2326.   say 'The point class has created' .point~instances 'instances.'
  2327.  
  2328.                                         /* Create a new metaclass that  */
  2329.                                         /* will count its instances     */
  2330.   ::class InstanceCounter subclass class
  2331.     ::method init                       /* Create an INIT method to     */
  2332.       expose instanceCount              /* initialize instanceCount     */
  2333.       instanceCount = 0                 /* Forward INIT to superclass   */
  2334.  
  2335.       .message~new(self, .array~of('INIT',super), 'a', arg(1,'A'))~send
  2336.  
  2337.     ::method new                        /* Create a NEW instance method */
  2338.       expose instanceCount              /* Create a new instance        */
  2339.       instanceCount = instanceCount + 1 /* Bump the count               */
  2340.  
  2341.                                         /* Forward NEW to superclass    */
  2342.       return .message~new(self, .array~of('NEW',super), 'a', arg(1,'A'))~send
  2343.  
  2344.  
  2345.     ::method instances                  /* Create an INSTANCES method   */
  2346.       expose instanceCount              /* Return the instance count    */
  2347.       return instanceCount
  2348.  
  2349.                                         /* Create Point class using     */
  2350.                                         /* InstanceCounter metaclass    */
  2351.   ::class point public metaclass InstanceCounter
  2352.     ::method init                       /* Create an INIT method        */
  2353.       expose xVal yVal                  /* Set object variables         */
  2354.       use arg xVal, yVal                /* as passed on NEW             */
  2355.  
  2356.     ::method string                     /* Create a STRING method       */
  2357.       expose xVal yVal                  /* Use object variables         */
  2358.       return '('xVal','yVal')'          /* to return string value       */
  2359.  
  2360.  
  2361. ΓòÉΓòÉΓòÉ 6. A Closer Look at Objects ΓòÉΓòÉΓòÉ
  2362.  
  2363. Now that you know about classes and how to create them, we'll cover the 
  2364. mechanics of using objects and methods in more detail. First, here is a quick 
  2365. refresher. 
  2366.  
  2367. We have said that a REXX object consists of: 
  2368.  
  2369.      Actions coded as methods 
  2370.      Characteristics, coded as variables, and their values, sometimes referred 
  2371.       to as "state data" 
  2372.  
  2373.  Sending a message to an object causes it to perform a related action. The 
  2374.  method whose name matches the message performs the action. The message is the 
  2375.  interface to the object, and with information hiding, only methods that belong 
  2376.  to an object can access its variables. 
  2377.  
  2378.  Objects are grouped hierarchically into classes. The class at the very top of 
  2379.  the hierarchy is the Object class. Everything below it in the hierarchy 
  2380.  belongs to the Object class and is therefore an object. As a result, all 
  2381.  classes are objects. 
  2382.  
  2383.  In a class hierarchy, classes, superclasses, and subclasses are relative to 
  2384.  one another. Unless designated otherwise, any class directly above a class in 
  2385.  the hierarchy is a superclass. And any class below is a subclass. 
  2386.  
  2387.  From a class object you can create instances of the class. Instances are 
  2388.  merely similar objects that fit the template of the class; they belong to the 
  2389.  class, but are not classes themselves. Instances are the most basic, most 
  2390.  elemental of objects. 
  2391.  
  2392.  Both classes and their instances are objects. All objects contain variables 
  2393.  and methods, and so this is true for class objects. The methods a class 
  2394.  provides for use by its various instances are called instance methods. In 
  2395.  effect, these define which messages an instance can respond to. Instance 
  2396.  methods are by far the most common methods in REXX, and here we simply call 
  2397.  them "methods." 
  2398.  
  2399.  The methods available to the class object itself are called class methods. 
  2400.  (They are actually the instance methods of the Class class.) They define 
  2401.  messages that only the class--and not its instances--can respond to. Class 
  2402.  methods generally exist to create instances and are much less common. When 
  2403.  referring to these rarer methods, we will be sure to identify them 
  2404.  specifically as "class methods." 
  2405.  
  2406.  
  2407.   Instance methods and class methods
  2408.  
  2409.  
  2410.         Instance methods     Class methods
  2411.         ----------------     -------------
  2412.         ADD           CREATE_INSTANCE
  2413.         SUBTRACT
  2414.    ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇ  MULTIPLY    Number      
  2415.    Γöé     DIVIDE     class ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2416.    Γöé              Γöé
  2417.    Γöé         ΓöîΓöÇΓöÇΓö¼ΓöÇΓöÇΓö¼ΓöÇΓöÇΓö╝ΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2418.    Γöé         Γöé  Γöé  Γöé  Γöé  Γöé   Γöé
  2419.    ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 1  2  3  4  5 ... n
  2420.  
  2421.               instances
  2422.  
  2423.  
  2424. ΓòÉΓòÉΓòÉ 6.1. Using Objects in REXX Clauses ΓòÉΓòÉΓòÉ
  2425.  
  2426. To extend our exploration of objects, let's begin with the Myarray object. 
  2427. These examples with Myarray illustrate how to use new objects in REXX clauses. 
  2428. In the expression: 
  2429.  
  2430. myarray=.array~new(5)
  2431.  
  2432. a new instance of the Array class, Myarray, is created. (Recall that a period 
  2433. precedes a class name in an expression, to distinguish the class from other 
  2434. variables.) Our Myarray array object has five elements. 
  2435.  
  2436. After Myarray is created, you'll want to assign values to it. One way is with 
  2437. the PUT method. PUT has two arguments, which must be enclosed in parentheses. 
  2438. The first argument is the string to be placed in the element. The second is the 
  2439. number of the element in which to place the string. Here, we associate the 
  2440. string object "Hello" with the third element of Myarray: 
  2441.  
  2442. myarray~put("Hello",3)
  2443.  
  2444. REXX dynamically adjusts the size of the array to accommodate the new element. 
  2445.  
  2446. One way to retrieve values from an array object is by sending it an AT message. 
  2447. In the next example, the SAY instruction displays the third element of Myarray: 
  2448.  
  2449. say myarray~at(3)
  2450.  
  2451. Results:
  2452.  
  2453. Hello
  2454.  
  2455. The SAY instruction expects the string object as input, and that is precisely 
  2456. what AT returns. So what happens if you put a non-string object in the SAY 
  2457. instruction? SAY sends a STRING message to the object. The STRING method for 
  2458. REXX's built-in objects returns a human-readable string representation for the 
  2459. object. In our example, the STRING method for Myarray returns the string "an 
  2460. array": 
  2461.  
  2462. say myarray  /* SAY sends STRING message to Myarray */
  2463.  
  2464. Results:
  2465.  
  2466. an array
  2467.  
  2468. Whenever a method returns a string, you can use it within expressions that 
  2469. require a string. Here, the element of the array that AT returns is a string, 
  2470. so you can put an expression containing the AT method inside a string function 
  2471. like COPIES(): 
  2472.  
  2473. say copies(myarray~at(3),4)
  2474.  
  2475. Results:
  2476. HelloHelloHelloHello
  2477.  
  2478. This example gets the same result using only methods: 
  2479.  
  2480. say myarray~at(3)~copies(4)
  2481.  
  2482. Notice that the expression is evaluated from left to right. You can also use 
  2483. parentheses to enforce an order of evaluation. 
  2484.  
  2485. Almost all messages are sent using the twiddle, but there are exceptions. The 
  2486. exceptions have been made to improve the reliability of the language. This 
  2487. example uses the []= method (left-bracket right-bracket equal-sign) and [] 
  2488. method to set and retrieve array elements: 
  2489.  
  2490. myarray[4]="the fourth element"
  2491. say myarray[4]
  2492.  
  2493. Although the above two statements look like an ordinary array assignment and 
  2494. array reference, they are really messages to the Myarray object. You can prove 
  2495. it to yourself by executing these equivalent statements, which use the twiddle 
  2496. to send the messages. 
  2497.  
  2498. myarray~"[]="("a new test",4)
  2499. say myarray~"[]"(4)
  2500.  
  2501. Similarly, expression operators (such as +,-,/, and *) are actually methods. 
  2502. But you don't have to use the twiddle to send them: 
  2503.  
  2504. say 2+3      /* Displays 5 */
  2505. say 2~'+'(3) /* Displays 5 */
  2506.  
  2507. In the second SAY statement, quotes are needed around the + message because it 
  2508. is a character not allowed in a REXX symbol. 
  2509.  
  2510. Now let's move on to methods. There are three in particular that you'll use 
  2511. often. 
  2512.  
  2513.  
  2514. ΓòÉΓòÉΓòÉ 6.2. Common Methods You'll Want to Define ΓòÉΓòÉΓòÉ
  2515.  
  2516. When running your program, three methods that REXX looks for, and runs 
  2517. automatically when appropriate, are INIT, UNINIT, and STRING. 
  2518.  
  2519.  
  2520. ΓòÉΓòÉΓòÉ 6.2.1. Initializing Instances Using INIT ΓòÉΓòÉΓòÉ
  2521.  
  2522. Recall that object classes are those that can create instance objects. When 
  2523. these instances require initialization, you'll want to define an INIT method to 
  2524. set a particular starting value or initiate some startup processing. REXX will 
  2525. look for an INIT method whenever a new object is created; if INIT is there, 
  2526. REXX runs it. 
  2527.  
  2528. The purpose of initialization is to ensure that the variable is set correctly 
  2529. before using it in an operation. If an INIT method is defined, REXX runs it 
  2530. after creating the instance. Any initialization arguments specified on the NEW 
  2531. or ENHANCED message are passed to the INIT method, which may use them to set 
  2532. the initial state of object variables. 
  2533.  
  2534. If an instance has more than one INIT method (for example, INIT is defined in 
  2535. multiple classes), each INIT method must forward the INIT message up the 
  2536. hierarchy and run the topmost version of INIT, to properly initialize the 
  2537. instance. An example in the next section demonstrates use of INIT. 
  2538.  
  2539.  
  2540. ΓòÉΓòÉΓòÉ 6.2.2. Returning String Data Using STRING ΓòÉΓòÉΓòÉ
  2541.  
  2542. Another useful method is STRING. The STRING method is a handy way to access 
  2543. object data and return it in string form for use by your program. When a SAY 
  2544. instruction is processed in REXX, REXX automatically sends a STRING message to 
  2545. the object specified in the expression. In doing this, REXX uses the STRING 
  2546. method of the Object class and returns a human-readable string representation 
  2547. for the object. For example, if you instruct REXX to say a, and a is an array 
  2548. object, REXX returns "an array." You can take advantage of this automatic use 
  2549. of STRING by overriding REXX's STRING method with your own, and extract the 
  2550. object data itself--in this case, the actual array data. 
  2551.  
  2552. Let's look at two programs that demonstrate STRING and INIT. In the first 
  2553. program, the Part class is created, and along with it, the two methods under 
  2554. discussion, STRING and INIT: 
  2555.  
  2556. /* PARTDEF.CMD -- Class and method definition file */
  2557.  
  2558. /* Define the Part class as a public class */
  2559. ::class part public
  2560.  
  2561. /* Define the INIT method to initialize object variables */
  2562. ::method init
  2563. expose name description number
  2564. use arg name, description, number
  2565.  
  2566. /* Define the STRING method to return a string with the part name */
  2567. ::method string
  2568. expose name
  2569. return "Part name:" name
  2570.  
  2571. On the ::CLASS directive, the keyword PUBLIC indicates that the class can be 
  2572. shared with other programs. The two ::METHOD directives define INIT and STRING. 
  2573. Whenever REXX creates a new instance of a class, it calls the INIT method for 
  2574. the class. (We'll see how to create an instance of a class in the next 
  2575. program.) Our INIT method uses an EXPOSE instruction to make the name, 
  2576. description, and number variables available to other methods. These exposed 
  2577. variables are object variables, and are associated with a particular instance 
  2578. of a class. 
  2579.  
  2580.  
  2581. Instances in the Part class
  2582.  
  2583.  
  2584.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  2585.   Γöé
  2586.   Γöé
  2587. Part class
  2588.  
  2589. part instance
  2590.  (name='Widget')
  2591.  (description='A small widge')
  2592.  (number=12345)
  2593.  
  2594. part instance
  2595.  (name='Framistat')
  2596.  (description='A device to control frams')
  2597.  (number=899)
  2598.  
  2599. part instance
  2600.  (name='Defragulator')
  2601.  (description='Removes frags from framistats')
  2602.  (number=01045)
  2603.  
  2604. INIT expects to be passed three arguments. The USE ARG instruction assigns 
  2605. these three arguments to the name, description, and number variables, 
  2606. respectively. Since those variables are exposed, the values are available to 
  2607. other methods. 
  2608.  
  2609. The STRING method returns the string "Part name: ", followed by the name of a 
  2610. part. The STRING method doesn't expect any arguments. It uses the EXPOSE 
  2611. instruction to tap into the object variables. The RETURN instruction returns 
  2612. the result string. 
  2613.  
  2614. Now let's see how to use the Part class: 
  2615.  
  2616. /* USEPART.CMD  - use the Part class          */
  2617. myparta=.part~new('Widget','A small widge',12345)
  2618. mypartb=.part~new('Framistat','Device to control frams',899)
  2619. say myparta
  2620. say mypartb
  2621. exit
  2622. ::requires partdef
  2623.  
  2624. The USEPART program creates two "parts", which are instances of the Part class. 
  2625. It then displays the names of the two parts. 
  2626.  
  2627. REXX processes all directives before running your program. The ::REQUIRES 
  2628. directive indicates that the program needs access to public class definitions 
  2629. that are in another program. In this case, the ::REQUIRES directive refers to 
  2630. the PARTDEF program, which contains the Part definition. 
  2631.  
  2632. Next, look at the two assignment statements for MypartA and MypartB. These 
  2633. assignment statements create two objects that are instances of the Part class. 
  2634. The objects are created by sending a NEW message to the Part class. The NEW 
  2635. message causes the INIT method to be invoked as part of object creation. Our 
  2636. INIT method takes the three arguments you provide and makes them part of the 
  2637. object's own exclusive set of variables, called a variable pool. Each object 
  2638. has its own variable pool (name, description, and number). 
  2639.  
  2640. The SAY instruction, as we mentioned earlier, sends a STRING message to the 
  2641. object. In the first SAY instruction, the STRING message is sent to MypartA. 
  2642. The STRING method accesses the Name object variable for MypartA and returns it 
  2643. as part of a string. In the second SAY instruction, the STRING message is sent 
  2644. again, but to a different object: MypartB. Because the STRING method is invoked 
  2645. for MypartB, it automatically accesses the variables for MypartB. Recall that 
  2646. you don't need to pass the name of the object to the method in order to 
  2647. distinguish different sets of object variables; REXX keeps track of them for 
  2648. you. 
  2649.  
  2650. Another way to define classes is by using the SUBCLASS method. You can send a 
  2651. SUBCLASS method to any desired superclass to create a class. 
  2652.  
  2653.  
  2654. ΓòÉΓòÉΓòÉ 6.2.3. Uninitializing and Deleting Instances Using UNINIT ΓòÉΓòÉΓòÉ
  2655.  
  2656. Object classes, while able to create instances, have no direct control over 
  2657. their deletion. If you assign a new value to a variable, REXX automatically 
  2658. reclaims the storage for the old value in a process called garbage collection. 
  2659.  
  2660. If variables of other objects no longer reference an instance, REXX 
  2661. automatically reclaims that instance. If the instance has allocated other 
  2662. system resources, you must release them at this time using an UNINIT method. 
  2663. REXX cannot automatically release these resources because it is unaware that 
  2664. the instance has allocated them. 
  2665.  
  2666. In the following example, the value passed to text is initialized by REXX using 
  2667. INIT and deleted by REXX using UNINIT. This program makes visible REXX's 
  2668. automatic invocation of INIT and UNINIT by revealing its processing on the 
  2669. screen using the SAY instruction: 
  2670.  
  2671. /* UNINIT.CMD -- example of UNINIT processing */
  2672.  
  2673. a=.scratchpad~new('Of all the things I''ve lost')
  2674. a=.scratchpad~new('I miss my mind the most')
  2675. say 'Exiting program.'
  2676. exit
  2677.  
  2678. ::class scratchpad
  2679.  
  2680.   ::method init
  2681.     expose text
  2682.     use arg text
  2683.     say 'Remembering' text
  2684.  
  2685.   ::method uninit
  2686.     expose text
  2687.     say 'Forgetting' text
  2688.     return
  2689.  
  2690. Circumstances dictate when uninitialization processing is needed--when a 
  2691. message object holds an unreported error that should be reported and cleared, 
  2692. for example. If an object requires uninitialization, define an UNINIT method to 
  2693. specify the processing you want. 
  2694.  
  2695. If UNINIT is defined, REXX runs it before reclaiming the object's storage. If 
  2696. an instance has more than one UNINIT method (for example, UNINIT is defined in 
  2697. multiple classes), each UNINIT method is responsible for sending the UNINIT 
  2698. message up the hierarchy (using the SUPERCLASS overrides) to run the topmost 
  2699. version of INIT. 
  2700.  
  2701.  
  2702. ΓòÉΓòÉΓòÉ 6.3. Special Variables ΓòÉΓòÉΓòÉ
  2703.  
  2704. When writing methods, you can use some special variables available in REXX. A 
  2705. special variable is one that may be set automatically during processing of a 
  2706. REXX program. There are five such variables: 
  2707.  
  2708.  RC  is set to the return code from any executed command (including those 
  2709.      submitted with the ADDRESS instruction). After the trapping of ERROR or 
  2710.      FAILURE conditions, it is also set to the command return code. When the 
  2711.      SYNTAX condition is trapped, RC is set to the syntax error number (1-99). 
  2712.      RC is unchanged when any other condition is trapped. 
  2713.  
  2714.      Note:  Commands executed manually while tracing interactively do not 
  2715.             change the value of RC. 
  2716.  
  2717.  RESULT is set by a RETURN instruction(**) in a subroutine that has been 
  2718.      called, or a method that was activated by a message instruction, if the 
  2719.      RETURN instruction specifies an expression. If the RETURN instruction has 
  2720.      no expression on it then RESULT is dropped (becomes uninitialized). 
  2721.  
  2722.  SELF is set when a method is activated. Its value is the object that forms the 
  2723.      execution context for the method (that is, the receiver object of the 
  2724.      activating message). 
  2725.  
  2726.      You can use SELF to: 
  2727.  
  2728.          Run a method in an object in which a method is already running. For 
  2729.           example, a FIND_CLUES method is running in an object called 
  2730.           Mystery_Novel. When FIND_CLUES finds a clue, it sends a 
  2731.           READ_LAST_PAGE message to Mystery_Novel: 
  2732.  
  2733.                     self~read_last_page
  2734.  
  2735.          Pass references about an object to the methods of other objects. For 
  2736.           example, a SING method is running in object Song. The code: 
  2737.  
  2738.                     Singer2~duet(self)
  2739.  
  2740.           would give the DUET method access to the same Song. 
  2741.  
  2742.  SIGL is set to the line number of the last instruction that caused a transfer 
  2743.      of control to a label (that is, any SIGNAL, CALL, internal function call, 
  2744.      or trapped condition). 
  2745.  
  2746.  SUPER is set when a method is activated. Its value is the class object that is 
  2747.      the usual starting point for a superclass method lookup for the SELF 
  2748.      object. This is the first immediate superclass of the class that defined 
  2749.      the method currently running. 
  2750.  
  2751.      The special variable SUPER lets you call a method in the superclass of an 
  2752.      object. For example, the following Savings class has INIT methods that the 
  2753.      Savings class, Account class, and Object class define. 
  2754.  
  2755.           ::class Account
  2756.  
  2757.             ::method INIT
  2758.               expose balance
  2759.               use arg balance
  2760.               self~init:super    /* Forwards to the Object INIT method  */
  2761.  
  2762.             ::method TYPE
  2763.               return "an account"
  2764.  
  2765.             ::method name attribute
  2766.  
  2767.           ::class Savings subclass Account
  2768.  
  2769.             ::method INIT
  2770.               expose interest_rate
  2771.               use arg balance, interest_rate
  2772.               self~init:super(balance)       /* Forwards to the Account INIT method */
  2773.  
  2774.             ::method type
  2775.               return "a savings account"
  2776.  
  2777.      When the INIT method of the Savings class is called, the variable SUPER is 
  2778.      set to the Account class object. The instruction: 
  2779.  
  2780.           self~init:super(balance)
  2781.  
  2782.      calls the INIT method of the Account class rather than recursively calling 
  2783.      the INIT method of the Savings class. When the INIT method of the Account 
  2784.      class is called, the variable SUPER is assigned to the Object class. 
  2785.      Specifying 
  2786.  
  2787.           self~init:super
  2788.  
  2789.      calls the INIT method the Object class defines. 
  2790.  
  2791.  You can alter these variables, just like any other variable, but REXX 
  2792.  continues to set RC, RESULT, and SIGL automatically when appropriate. EXPOSE, 
  2793.  PROCEDURE, USE, and DROP instruction also affect these variables in their 
  2794.  usual way. 
  2795.  
  2796.  Certain other information is available to a REXX program. This usually 
  2797.  includes the name the program was called by and the source of the program 
  2798.  (which are available using the PARSE SOURCE instruction.) In addition, PARSE 
  2799.  VERSION makes available the language version and date of REXX implementation 
  2800.  that is running. The built-in functions ADDRESS, DIGITS, FUZZ, FORM, and TRACE 
  2801.  return other settings that affect the execution of a program. 
  2802.  
  2803.  
  2804. ΓòÉΓòÉΓòÉ 6.4. Public, Local, and Built-in Environment Objects ΓòÉΓòÉΓòÉ
  2805.  
  2806. In addition to the special variables, REXX provides a unique set of objects, 
  2807. called environment objects. Environment objects are members of the Object 
  2808. class, and the Object class only. They are like class objects whose class 
  2809. contains only one member, the object itself. REXX makes the following 
  2810. environment objects available: 
  2811.  
  2812.  
  2813. ΓòÉΓòÉΓòÉ 6.4.1. The Environment Object (.environment) ΓòÉΓòÉΓòÉ
  2814.  
  2815. The Environment object is a directory of public objects that are always 
  2816. accessible. To place something in the Environment directory, use the form: 
  2817.  
  2818. .environment~your.object = value
  2819.  
  2820. Include a period (.) in any object name you use, to avoid conflicts with 
  2821. current or future REXX entries to the Environment directory. To retrieve your 
  2822. object, use the form: 
  2823.  
  2824. say .environment~your.object
  2825.  
  2826. To give your object definition limited retrievability, place it in .local, 
  2827. where the scope is the current process only. 
  2828.  
  2829. Use an environment symbol to access the entries of this directory. An 
  2830. environment symbol starts with a period and has at least one other character, 
  2831. and its second character cannot be a digit. You have seen environment symbols 
  2832. earlier; for example in: 
  2833.  
  2834. asav = .savings~new
  2835.  
  2836. .Savings is an environment symbol, and refers to the Savings class. The classes 
  2837. you create can be referenced with an environment symbol, and there is an 
  2838. environment symbol for each REXX-defined class, as well as for each of the 
  2839. unique objects this section describes, such as the NIL object. 
  2840.  
  2841.  
  2842. ΓòÉΓòÉΓòÉ 6.4.1.1. The NIL Object (.nil) ΓòÉΓòÉΓòÉ
  2843.  
  2844. The NIL object is a special environment object that does not contain data. It 
  2845. represents the absence of an object, the way a null string represents a string 
  2846. with no characters. Its only methods are those of the Object class. You use the 
  2847. NIL object (rather than the null string) to test for the absence of data in an 
  2848. array entry: 
  2849.  
  2850. if board[row,column] = .nil
  2851. then ...
  2852.  
  2853. All the environment objects REXX provides are single symbols, but use compound 
  2854. symbols when you create your own, to avoid conflicts with future REXX-defined 
  2855. entries. 
  2856.  
  2857. Objects in the Environment object--also called the Global environment 
  2858. object--are available to all programs running on your system. Objects in the 
  2859. Local environment object (below) are available to programs running within the 
  2860. same process. 
  2861.  
  2862.  
  2863. ΓòÉΓòÉΓòÉ 6.4.2. The Local Environment Object (.local) ΓòÉΓòÉΓòÉ
  2864.  
  2865. The Local environment object is is a directory of process-specific objects that 
  2866. are always accessible. To place something in the Local environment directory, 
  2867. use the form: 
  2868.  
  2869. .local~your.object = value
  2870.  
  2871. Be sure to include a period (.) in any object name you use, to avoid conflicts 
  2872. with current or future REXX entries to the Local directory. To retrieve your 
  2873. object, use the form: 
  2874.  
  2875. say .local~your.object
  2876.  
  2877. The scope of .local is the current process. To give your object definition 
  2878. wider retrievability, place it in .environment, where the object will be shared 
  2879. across environments. 
  2880.  
  2881. Access objects in the Local environment object the same way as in the 
  2882. Environment object. REXX provides the following objects in the Local 
  2883. environment: 
  2884.  
  2885.  .error The Error object (the default error stream) where REXX writes error 
  2886.      messages and trace output to. 
  2887.  
  2888.  .input The Input object (the default input stream), which is the source for 
  2889.      the PARSE LINEIN instruction, the LINEIN method of the Stream class, and 
  2890.      (if you don't specify a stream name) the LINEIN built-in function. It is 
  2891.      also the source of the PULL and PARSE PULL instructions if the external 
  2892.      data queue is empty. 
  2893.  
  2894.  .output The Output object (the default output stream), which is the 
  2895.      destination of output from the SAY instruction, the LINEOUT method 
  2896.      (.OUTPUT~LINEOUT), and (if you don't specify a stream name) the LINEOUT 
  2897.      built-in function. You can replace this object in the environment to 
  2898.      direct such output elsewhere (for example, to a transcript window). 
  2899.  
  2900.  .som The SOM server object. 
  2901.  
  2902.  .somclass The SOMClass class. 
  2903.  
  2904.  .somclassmgrobject The SOMClassMgrObject object. 
  2905.  
  2906.  .somobject The SOMObject class. 
  2907.  
  2908.  
  2909. ΓòÉΓòÉΓòÉ 6.4.3. Built-In Environment Objects ΓòÉΓòÉΓòÉ
  2910.  
  2911. REXX provides some other environment objects all programs can use. To access 
  2912. these built-in objects, you use the special environment symbols whose first 
  2913. character is `.'. 
  2914.  
  2915.  .methods The .methods environment symbol identifies a directory of methods 
  2916.      that ::METHOD directives in the currently running program define. The 
  2917.      directory indexes are the method names. The directory values are the 
  2918.      method objects. Only methods that are not preceded by a ::CLASS directive 
  2919.      are in the .methods directory. If there are no such methods, the .methods 
  2920.      symbol has the default value of `.METHODS'. Here's an example: 
  2921.  
  2922.           use arg class, methname
  2923.           class~define(methname,.methods['a'])
  2924.           ::method a
  2925.           use arg text
  2926.           say text
  2927.  
  2928.  .rs .rs is set to the return status from any executed command (including those 
  2929.      submitted with the ADDRESS instruction). The .rs environment symbol has a 
  2930.      value of -1 when a command returns a FAILURE condition, a value of 1 when 
  2931.      a command returns an ERROR condition, and a value of 0 when a command 
  2932.      indicates successful completion. The value of .rs is also available after 
  2933.      trapping of the ERROR or FAILURE condition. 
  2934.  
  2935.      Note:  Commands executed manually while tracing interactively do not 
  2936.             change the value of .rs. The initial value of .rs is 0. 
  2937.  
  2938.  
  2939. ΓòÉΓòÉΓòÉ 6.4.4. The Default Search Order for Environment Objects ΓòÉΓòÉΓòÉ
  2940.  
  2941. When you use an environment symbol, REXX performs a series of searches to see 
  2942. if the environment symbol has an assigned value. The search locations and their 
  2943. ordering are: 
  2944.  
  2945.    1. The directory of classes declared on ::CLASS directives within the 
  2946.       current program file. 
  2947.  
  2948.    2. The directory of PUBLIC classes declared on ::CLASS directives of other 
  2949.       files included with a ::REQUIRES directive. 
  2950.  
  2951.    3. The program local environment directory. The local environment includes 
  2952.       process-specific objects such as the .INPUT and .OUTPUT objects. You can 
  2953.       directly access the local environment directory by using the .Local 
  2954.       environment symbol. 
  2955.  
  2956.    4. The global environment directory. The global environment includes all 
  2957.       "permanent" REXX objects such as the REXX supplied classes (.ARRAY and so 
  2958.       on) and constants such as .TRUE and .FALSE. You can directly access the 
  2959.       global environment by using the .environment environment symbol or using 
  2960.       the VALUE built-in function with a null string for the selector argument. 
  2961.  
  2962.    5. REXX defined symbols. Other simple environment symbols are reserved for 
  2963.       use by REXX for built-in objects. The currently defined built-in objects 
  2964.       are .RS and .METHODS. 
  2965.  
  2966.  If an entry is not found for an environment symbol, then the default character 
  2967.  string value is used. 
  2968.  
  2969.  Note:  You can place entries in both the .local and .environment directories 
  2970.         for programs to use. To avoid conflicts with future REXX defined 
  2971.         entries, it is recommended that entries you place in either of these 
  2972.         directories include at least one period in the entry name. 
  2973.  
  2974.  Example: 
  2975.  
  2976.   /* establish a global settings directory */
  2977.   .local~setentry('MyProgram.settings', .directory~new)
  2978.  
  2979.  
  2980. ΓòÉΓòÉΓòÉ 6.5. Determining the "Scope" of Methods and Variables ΓòÉΓòÉΓòÉ
  2981.  
  2982. Methods interact with variables and their associated data. But a method cannot 
  2983. interact with just any variable. Certain methods and variables are designed to 
  2984. work together. A method designates the variables it wants to work with by 
  2985. exposing them using an EXPOSE instruction. The exposed methods are called 
  2986. object variables. Exposing variables confines them to an object; in 
  2987. object-oriented terms, we say they are encapsulated. This protects the object 
  2988. variables' data from being changed by "unauthorized" methods belonging to other 
  2989. objects. 
  2990.  
  2991.  
  2992. ΓòÉΓòÉΓòÉ 6.5.1. Objects with a Class Scope ΓòÉΓòÉΓòÉ
  2993.  
  2994. Actually, this encapsulation usually takes place at the class level. The class 
  2995. is designed as a template of methods and variables--the common "mold" from 
  2996. which all instances for that class will be stamped. The instances themselves 
  2997. retain only the values of their variables. 
  2998.  
  2999. Within the hierarchy, then, it is the class structure that ensures the 
  3000. integrity of a class's variables, so that only those methods designed to 
  3001. operate on them, do. (The class structure also provides for easy updating of 
  3002. the method code. If a method requires a change, you only have to change it 
  3003. once, at the class level. The change then is acquired by all the instances 
  3004. sharing the method.) 
  3005.  
  3006. Associated methods and variables are said to have a certain scope, and in this 
  3007. case, that scope is the class to which they belong. In other words, the scope 
  3008. of a method and variable group defines or limits the range of objects that can 
  3009. share that group. Typically, a scope consists of the methods and object 
  3010. variables confined to a single class. 
  3011.  
  3012.  
  3013. Scope of the Number class
  3014.  
  3015.  
  3016.  ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇScope of the Number classΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3017.  Γöé                       Γöé
  3018.  Γöé Instance methods     Instance variables Γöé
  3019.  Γöé ----------------     ------------------ Γöé
  3020.  Γöé ADD           number       Γöé
  3021.  Γöé SUBTRACT                  Γöé
  3022.  Γöé MULTIPLY                  Γöé
  3023.  Γöé DIVIDE                   Γöé
  3024.  Γöé                       Γöé
  3025.  Γöé                       Γöé
  3026.  Γöé          Number           Γöé
  3027.  ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ  class  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3028.            Γöé
  3029.        ΓöîΓöÇΓöÇΓö¼ΓöÇΓöÇΓö¼ΓöÇΓöÇΓö╝ΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3030.        Γöé  Γöé  Γöé  Γöé  Γöé   Γöé
  3031.        1  2  3  4  5 ... n
  3032.  
  3033.          instances
  3034.  
  3035. Each class in a class hierarchy has a separate scope from every other class. 
  3036. This is what allows a variable in a subclass to have the same name as a 
  3037. variable in a superclass, even though the methods that use the variables may be 
  3038. completely different. But scopes are not confined just to classes. 
  3039.  
  3040.  
  3041. ΓòÉΓòÉΓòÉ 6.5.2. Objects with Their Own Unique Scope ΓòÉΓòÉΓòÉ
  3042.  
  3043. The methods and variables used by instances in a class are usually found at the 
  3044. class level. But sometimes an instance differs in some way from the others in 
  3045. its class. It may perform an additional action or require some unique handling. 
  3046. In this case one or more methods and related variables can be added directly to 
  3047. the instance. These methods and variables form a totally separate scope, 
  3048. independent of the more-typical class scopes found throughout the rest of the 
  3049. hierarchy. 
  3050.  
  3051. Methods can be added directly to an instance's collection of object methods 
  3052. using SETMETHOD, a method of the Object class. All subclasses of the Object 
  3053. class inherit SETMETHOD. Alternately, the Class class provides an ENHANCED 
  3054. method that lets you create new instances of a class, whose object methods are 
  3055. the instance methods of its class, but "enhanced" with additional collection 
  3056. methods. 
  3057.  
  3058.  
  3059. ΓòÉΓòÉΓòÉ 6.6. More about Methods ΓòÉΓòÉΓòÉ
  3060.  
  3061. A method name can be any character string. When an object receives a message, 
  3062. REXX searches for a method whose name matches the message name. 
  3063.  
  3064. You need to use quotation marks around a method name when it is the same as an 
  3065. operator. The following example illustrates how to do this correctly. It 
  3066. creates a new class (Cost), defines a new method (%), creates an instance of 
  3067. the Cost class (Mycost), and sends a % message to Mycost: 
  3068.  
  3069. mycost = cost~new           /* Creates new instance mycost */
  3070. mycost~'%'                  /* Sends % message to mycost   */
  3071.  
  3072. ::class Cost subclass 'Retail' /* Creates Cost, a sub-     */
  3073.                                /* class of 'Retail' class  */
  3074.   ::method "%"                 /* Creates % method         */
  3075.     expose p                   /* Produces: Enter a price. */
  3076.     say "Enter a price"        /* If the user specifies a  */
  3077.     pull p                     /* price of 100,            */
  3078.     say p*1.07                 /* produces: 107            */
  3079.     return 0
  3080.  
  3081.  
  3082. ΓòÉΓòÉΓòÉ 6.6.1. The Default Search Order for Selecting a Method ΓòÉΓòÉΓòÉ
  3083.  
  3084. When a message is sent to an object, REXX looks for a method whose name exactly 
  3085. matches the message string. If the message is ADD, for example, REXX looks for 
  3086. a method named ADD. Because, in the class hierarchy, there may be more than one 
  3087. method with the same name, REXX begins its search by going first to the object 
  3088. specified in the message. If the sought method is not found there, the search 
  3089. continues up the hierarchy. In order, REXX searches for: 
  3090.  
  3091.    1. A method the object itself defines (with SETMETHOD or ENHANCED) 
  3092.  
  3093.    2. A method the object's class defines 
  3094.  
  3095.       An object acquires the methods of its parent class; that is, the class 
  3096.       for which the object was created. If the class subsequently receives new 
  3097.       methods, objects predating the new methods do not acquire them. 
  3098.  
  3099.    3. A method an object's superclasses define 
  3100.  
  3101.       As with the object's class, only methods that existed in the superclass 
  3102.       when the object was created are valid. REXX searches the superclass 
  3103.       method definitions in the order that INHERIT messages were sent to an 
  3104.       object's class. 
  3105.  
  3106.  If REXX doesn't find a match for the message name, REXX checks the object for 
  3107.  method name UNKNOWN. If it exists, REXX calls the UNKNOWN method, and returns 
  3108.  as the message result any result the UNKNOWN method returns. The UNKNOWN 
  3109.  method arguments are the original message name and a REXX array containing the 
  3110.  original message arguments (see Defining an UNKNOWN Method). If the object 
  3111.  doesn't have an UNKNOWN method, REXX raises a NOMETHOD condition. Any trapped 
  3112.  information can then be inspected using REXX's CONDITION built-in function. 
  3113.  
  3114.  REXX searches up the hierarchy so that methods existing higher can be 
  3115.  supplemented or overridden by methods existing lower. 
  3116.  
  3117.  
  3118.   Searching the hierarchy for a method
  3119.  
  3120.  
  3121.                    Γöé
  3122.                   Γöé Γöé
  3123.                   Γöé Γöé
  3124.                    superclass
  3125.               ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ Γöé
  3126.               Γöé  ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3127.               Γöé  Γöé      Γöé
  3128.                superclass  superclass
  3129.    ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ  Γöé      Γöé
  3130.    Γöé ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ      Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3131.    Γöé Γöé      Γöé      Γöé      Γöé      Γöé      Γöé
  3132.     class    class    class    class    class    class
  3133.    Γöé
  3134.    Γöé instance  instance   instance   instance  instance  instance
  3135.    Γöé instance  instance   instance   instance  instance  instance
  3136.     instance  instance   instance   instance  instance  instance
  3137.    Γöé
  3138.    ΓööΓöÇmessage
  3139.  
  3140.  
  3141.  For example, suppose you wrote a program that allows users to look up other 
  3142.  users' phone numbers. Your program includes a class called Phone_Directory, 
  3143.  and all its instances are users' names with phone numbers. You have included a 
  3144.  method in Phone_Directory called NOTIFY that reports some data to a file 
  3145.  whenever someone looks up a number. All instances of Phone_Directory use the 
  3146.  NOTIFY method. 
  3147.  
  3148.  Now you decide you want NOTIFY, in addition to its normal handling, to 
  3149.  personally inform you whenever anyone looks up your number. To accommodate 
  3150.  this special case for your name only, you create your own NOTIFY method that 
  3151.  adds the new task and replicates the file handling task. You save the new 
  3152.  method as part of your own name instance, retaining the same name, NOTIFY. 
  3153.  
  3154.  Now, when a NOTIFY message is sent to your name instance, the new version of 
  3155.  NOTIFY will be found first. REXX will look no further up the class hierarchy. 
  3156.  The instance-level version will override the version at the class level. This 
  3157.  technique of overriding lets you change a method used by one instance without 
  3158.  disturbing the common method used by all the other instances. It is very 
  3159.  powerful for that reason. 
  3160.  
  3161.  
  3162. ΓòÉΓòÉΓòÉ 6.6.2. Changing the Search Order for Methods ΓòÉΓòÉΓòÉ
  3163.  
  3164. When composing a message, you can change the default search order for methods 
  3165. by doing both of the following: 
  3166.  
  3167.    1. Making the receiver object the sender object. (You usually do this by 
  3168.       specifying the special variable SELF. SELF holds the value of the object 
  3169.       in which a method is running. You can use SELF to run another method in 
  3170.       an object where a method is already running or pass references about an 
  3171.       object to the methods of other objects.) 
  3172.  
  3173.    2. Specifying a colon and a class symbol after the message name. The class 
  3174.       symbol identifies the class object to use as the starting point for the 
  3175.       search. This class object must be: 
  3176.  
  3177.           A direct superclass of the class that defines the active method 
  3178.  
  3179.           The object's own class, if you used SETMETHOD to define the active 
  3180.            method 
  3181.  
  3182.            The class symbol is usually the special variable SUPER, but it can 
  3183.            be any environment symbol or variable name whose value is a valid 
  3184.            class. 
  3185.  
  3186.  In A Sample Program Using Directives, an Account subclass of the Object 
  3187.  superclass is created. It defines a TYPE method for Account, and creates the 
  3188.  Savings subclass of Account. The example defines a TYPE method for the Savings 
  3189.  subclass, as follows: 
  3190.  
  3191.  
  3192.   ::class Savings subclass Account
  3193.  
  3194.     ::method 'TYPE'
  3195.       return "a savings account"
  3196.  
  3197.  To change the search order so REXX searches for TYPE in the Account rather 
  3198.  than Savings subclass, enter this instead: 
  3199.  
  3200.  
  3201.     ::method 'TYPE'
  3202.       return self~type:super '(savings)'
  3203.  
  3204.  When you create an asav instance of the Savings subclass and send a TYPE 
  3205.  message to asav: 
  3206.  
  3207.  
  3208.   say asav~type
  3209.  
  3210.  REXX displays: 
  3211.  
  3212.  
  3213.   an account
  3214.  
  3215.  rather than: 
  3216.  
  3217.  
  3218.   a savings account
  3219.  
  3220.  because REXX searches for TYPE in the Account class first. 
  3221.  
  3222.  
  3223. ΓòÉΓòÉΓòÉ 6.6.3. Public versus Private Methods ΓòÉΓòÉΓòÉ
  3224.  
  3225. A method can be public or private. Any object can send a message that runs a 
  3226. public method. Only a message an object sends to itself (using the special 
  3227. variable SELF as the message receiver) can run a private method. Private 
  3228. methods include methods at different scopes within the same object. (This lets 
  3229. superclasses make methods available to their subclasses while hiding those 
  3230. methods from clients of the object.) A private method is like an internal 
  3231. subroutine. It shields the internal workings of an object. 
  3232.  
  3233.  
  3234. ΓòÉΓòÉΓòÉ 6.6.4. Defining an UNKNOWN Method ΓòÉΓòÉΓòÉ
  3235.  
  3236. When an object that receives a message has no matching message name, REXX 
  3237. checks if the object has a method named UNKNOWN. If it does, REXX calls 
  3238. UNKNOWN, passing two arguments. The first is the name of the method that was 
  3239. not located. The second is an array containing the arguments passed with the 
  3240. original message. 
  3241.  
  3242. To define an UNKNOWN message, specify: 
  3243.  
  3244. UNKNOWN(message_name,message_args)
  3245.  
  3246.  
  3247. ΓòÉΓòÉΓòÉ 6.7. Concurrency ΓòÉΓòÉΓòÉ
  3248.  
  3249. In object-oriented programming, as in the real world, objects interact with 
  3250. each other. This interaction does not usually happen in isolation. Picture, for 
  3251. example, throngs of people interacting at rush hour in the business district of 
  3252. a big city. A program that aspires to simulate the real world would have to 
  3253. enable many objects to interact at any given time. That could mean thousands of 
  3254. objects sending messages to each other, thousands of methods running at once. 
  3255. In REXX, this simultaneous activity is called concurrency. To be precise, the 
  3256. concurrency is object-based concurrency because it involves objects, as opposed 
  3257. to, say, processes or threads. 
  3258.  
  3259. REXX objects are inherently concurrent, and this concurrency takes two forms: 
  3260.  
  3261.      Inter-object concurrency, where multiple objects are active--exchanging 
  3262.       messages, synchronizing, running their methods--at the same time 
  3263.  
  3264.      Intra-object concurrency, where multiple methods are able to run on the 
  3265.       same object at the same time 
  3266.  
  3267.  Default settings in REXX allow full inter-object concurrency but limited 
  3268.  intra-object concurrency. Some situations will make it desirable to use 
  3269.  special REXX instructions, routines, or classes to make full intra-object 
  3270.  concurrency happen. First, let's look at what is automatic. 
  3271.  
  3272.  
  3273. ΓòÉΓòÉΓòÉ 6.7.1. Full Inter-Object Concurrency ΓòÉΓòÉΓòÉ
  3274.  
  3275. Inter-object concurrency, where objects in a program are actively running 
  3276. methods at the same time, is provided for by REXX in two ways: 
  3277.  
  3278.      Early reply, by means of the REPLY instruction 
  3279.      Message objects 
  3280.  
  3281.  Early reply allows the object sending a message to keep on processing after 
  3282.  the message is sent. Meanwhile, the receiving object runs the method 
  3283.  corresponding to the message. This method contains the REPLY instruction, 
  3284.  which returns any results to the sender, interrupting the sender just long 
  3285.  enough to reply. The sender and receiver continue operating simultaneously. 
  3286.  
  3287.  Alternatively, an independent message object can be created and sent to a 
  3288.  receiver. One difference in this approach is that any reply returned does not 
  3289.  interrupt the sender. It waits until the sender asks for it. In addition, 
  3290.  message objects can simply notify the sender about the completion of the 
  3291.  method it sent, and even specify synchronous or asynchronous method 
  3292.  activation. 
  3293.  
  3294.  The chains of execution represented by the sender method and the receiver 
  3295.  method are called activities. An activity is a thread of execution that can 
  3296.  run methods concurrently with methods on other activities. In other words, 
  3297.  activities can run at the same time. 
  3298.  
  3299.  An activity contains a stack of invocations that represent the REXX programs 
  3300.  running on the activity. An invocation can be: 
  3301.  
  3302.      A main program invocation 
  3303.      An internal function or subroutine call 
  3304.      An external function or subroutine call 
  3305.      An INTERPRET instruction 
  3306.      A message invocation 
  3307.  
  3308.  An invocation is pushed onto an activity when an executable unit is invoked. 
  3309.  An invocation is removed (or popped) when execution completes. 
  3310.  
  3311.  
  3312. ΓòÉΓòÉΓòÉ 6.7.2. Object Variable Pools ΓòÉΓòÉΓòÉ
  3313.  
  3314. Every object has its own set of variables, called its object variable pool. 
  3315. These are variables associated solely with the object--rather than with any one 
  3316. method belonging to the object. When an object's method runs, the first thing 
  3317. it does is identify the object variables it intends to work with. Technically, 
  3318. it "exposes" these variables, using the REXX instruction EXPOSE. Exposing the 
  3319. object's variables distinguishes them from variables used by the method itself, 
  3320. which are not exposed. Every method an object owns--that is, all the instance 
  3321. methodsin the object's class--can expose variables from the object's variable 
  3322. pool. 
  3323.  
  3324. Therefore, an object variable pool includes: 
  3325.  
  3326.      Variables exposed by methods in the object's class (call these variables 
  3327.       a subpool) 
  3328.      Variables inherited from classes elsewhere in the hierarchy (in the form 
  3329.       of additional subpools) 
  3330.  
  3331.  Recall that all of a class's variables, together with the methods that expose 
  3332.  them, are called a class scope. REXX exploits this idea of class scope to 
  3333.  achieve concurrency. To explain, the object variable pool is really a 
  3334.  collection of variable subpools. Each subpool is at a different scope in the 
  3335.  object's inheritance chain. As long as the methods running on the object are 
  3336.  at different scopes, they can run simultaneously. 
  3337.  
  3338.  Let's amplify this point further. Scopes, like objects, hide and protect data 
  3339.  from outside manipulation. Methods at the same scope share the variable 
  3340.  subpools at that scope. The scope shields the variable subpools from methods 
  3341.  operating at other scopes. This lets you reuse variable names from class to 
  3342.  class, without fear the variables could be accessed and possibly corrupted by 
  3343.  a method outside their own class. So class scopes effectively partition an 
  3344.  object's variable pool into subpools that can operate independently of one 
  3345.  another. Multiple methods can use the same variable pool concurrently, as long 
  3346.  as they confine themselves to variables in their own subpools. 
  3347.  
  3348.  
  3349. ΓòÉΓòÉΓòÉ 6.7.3. Prioritizing Access to Variables ΓòÉΓòÉΓòÉ
  3350.  
  3351. Even with class scopes and subpool partitioning, a variable is still vulnerable 
  3352. if multiple methods within the scope try to access it at the same time. To 
  3353. handle this, REXX rules that once a particular method is activated and exposes 
  3354. variables from its subpool, that method has exclusive use of the subpool until 
  3355. processing is through. Until then, REXX delays running any other method needing 
  3356. the same subpool. 
  3357.  
  3358. Thus, within a single scope, if different activities send multiple messages to 
  3359. the same object, REXX forces the methods to run sequentially. This "first-in, 
  3360. first-out" processing of methods in a scope prevents them from simultaneously 
  3361. accessing any one variable, and maybe corrupting the data. 
  3362.  
  3363.  
  3364. ΓòÉΓòÉΓòÉ 6.7.4. Sending Messages within an Activity ΓòÉΓòÉΓòÉ
  3365.  
  3366. REXX makes one exception to sequential processing--when a method sends a 
  3367. message to itself. Say method M1 has been given exclusive access to object O, 
  3368. and then tries to run a second, internal method M2, also belonging to O. 
  3369. Internal method M2 would try to run, but REXX would delay it until original 
  3370. method M1 finished. Yet M1 would be unable to proceed until M2 ran. The two 
  3371. methods would become deadlocked. In actual practice REXX intervenes by treating 
  3372. internal method M2 like a subroutine call. In this case, REXX will run method 
  3373. M2 immediately, then continue processing method M1. 
  3374.  
  3375. The mechanism controlling this is the activity. Typically, whenever a message 
  3376. is invoked on an object, the activity acquires exclusive access by locking the 
  3377. object's scope. Any other activity sending a message to the object whose scope 
  3378. is locked must wait until the first activity releases the lock. The situation 
  3379. is different, however, if the messages originate from the same activity. When 
  3380. an invocation running on an activity sends another message to the same object, 
  3381. the method is allowed to run because the activity has already acquired the lock 
  3382. for the scope. Thus, REXX permits nested, non-concurrent method invocations on 
  3383. a single activity. No deadlocks occur because REXX treats these additional 
  3384. messages as subroutine calls. 
  3385.  
  3386.  
  3387. ΓòÉΓòÉΓòÉ 6.7.5. Programming for Intra-Object Concurrency ΓòÉΓòÉΓòÉ
  3388.  
  3389. You've read that multiple methods can access the same object at the same time 
  3390. only if they are operating at different scopes. That is because they are 
  3391. working with separate variable subpools. If two methods in the same scope try 
  3392. to run on the object, REXX by default processes them on a "first-in, first-out" 
  3393. basis, while treating internal methods as subroutines. You can, however, 
  3394. achieve full intra-object concurrency. REXX offers several mechanisms for this, 
  3395. including: 
  3396.  
  3397.      The SETUNGUARDED method of the Method class and the UNGUARDED option of 
  3398.       the ::METHOD directive, which provide unconditional intra-object 
  3399.       concurrency. 
  3400.  
  3401.      The GUARD OFF and GUARD ON instructions, which permit switching between 
  3402.       intra-object and default concurrency 
  3403.  
  3404.  When intra-object concurrency at the scope level is needed, you must 
  3405.  specifically employ these mechanisms (see the following section). Otherwise, 
  3406.  REXX will sequentially process the methods when they are competing for the 
  3407.  same object variables. 
  3408.  
  3409.  
  3410. ΓòÉΓòÉΓòÉ 6.7.6. Activating Methods ΓòÉΓòÉΓòÉ
  3411.  
  3412. By default, REXX assumes that an active method requires exclusive use of its 
  3413. object variable pool. Should another method attempt access at that time, it is 
  3414. locked out until the first method is done with the variable pool. This default 
  3415. intra-object concurrency maintains the integrity of the variable pool and 
  3416. prevents unexpected results. The intra-object concurrency support is especially 
  3417. useful in coding servers. You don't need to manage queues for incoming requests 
  3418. that result in messages being sent to the same object. REXX does it for you. 
  3419.  
  3420. Some methods can function concurrently without affecting the variable pool 
  3421. integrity or yielding unexpected results. When a method does not need exclusive 
  3422. use of its object variable pool, you can use the SETUNGUARDED method or the 
  3423. UNGUARDED option of the ::METHOD directive to provide unconditional 
  3424. intra-object concurrency. These mechanisms control the locking of an object's 
  3425. scope when a method is invoked. 
  3426.  
  3427. Many methods cannot use SETUNGUARDED and UNGUARDED simply because they require 
  3428. exclusive use of their variable pool some of the time. At other times, they 
  3429. need to perform some action which will involve the concurrent use of the same 
  3430. pool by a method on another activity. In this case, you can use the GUARD 
  3431. instruction. Using the GUARD instruction, when the method reaches the point in 
  3432. its processing where it requires concurrent use of the variable pool, it 
  3433. invokes GUARD OFF. GUARD OFF lets another method running on a different 
  3434. activity become active on the same object. If the method needs to regain 
  3435. exclusive use, it invokes GUARD ON. 
  3436.  
  3437. For even more flexibility when activating methods, you can use GUARD ON/OFF 
  3438. with the "WHEN expression" option. Add this instruction to the method code at 
  3439. the point where exclusive use of the variable pool becomes conditional. When 
  3440. processing reaches this point, REXX evaluates expression to determine if it is 
  3441. true or false. 
  3442.  
  3443. For example, if you specify "GUARD OFF WHEN expression," the issuing method 
  3444. waits until expression becomes true. To become true, another method must assign 
  3445. or drop an object variable that is named in expression. Whenever an object 
  3446. variable changes, REXX reevaluates expression. If expression becomes true, 
  3447. exclusive use of the variable pool is released (because GUARD OFF was 
  3448. specified) and the issuing method resumes with the next instruction. 
  3449.  
  3450.  
  3451. ΓòÉΓòÉΓòÉ 6.7.7. Computer Karaoke--A REXX Concurrency Sample ΓòÉΓòÉΓòÉ
  3452.  
  3453. Traditional REXX multimedia support provides limited capabilities for 
  3454. synchronizing multimedia events. Although you can use REXX to start a 
  3455. multimedia object, REXX is not notified when the processing is complete. This 
  3456. makes multimedia synchronization an ideal candidate for exploiting concurrency 
  3457. in object-oriented REXX. This sample also uses .alarm and .message environment 
  3458. symbols from the directory of public objects mentioned in the previous section. 
  3459.  
  3460.  
  3461. ΓòÉΓòÉΓòÉ 6.7.7.1. The Three Files in This Sample ΓòÉΓòÉΓòÉ
  3462.  
  3463. This sample uses three files. First we'll show you the files, then we'll 
  3464. explain how they work. The first file, CDNOTES.CMD, shows some of the 
  3465. synchronization you can do with REXX: 
  3466.  
  3467.  
  3468. The CDNOTES.CMD "play and display" file
  3469.  
  3470. /* CDNOTES.CMD -- plays a CD and displays synchronized text           */
  3471. parse arg track                             /* Get a track number     */
  3472. if track='' then do
  3473.    say 'Must specify a track number...'
  3474.    exit
  3475. end
  3476. script=.script~new('gabriel.'||track)       /* Create script          */
  3477. cd=.multimedia~new('cdaudio')               /* Create CDAUDIO object  */
  3478. cd~set('time format milliseconds')          /* Set the time format    */
  3479. startloc=cd~status('position track' track)  /* Set start point        */
  3480. if track=cd~status('number of tracks') then /* Last track?            */
  3481.    endloc=''                                /* Set stop point...      */
  3482. else
  3483.    endloc='to' cd~status('position track' track+1)
  3484.  
  3485. /* Play the CD and return control immediately                         */
  3486. done=cd~start('play','from' startloc endloc)
  3487. script~start                            /* Start synchronized display */
  3488. cd~close                                /* Close the CD object        */
  3489. rc=.multimedia~free                     /* Free multimedia resources  */
  3490. exit
  3491.  
  3492. ::requires orexxmm
  3493.  
  3494. CDNOTES plays an audio CD and displays text that is synchronized with the music 
  3495. so that you can sing along. The text is read from a second file, which also 
  3496. contains timing information: 
  3497.  
  3498.  
  3499. The GABRIEL.7 timing information file
  3500.  
  3501. 0  Digging in the Dirt -- by Peter Gabriel
  3502. 25 Something in me...
  3503. 31 All the time...
  3504. 37 No way of dealing...
  3505. 43 Can't go on...
  3506. 49 This time...
  3507. 51 This time...
  3508. 54 This time...
  3509. 57 I told you...
  3510.      .
  3511.      .
  3512.      .
  3513.  
  3514. To make this all work, two new classes are needed: one for the text (that is, 
  3515. the script), and one for the multimedia objects. These class definitions are in 
  3516. a third file, OREXXMM.CMD: 
  3517.  
  3518.  
  3519. The OREXXMM.CMD class definitions file
  3520.  
  3521. /* Object REXX class and methods for multimedia                     */
  3522.  
  3523. ::class script public                     /* Class for scripts      */
  3524.  
  3525.   ::method init
  3526.    expose timeline
  3527.    use arg fileid                         /* Get the file ID        */
  3528.    file=.stream~new(fileid)               /* Create stream object   */
  3529.    timeline=file~makearray('line')        /* Read file into array   */
  3530.    file~close                             /* Close the file         */
  3531.  
  3532.   ::method start
  3533.    expose timeline
  3534.    j=timeline~dimension(1)              /* Get the number of lines  */
  3535.    do i=1 to j                          /* For each line...         */
  3536.                                         /* ...create message object */
  3537.      msg=.message~new(self,'do','I',i)  /* ...hurl it into the void */
  3538.      .alarm~new(timeline[i]~word(1),msg)
  3539.    end                                  /* end do                   */
  3540.  
  3541.   ::method do
  3542.    expose timeline
  3543.    use arg i                              /* Retrieve line number   */
  3544.    say time() timeline[i]~subword(2)      /* Display words          */
  3545.  
  3546. ::class multimedia public         /* Class to "wrap" MCI string     */
  3547.  
  3548.   ::method init
  3549.    expose object
  3550.    use arg object
  3551.    /* Initialize the REXX multimedia support                        */
  3552.    call rxfuncadd 'mciRxInit', 'MCIAPI', 'mciRxInit'
  3553.    call mciRxInit
  3554.    /* Open the specified device                                     */
  3555.    return mciRxSendString('open' type 'wait','retstr','0','0')
  3556.  
  3557.   ::method unknown                /* All MCI string verbs use this  */
  3558.    expose object
  3559.    use arg mname, margs
  3560.    /* Call the MCI support with appropriate verb and arguments      */
  3561.    if margs[1]=.nil then margs[1]=''
  3562.    return self~mciRxSendString(mname, margs[1] 'wait')
  3563.  
  3564.   ::method mciRxSendString
  3565.    expose object
  3566.    use arg verb, items
  3567.    rc=mciRxSendString(verb object items,'retstr','0','0')
  3568.    return retstr
  3569.  
  3570.   ::method free class            /* Class method to free resources  */
  3571.    call mciRxExit
  3572.    return result
  3573.  
  3574.  
  3575. ΓòÉΓòÉΓòÉ 6.7.7.2. How the Class Definition File Works ΓòÉΓòÉΓòÉ
  3576.  
  3577. Let's start by looking at the class definitions in OREXXMM.CMD. 
  3578.  
  3579.  
  3580. ΓòÉΓòÉΓòÉ 6.7.7.2.1. Three Methods for the Script Class ΓòÉΓòÉΓòÉ
  3581.  
  3582. For the Script class, we provide three methods: INIT, START, and DO. REXX 
  3583. invokes an INIT method for an object whenever a NEW message is sent to the 
  3584. class. For our INIT processing, we read the file containing the script into an 
  3585. array. INIT expects the file identifier as an argument: 
  3586.  
  3587. use arg fileid
  3588.  
  3589. INIT sends a NEW message to the Stream class to get a new stream object: 
  3590.  
  3591. file=.stream~new(fileid)
  3592.  
  3593. The Stream class is useful for file I/O in REXX. To read the file, a MAKEARRAY 
  3594. message is sent to the stream object: 
  3595.  
  3596. timeline=file~makearray('line')
  3597.  
  3598. MAKEARRAY is a very handy method. When used on a stream object, it reads an 
  3599. entire file into an array. After reading the file, INIT sends a CLOSE message 
  3600. to the stream object to close the file. 
  3601.  
  3602. INIT uses the EXPOSE instruction to make the Timeline array available to all 
  3603. other methods in the Script class. 
  3604.  
  3605. Next, the START method starts the display of the lines of text. It uses an 
  3606. EXPOSE instruction to access the Timeline array. For each line in the script, 
  3607. START creates a message object. This is the tricky part of the program. 
  3608.  
  3609. The message object provides for the deferred sending of a message: 
  3610.  
  3611. msg=.message~new(self,'do','I',i)
  3612.  
  3613. The NEW message causes REXX to run the INIT method of the Message class. The 
  3614. arguments on the NEW message are used by INIT. The first argument on NEW 
  3615. defines where the message should be sent (SELF). The second argument is the 
  3616. message to be sent (DO). The third argument indicates that the next (fourth) 
  3617. argument is an individual string (as opposed to an array). The fourth and final 
  3618. argument is the argument to be passed on the message. The message objects that 
  3619. are created contain the information necessary to send this message: 
  3620.  
  3621. self~do(i)  /* Where "i" is an index to the array of strings */
  3622.  
  3623. SELF is a special variable. Its value is the object that forms the processing 
  3624. context for the method. In other words, SELF represents the object on which the 
  3625. method is running. In this case, the method that is running is the START 
  3626. method. START runs on an instance of the Script class, so SELF represents the 
  3627. particular instance of the Script class for which START is running. 
  3628.  
  3629. SELF might seem abstract, but its use becomes immediately apparent when you try 
  3630. to write your own methods. Eventually you'll need to send a message to the 
  3631. object that you are processing. But REXX doesn't pass object handles, so what 
  3632. do you send the message to? You send it to SELF. 
  3633.  
  3634. After creating a message object, START creates an alarm object for the message. 
  3635. An alarm object sends any message to an object at a given time: 
  3636.  
  3637. .alarm~new(timeline[i]~word(1),msg)
  3638.  
  3639. The NEW message causes REXX to run the INIT method for the newly-created alarm 
  3640. object. INIT expects a time displacement as its first argument. We pass it the 
  3641. number of seconds into the song that the line in timeline[i] is sung. The 
  3642. second argument on INIT is the message object that is to be processed at that 
  3643. time. 
  3644.  
  3645. After creating all the alarm objects, START returns to its caller. Meanwhile, 
  3646. all the alarm objects are ticking away concurrently, waiting for the correct 
  3647. moments to send the DO messages to SELF. START ends far before all the alarm 
  3648. objects are processed. 
  3649.  
  3650. The DO method uses EXPOSE to get the Timeline array. DO expects a line number 
  3651. as an argument. These line numbers were put in the message objects when they 
  3652. were created. DO displays the line using a SAY instruction. 
  3653.  
  3654.  
  3655. ΓòÉΓòÉΓòÉ 6.7.7.2.2. Four Methods for the Multimedia Class ΓòÉΓòÉΓòÉ
  3656.  
  3657. For playing the CD, we use the REXX multimedia support currently supplied with 
  3658. OS/2. We want to "wrap" the support with REXX methods so that we can take 
  3659. advantage of REXX concurrency support. 
  3660.  
  3661. The wrapping involves four methods: INIT, UNKNOWN, MCIRXSENDSTRING, and FREE. 
  3662. The INIT method initializes the REXX multimedia support and opens whatever 
  3663. device is passed to it. CDNOTES will pass `cdaudio' to it so that the audio CD 
  3664. device is opened. 
  3665.  
  3666. FREE is a class method. We'll use it at the end of CDNOTES to free the 
  3667. multimedia resources. 
  3668.  
  3669. The most interesting method is UNKNOWN. UNKNOWN is like an "otherwise" clause 
  3670. for a class. If you send an object a message and there isn't a method by that 
  3671. name, the UNKNOWN method is invoked. 
  3672.  
  3673. In the CDNOTES "play and display" file, we'll be using the MCI string verbs 
  3674. STATUS, SET, PLAY, and CLOSE for the CD. The MCI string command format for 
  3675. those verbs is symmetrical: verb, followed by items, followed by 'WAIT' 
  3676. (required for REXX). We haven't defined these verbs as methods of our 
  3677. Multimedia class. So if we send these verbs as messages to an instance of our 
  3678. Multimedia class, the UNKNOWN method will be invoked. 
  3679.  
  3680. When REXX invokes the UNKNOWN method, it passes the name of the method as the 
  3681. first argument, and any arguments that were specified as the second argument. 
  3682. This second argument is an array of arguments. Our UNKNOWN method builds an MCI 
  3683. command string from the arguments and then uses the MCIRXSENDSTRING method to 
  3684. process the string. 
  3685.  
  3686. The MCIRXSENDSTRING method calls the mciRxSendString function and returns 
  3687. RETSTR to the caller. 
  3688.  
  3689.  
  3690. ΓòÉΓòÉΓòÉ 6.7.7.3. How the "Play and Display" File Works ΓòÉΓòÉΓòÉ
  3691.  
  3692. Now let's take a look at how CDNOTES uses the classes. CDNOTES reads a script 
  3693. file as input. The script file contains lines of text and the amount of time 
  3694. (in seconds) that must pass before each line is displayed. For our example, we 
  3695. used "Digging in the Dirt" from Peter Gabriel's "Us" CD. We determined the 
  3696. times for each line by playing back the CD using OS/2's CD player, and jotting 
  3697. down the displayed time when each line started. 
  3698.  
  3699. CDNOTES also has a ::REQUIRES directive for the OREXXMM.CMD, which contains the 
  3700. class definitions for Multimedia and Script. 
  3701.  
  3702. CDNOTES accepts one argument: a number of a track on the CD to play. It uses 
  3703. the track number as an extension for the file identifier. Thus GABRIEL.7 (for 
  3704. track 7) is used as the file name in the sample. 
  3705.  
  3706. After retrieving the command line argument, CDNOTES creates a multimedia script 
  3707. by sending a NEW message to the Script class: 
  3708.  
  3709. script=.script~new('gabriel.'||track)  /* Create script      */
  3710.  
  3711. The name of the file containing the script is passed as an argument on the NEW 
  3712. message. 
  3713.  
  3714. Next CDNOTES creates an instance of the Multimedia class. The NEW message 
  3715. invokes the INIT method of the Multimedia class. The INIT method expects to be 
  3716. passed the type of multimedia object being opened. In our case, it is CDAUDIO: 
  3717.  
  3718. cd=.multimedia~new('cdaudio')    /* Create CDAUDIO object  */
  3719.  
  3720. The next few lines of code determine where the end of the track is. The SET and 
  3721. STATUS messages cause REXX to run the UNKNOWN method of the Multimedia class. 
  3722. The UNKNOWN method builds the appropriate MCI string command. 
  3723.  
  3724. cd~set('time format milliseconds')          /* Set the time format  */
  3725. startloc=cd~status('position track' track)   /* Set start point      */
  3726. if track=cd~status('number of tracks') then  /* Last track?          */
  3727.    endloc=''                                 /* Set stop point...    */
  3728. else
  3729.    endloc='to' cd~status('position track' track+1)
  3730.  
  3731. Now CDNOTES becomes a bit more interesting. To play the CD, we use the START 
  3732. method of the Object class: 
  3733.  
  3734. done=cd~start('play','from' startloc endloc 'wait')
  3735.  
  3736. The START method sends a message, which is specified in the arguments, to the 
  3737. CD object. The first argument on the START message is the message to be sent. 
  3738. The second argument on START are the arguments for the message being sent. In 
  3739. this case, the message is PLAY, and the argument that is passed on the PLAY 
  3740. method is the result of the expression: 
  3741.  
  3742. 'from' startloc endloc 'wait'
  3743.  
  3744. The START method sends the message and then immediately returns control to 
  3745. CDNOTES. The PLAY message causes the UNKNOWN method to be processed. UNKNOWN 
  3746. builds an MCI PLAY instruction to start the CD. We didn't send the PLAY message 
  3747. directly to the CD object because control wouldn't return to the CDNOTES 
  3748. program until the CD track finished playing--we wouldn't be able to synchronize 
  3749. the display of the text. 
  3750.  
  3751. After starting the CD, CDNOTES starts the synchronized text display by sending 
  3752. the START message to the script object: 
  3753.  
  3754. script~start
  3755.  
  3756. START creates message objects and alarm objects for every line in the song, and 
  3757. returns control immediately to CDNOTES. START is an example of polymorphism. In 
  3758. the Object class, START sends a message and returns immediately. In the Script 
  3759. class, START creates message and alarm objects, and returns immediately. Since 
  3760. the functions are similar, they have the same name. 
  3761.  
  3762. Notice that we don't account for processing delays that may occur in creating 
  3763. the alarm objects or in starting the audio playback. Consequently, the 
  3764. synchronization won't be perfect. In a real application, you might want to 
  3765. adjust the timings in the script file or add an adjustment factor when creating 
  3766. the alarm objects. 
  3767.  
  3768. START doesn't wait for the alarm objects to process before returning to its 
  3769. caller. Consequently, START returns to CDNOTES well before the CD track has 
  3770. completed playback. The next line of code closes the CD: 
  3771.  
  3772. cd~close
  3773.  
  3774. So if the CD is still playing, why doesn't CLOSE stop it prematurely? CLOSE 
  3775. causes REXX to run the UNKNOWN method. The UNKNOWN method runs on the same 
  3776. object (CD) using the same object variables that are in use because of the PLAY 
  3777. method. REXX senses that another method is using the object variable, and 
  3778. blocks the CLOSE until PLAY completes. (You can check this by placing SAY 
  3779. instructions around the line containing the CLOSE.) 
  3780.  
  3781. After closing the CD, CDNOTES frees multimedia resources by sending the FREE 
  3782. message to the Multimedia class. FREE is a class method. 
  3783.  
  3784. As this brief sample shows, REXX's object-oriented features greatly extend what 
  3785. you can do with the language. And they do so while maintaining the simplicity 
  3786. and brevity of the traditional REXX. CDNOTES uses objects, concurrent 
  3787. programming, and multimedia to create a simple computer karaoke in about 70 
  3788. lines of code. 
  3789.  
  3790.  
  3791. ΓòÉΓòÉΓòÉ 7. Commands ΓòÉΓòÉΓòÉ
  3792.  
  3793. From a REXX program you can pass commands to OS/2 or to applications designed 
  3794. to work with REXX. When used to run OS/2 commands, REXX becomes a powerful 
  3795. substitute for the OS/2 Batch Facility. You can use variables, control 
  3796. structures, math, and parsing to create procedures that would be impossible to 
  3797. implement with the OS/2 Batch Facility. 
  3798.  
  3799. Applications that are designed to work with REXX are often referred to as 
  3800. scriptable applications. To work with REXX, a scriptable application registers 
  3801. an environment with REXX. An environment serves as a kind of workspace shared 
  3802. between REXX and the application. Environments accept application subcommands 
  3803. issued from REXX programs. 
  3804.  
  3805. For example, many editors provide a command prompt or dialog box from which you 
  3806. can issue subcommands to set margins, add lines, and so on. If the editor is 
  3807. scriptable from REXX, you can issue editor subcommands from a REXX program. 
  3808. These REXX programs are typically referred to as macros. The Enhanced Editor 
  3809. included with OS/2 is an example of an editor that you can script with REXX 
  3810. macros. 
  3811.  
  3812. When an application runs a REXX macro, REXX directs commands to the 
  3813. application's environment. If you issue a subcommand that the application does 
  3814. not recognize, it may or may not pass the command to OS/2, depending on the 
  3815. application. 
  3816.  
  3817. To let you specify which environment processes a command, REXX includes an 
  3818. ADDRESS instruction. Starting your REXX programs from the OS/2 command line 
  3819. makes OS/2 the default environment for REXX commands. 
  3820.  
  3821.  
  3822. ΓòÉΓòÉΓòÉ 7.1. How to Issue Commands ΓòÉΓòÉΓòÉ
  3823.  
  3824. REXX makes it easy to issue commands. The basic rule is that whatever REXX 
  3825. cannot process, it passes to the default environment. You can: 
  3826.  
  3827.      Let REXX evaluate part or all of a clause as an expression. REXX 
  3828.       automatically passes the resulting string to OS/2. 
  3829.  
  3830.      Enclose the entire clause in quotation marks. That renders it a literal 
  3831.       string for REXX to pass to OS/2. 
  3832.  
  3833.      Send a command explicitly to OS/2 by using the ADDRESS instruction. 
  3834.  
  3835.  REXX processes your program one clause at a time. It examines each clause to 
  3836.  determine if it is: 
  3837.  
  3838.      A directive, such as ::CLASS or ::METHOD 
  3839.  
  3840.      A message instruction, such as: 
  3841.  
  3842.             .array~new
  3843.  
  3844.      A keyword instruction, such as: 
  3845.  
  3846.             say 'Type total number'
  3847.  
  3848.       or 
  3849.  
  3850.             pull input
  3851.  
  3852.      A variable assignment (any valid symbol followed by an equal sign), such 
  3853.       as: 
  3854.  
  3855.             price = cost * 1.2
  3856.  
  3857.      A label for calling other routines 
  3858.  
  3859.      A null (empty) clause 
  3860.  
  3861.  If the clause is none of the above, REXX evaluates the entire clause as an 
  3862.  expression and passes the resulting string to OS/2. 
  3863.  
  3864.  If the string is a valid OS/2 command, OS/2 processes it as though you had 
  3865.  typed the string at the command prompt and pressed the Enter key. 
  3866.  
  3867.  The following example shows a REXX clause that uses the DIR command to display 
  3868.  a list of files in the current directory. 
  3869.  
  3870.   /* display current directory */
  3871.   say 'DIR command using REXX'
  3872.   dir
  3873.  
  3874.  The clause dir is not a REXX instruction or a label, so REXX evaluates it and 
  3875.  passes the resulting string to OS/2. OS/2 recognizes the string DIR as one of 
  3876.  its commands and processes it. 
  3877.  
  3878.  Letting REXX evaluate the command as an expression might cause problems, 
  3879.  however. Try adding a path to the DIR command in the above program (such as, 
  3880.  dir c:\config.sys). The OS/2 command in this case is an incorrect REXX 
  3881.  expression. The program ends with an error. 
  3882.  
  3883.  A safer way to issue commands is by enclosing the command in quotes, which 
  3884.  makes the command a literal string. REXX doesn't evaluate the contents of 
  3885.  strings. Because the string isn't a REXX instruction or label, REXX passes the 
  3886.  string to OS/2. Here is an example using the PATH command: 
  3887.  
  3888.   /* display current path      */
  3889.   say 'PATH command using REXX'
  3890.   'path'
  3891.  
  3892.  The next example, DP.CMD, shows a program using the DIR and PATH commands. The 
  3893.  PAUSE command is added to wait for the user to press a key before issuing the 
  3894.  next instruction or command. Borders are added too. 
  3895.  
  3896.   /* DP.CMD -- Issue DIR and PATH commands to OS/2 */
  3897.  
  3898.   say '='~copies(40)    /* display line of "="'s   */
  3899.                         /* for a border            */
  3900.  
  3901.   'dir'                 /* display listing of      */
  3902.                         /* the current directory   */
  3903.  
  3904.   'pause'               /* pauses processing and   */
  3905.                         /* tells user to "Press    */
  3906.                         /* any key to continue."   */
  3907.  
  3908.   say '='~copies(40)    /* display line of '='     */
  3909.   'path'                /* display the current     */
  3910.                         /* PATH setting            */
  3911.  
  3912.  REXX displays the following on the screen when you run the program. 
  3913.  
  3914.   [C:\]dp
  3915.   ========================================
  3916.  
  3917.    The volume label in drive C is OS2.
  3918.    Directory of C:\EXAMPLES
  3919.  
  3920.   .            <DIR>     10-16-94  12:43p
  3921.   ..           <DIR>     10-16-94  12:43p
  3922.   EX4_1    CMD     nnnn  10-16-94   1:08p
  3923.   DEMO     TXT      117  10-16-94   1:10p
  3924.        4 File(s)   12163072 bytes free
  3925.   Press any key when ready . . .
  3926.  
  3927.   ========================================
  3928.   PATH=C:\OS2;C:\OS2\UTIL;C:\OS2\INSTALL
  3929.   [C:\]
  3930.  
  3931.  
  3932. ΓòÉΓòÉΓòÉ 7.2. Suppressing the Command Echo ΓòÉΓòÉΓòÉ
  3933.  
  3934. When your REXX program issues an OS/2 command, REXX passes the command to the 
  3935. OS/2 command handler for processing. This processing includes displaying, or 
  3936. echoing, the command on the screen. Commands are also echoed in old-style 
  3937. (non-REXX) .CMD files. 
  3938.  
  3939. To suppress command echoes, issue the ECHO OFF command from your REXX program. 
  3940. OS/2 will suppress all echoing for the remainder of your REXX program. To 
  3941. suppress echoing for one command, put an at sign (@) in front of the command: 
  3942.  
  3943. /* NOECHO.CMD -- suppress command echoes              */
  3944. say 'Without echo:'
  3945. '@dir c:\config.sys'
  3946. say 'With echo:'
  3947. 'dir c:\config.sys'
  3948. say 'Suppress remaining echoes...'
  3949. '@echo off'          /* suppress the echo of ECHO OFF */
  3950. 'dir c:\config.sys'
  3951.  
  3952.  
  3953. ΓòÉΓòÉΓòÉ 7.3. REXX and Batch Files ΓòÉΓòÉΓòÉ
  3954.  
  3955. You can use a REXX program anywhere you now use OS/2 batch files. The following 
  3956. example shows an OS/2 batch file that processes user input to display a help 
  3957. message: 
  3958.  
  3959. @echo off
  3960. if %1.==. goto msg
  3961. if %1 == on goto yes
  3962. if %1 == off goto no
  3963. if %1 == ON goto yes
  3964. if %1 == OFF goto no
  3965. if %1 == On goto yes
  3966. if %1 == oN goto yes
  3967. if %1 == OFf goto no
  3968. if %1 == OfF goto no
  3969. if %1 == Off goto no
  3970. if %1 == oFF goto no
  3971. if %1 == oFf goto no
  3972. if %1 == ofF goto no
  3973. helpmsg %1
  3974. goto exit
  3975. :msg
  3976. helpmsg
  3977. goto exit
  3978. :yes
  3979. prompt $i[$p]
  3980. goto exit
  3981. :no
  3982. cls
  3983. prompt
  3984. :exit
  3985.  
  3986. Here is the equivalent program in REXX: 
  3987.  
  3988. /* HELP.CMD -- Get help for a system message */
  3989. arg action .
  3990. select
  3991.   when action=''    then     'helpmsg'
  3992.   when action='ON'  then     'prompt $i[$p]'
  3993.   when action='OFF' then do
  3994.                            'cls'
  3995.                            'prompt'
  3996.                            end
  3997.   otherwise 'helpmsg' action
  3998.   end
  3999. exit
  4000.  
  4001.  
  4002. ΓòÉΓòÉΓòÉ 7.4. Issuing a Command to Call a .CMD File ΓòÉΓòÉΓòÉ
  4003.  
  4004. If you are issuing a command to have OS/2 run one of its built-in commands or 
  4005. other programs, you can call it by name as previous examples showed. However, 
  4006. to have OS/2 run another .CMD program from your REXX program, you must call it 
  4007. using a CALL instruction instead of calling it by name. There are two kinds of 
  4008. calls you can use: 
  4009.  
  4010.      The REXX CALL instruction 
  4011.      The OS/2 CALL command 
  4012.  
  4013.  The REXX CALL instruction calls other REXX programs. To call a REXX program 
  4014.  named MYSUB1, you could write the CALL instruction: 
  4015.  
  4016.   call mysub1
  4017.  
  4018.  REXX recognizes the CALL instruction, handles the call, and processes MYSUB1 
  4019.  as a REXX program. 
  4020.  
  4021.  The REXX CALL instruction does not work to call a non-REXX .CMD file. Instead, 
  4022.  you would use the OS/2 CALL command. To call a non-REXX .CMD program named 
  4023.  MYSUB2, you could write the CALL instruction like this: 
  4024.  
  4025.   "call mysub2"
  4026.  
  4027.  REXX evaluates the expression and passes it to the OS/2 command handler for 
  4028.  processing. The command handler recognizes the CALL command and processes 
  4029.  MYSUB2 as a .CMD program. 
  4030.  
  4031.  The quotation marks around call mysub2 indicate that this is the OS/2 CALL 
  4032.  command instead of a REXX CALL instruction. 
  4033.  
  4034.  
  4035. ΓòÉΓòÉΓòÉ 7.5. Using Variables to Build Commands ΓòÉΓòÉΓòÉ
  4036.  
  4037. You can use variables to build commands, just as you would use variables to 
  4038. construct any string. The SHOFIL.CMD program below is an example. SHOFIL types 
  4039. a file that the user specifies. It prompts the user to enter a file name and 
  4040. then builds a variable to hold the TYPE command and the input file name. 
  4041.  
  4042. To have REXX issue the command to the operating system, put the variable 
  4043. holding the command string on a line by itself. REXX evaluates the variable and 
  4044. passes the resultant string to OS/2: 
  4045.  
  4046. /* SHOFIL.CMD -- build command with variables */
  4047.  
  4048. /* prompt the user for a file name            */
  4049. say "Type a file name:"
  4050.  
  4051. /* assign the response to variable FILENAME   */
  4052. pull filename
  4053.  
  4054. /* build a command string by concatenation    */
  4055. commandstr = "TYPE" filename
  4056.  
  4057. /* Assuming the user typed "demo.txt,"        */
  4058. /* the variable COMMANDSTR contains           */
  4059. /* the string "TYPE DEMO.TXT" and so...       */
  4060.  
  4061. commandstr           /* ...REXX passes the    */
  4062.                      /* string on to OS/2     */
  4063.  
  4064. REXX displays the following on the screen when you run the program. 
  4065.  
  4066. [C:\]shofil
  4067. Type a file name:
  4068. demo.txt
  4069.  
  4070. This is a sample text file. Its sole
  4071. purpose is to demonstrate how
  4072. commands can be issued from REXX
  4073. programs.
  4074.  
  4075. [C:\]
  4076.  
  4077.  
  4078. ΓòÉΓòÉΓòÉ 7.6. Using Quotation Marks ΓòÉΓòÉΓòÉ
  4079.  
  4080. The rules for forming a command from an expression are exactly the same as 
  4081. those for forming expressions. Be careful of symbols that have meanings for 
  4082. both REXX and OS/2 programs. The DIRREX.CMD program below shows how REXX 
  4083. evaluates a command when the command name and a variable name are the same: 
  4084.  
  4085. /* DIRREX.CMD -- assign a value to the symbol DIR */
  4086. say "DIR command using REXX"
  4087. dir = "echo This is not a directory."
  4088.  
  4089. /* pass the evaluated variable to OS/2            */
  4090. dir
  4091.  
  4092. Because Dir is a variable that contains a string, the string is passed to OS/2. 
  4093. The OS/2 DIR command is not executed. Here are the results: 
  4094.  
  4095. [C:\]dirrex
  4096. DIR command using REXX:
  4097. This is not a directory.
  4098. [C:\]
  4099.  
  4100. REXX evaluates a literal string--a string enclosed in matching quotation 
  4101. marks--exactly as it is. To ensure that a symbol in a command is not evaluated 
  4102. as a variable, enclose it in matching quotation marks as follows: 
  4103.  
  4104. /* assign a value to the symbol DIR       */
  4105. say "DIR command using REXX"
  4106. dir = "echo This is another string now."
  4107.  
  4108. /* pass the literal string "dir" to OS/2  */
  4109. "dir"
  4110.  
  4111. REXX displays a directory listing. 
  4112.  
  4113. The best way to ensure that REXX passes a string to the OS/2 as a command is to 
  4114. enclose the entire clause in quotation marks. This is especially important when 
  4115. you use symbols that REXX uses as operators. 
  4116.  
  4117. If you want to use a variable in the command string, leave the variable outside 
  4118. the quotation marks. For example: 
  4119.  
  4120. extension = "BAK"
  4121. "delete *."ΓûîΓûîextension
  4122.  
  4123. option = "/w"
  4124. "dir"ΓûîΓûîoption
  4125.  
  4126.  
  4127. ΓòÉΓòÉΓòÉ 7.7. ADDRESS Instruction ΓòÉΓòÉΓòÉ
  4128.  
  4129. To send a command to a specific environment, use this format of the ADDRESS 
  4130. instruction: 
  4131.  
  4132. ADDRESS environment expression
  4133.  
  4134. For environment, specify the destination of the command. To address the OS/2 
  4135. environment, use the symbol CMD. For expression, specify an expression that 
  4136. results in a string that REXX passes to the environment. Here are some 
  4137. examples: 
  4138.  
  4139. address CMD "dir"     /* pass the literal string   */
  4140.                       /* "dir" to OS/2 program     */
  4141.  
  4142. cmdstr = 'dir *.txt'  /* assign a string           */
  4143.                       /* to a variable             */
  4144.  
  4145. address CMD cmdstr    /* REXX passes the string    */
  4146.                       /* "dir *.txt" to OS/2       */
  4147. address edit "regen"  /* REXX passes the "regen"   */
  4148.                       /* command to a fictitious   */
  4149.                       /* environment named edit    */
  4150.  
  4151. Notice that the ADDRESS instruction lets a single REXX program issue commands 
  4152. to two or more environments. 
  4153.  
  4154.  
  4155. ΓòÉΓòÉΓòÉ 7.8. Using Return Codes from Commands ΓòÉΓòÉΓòÉ
  4156.  
  4157. Information passes between REXX and the environment. REXX sends command strings 
  4158. to the environment, and the environment can return information. One piece of 
  4159. information that the environment passes to REXX is the return code from the 
  4160. command. 
  4161.  
  4162. With each command it processes, OS/2 produces a number called a return code. 
  4163. When a REXX program is running, this return code is automatically assigned to a 
  4164. special built-in REXX variable named RC. 
  4165.  
  4166. If the command was processed with no problems, the return code is nearly always 
  4167. 0. If something goes wrong, the return code issued is another, nonzero number. 
  4168. What the number is depends on the command itself and the error encountered. 
  4169.  
  4170. This example shows how to display a return code: 
  4171.  
  4172. /* GETRC.CMD report */
  4173. 'TYPE nosuch.fil'
  4174. say 'the return code is' RC
  4175.  
  4176. The special variable RC can be used in expressions just like any other 
  4177. variable. In the next example, an error message is displayed when a the TYPE 
  4178. command returns a nonzero value in RC: 
  4179.  
  4180. /* Simple if/then error-handler */
  4181. say "Type a file name:"
  4182. pull filename
  4183. "TYPE" filename
  4184. if RC \= 0
  4185. then say "Could not find" filename
  4186.  
  4187. This program tells you only that OS/2 could not find a nonexistent file. This 
  4188. program does not do much more than OS/2 does, but you have the basic idea of 
  4189. how to capture a return code. 
  4190.  
  4191. A system error alone does not stop the running of a REXX program. Without some 
  4192. provision to stop the program, in this case a trap, REXX continues running. You 
  4193. may have to press the Control (Ctrl)+Break keys to stop processing. REXX 
  4194. includes the following instructions for trapping and controlling system errors: 
  4195.  
  4196.      CALL ON ERROR 
  4197.      CALL ON FAILURE 
  4198.      SIGNAL ON ERROR 
  4199.      SIGNAL ON FAILURE 
  4200.  
  4201.  
  4202. ΓòÉΓòÉΓòÉ 7.9. Subcommand Processing ΓòÉΓòÉΓòÉ
  4203.  
  4204. REXX programs can issue commands or subcommands to programs other than OS/2. To 
  4205. determine what subcommands you can issue, refer to the documentation for the 
  4206. application. 
  4207.  
  4208. To make your own applications scriptable from REXX, see REXX Application 
  4209. Programming Interface. 
  4210.  
  4211.  
  4212. ΓòÉΓòÉΓòÉ 7.10. Trapping Command Errors ΓòÉΓòÉΓòÉ
  4213.  
  4214. The most efficient way to detect errors from commands is by creating condition 
  4215. traps, using the SIGNAL ON and CALL ON instructions, with either the ERROR or 
  4216. the FAILURE condition. When used in a program, these instructions enable, or 
  4217. switch on, a detector in REXX that tests the result of every command. Then, if 
  4218. a command signals an error, REXX stops usual program processing, searches the 
  4219. program for the appropriate label (ERROR:, or FAILURE:, or a label that you 
  4220. created), and resumes processing there. 
  4221.  
  4222. SIGNAL ON and CALL ON also tell REXX to store the line number (in the REXX 
  4223. program) of the command instruction that triggered the condition. REXX assigns 
  4224. that line number to the special variable SIGL. Your program can get even more 
  4225. information about what caused the command error through the built-in function 
  4226. CONDITION. 
  4227.  
  4228. Using the SIGNAL and CALL instructions to handle errors has several advantages; 
  4229. namely, programs: 
  4230.  
  4231.      Are easier to read because you can confine error-trapping to a single, 
  4232.       common routine 
  4233.  
  4234.      Are more flexible because they can respond to errors by clause (SIGL), by 
  4235.       return code (RC), or by other information (CONDITION method or built-in 
  4236.       function) 
  4237.  
  4238.      Can catch problems and react to them before the environment issues an 
  4239.       error message 
  4240.  
  4241.      Are easier to correct because you can turn the traps on and off (SIGNAL 
  4242.       OFF and CALL OFF) 
  4243.  
  4244.  For other conditions that may be detected using SIGNAL ON and CALL ON, see the 
  4245.  Object REXX Reference. 
  4246.  
  4247.  
  4248. ΓòÉΓòÉΓòÉ 7.10.1. Instructions and Conditions ΓòÉΓòÉΓòÉ
  4249.  
  4250. The instructions to set a trap for errors are SIGNAL and CALL. Example formats 
  4251. are: 
  4252.  
  4253. SIGNAL ON condition NAME trapname
  4254. CALL   ON condition NAME trapname
  4255.  
  4256. The SIGNAL ON instruction initiates an exit subroutine that ends the program. 
  4257. The CALL ON instruction initiates a subroutine that returns processing to the 
  4258. clause immediately following the CALL ON instruction. Use CALL ON when you want 
  4259. to recover from a command error or failure. 
  4260.  
  4261. The two command conditions that can be trapped are: 
  4262.  
  4263.  ERROR Detects any nonzero error code the default environment issues as the 
  4264.      result of a REXX command 
  4265.  
  4266.  FAILURE Detects a severe error, preventing the system from processing the 
  4267.      command 
  4268.  
  4269.  A failure, in this sense, is a particular category of error. If you use SIGNAL 
  4270.  ON or CALL ON to set a trap only for ERROR conditions, then it traps failures 
  4271.  as well as other errors. If you also specify a FAILURE condition, then the 
  4272.  ERROR trap ignores failures. 
  4273.  
  4274.  With both the SIGNAL and CALL instructions, you have the option of specifying 
  4275.  the name of the trap routine. Add a NAME keyword followed by the name of the 
  4276.  subroutine. If you don't specify the name of the trap routine, REXX uses the 
  4277.  value of condition as the name (REXX looks for the label ERROR:, FAILURE:, and 
  4278.  so on). 
  4279.  
  4280.  For more information about other conditions that can be trapped, see the 
  4281.  Object REXX Reference. 
  4282.  
  4283.  
  4284. ΓòÉΓòÉΓòÉ 7.10.2. Disabling Traps ΓòÉΓòÉΓòÉ
  4285.  
  4286. To turn off a trap for any part of a program, use the SIGNAL or CALL 
  4287. instructions with the OFF keyword, such as: 
  4288.  
  4289. SIGNAL OFF ERROR
  4290. SIGNAL OFF FAILURE
  4291. CALL OFF ERROR
  4292. CALL OFF FAILURE
  4293.  
  4294.  
  4295. ΓòÉΓòÉΓòÉ 7.10.3. Using SIGNAL ON ERROR ΓòÉΓòÉΓòÉ
  4296.  
  4297. The following example shows how a program might use SIGNAL ON to trap a command 
  4298. error in a program that copies a file. In this example, an error occurs because 
  4299. the name of a nonexistent file is stored in the variable File1. Processing 
  4300. jumps to the clause following the label ERROR: 
  4301.  
  4302.            / *  example  of  error  trap                                     * /
  4303.            signal  on  error                   / *  Set  the  trap .            * /
  4304.                 .
  4305.                 .
  4306.                 .
  4307.       Γöî ΓöÇΓöÇΓöÇ  " COPY "   file1  file2               / *  When  an  error  occurs . . .  * /
  4308.       Γöé          .
  4309.       Γöé          .
  4310.       Γöé     exit  .
  4311.       Γöö ΓöÇΓöÇΓöÇ  error :                            / *  . . . REXX  jumps  to  here    * /
  4312.            say  " Error "  rc  " at  line "  sigl
  4313.            say  " Program  cannot  continue . "
  4314.            exit                              / *  and  ends  the  program .    * /
  4315.  
  4316.  
  4317. ΓòÉΓòÉΓòÉ 7.10.4. Using CALL ON ERROR ΓòÉΓòÉΓòÉ
  4318.  
  4319. If there were a way to recover, such as by typing another file name, you could 
  4320. use CALL ON to recover and resume processing: 
  4321.  
  4322.            / *  example  of  error  recovery  * /
  4323.            call  on  error
  4324.                 .
  4325.                 .
  4326.                 .
  4327.      Γöî ΓöÇΓöÇΓöÇΓöÇ  " COPY "   file1  file2
  4328.      Γöé      say  " Using "  file2   ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ ΓöÉ
  4329.      Γöé           .                               Γöé
  4330.      Γöé           .                               Γöé
  4331.      Γöé            exit                           Γöé
  4332.      Γöö ΓöÇΓöÇΓöÇ   error :                               Γöé
  4333.            say  " Can  not  find "  file1             Γöé
  4334.            say  " Type  Y  to  continue  anyway . "     Γöé
  4335.            pull  ans                             Γöé
  4336.            if  ans  =  " Y "  then                    Γöé
  4337.               do                                Γöé
  4338.                  / *  create  dummy  file  * /        Γöé
  4339.                       .                         Γöé
  4340.                       .                         Γöé
  4341.                       .                         Γöé
  4342.                  file2  =  " dummy . fil "            Γöé
  4343.                  RETURN  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ ΓöÇΓöÇΓöÇ Γöÿ
  4344.                  end
  4345.            else  exit
  4346.  
  4347.  
  4348. ΓòÉΓòÉΓòÉ 7.10.5. A Common Error-handling Routine ΓòÉΓòÉΓòÉ
  4349.  
  4350. The following example shows a simple error trap that you can use in many 
  4351. programs: 
  4352.  
  4353. /* Here is a sample "main program" with an error            */
  4354. signal on error        /* enable error handling             */
  4355. 'ersae myfiles.*'      /* mis-typed 'erase' instruction     */
  4356. exit
  4357.  
  4358. /* And here is a fairly generic error-handler for this      */
  4359. /* program (and many others...)                             */
  4360. error:
  4361.   say 'error' rc 'in system call.'
  4362.   say
  4363.   say 'line number =' sigl
  4364.   say 'instruction = '  ΓûîΓûî sourceline(sigl)
  4365.   exit
  4366.  
  4367.  
  4368. ΓòÉΓòÉΓòÉ 8. Input and Output ΓòÉΓòÉΓòÉ
  4369.  
  4370. Object REXX supports a stream I/O model. In the stream model, your program 
  4371. reads data from various devices (such as hard disks, CD-ROMs, and keyboards) as 
  4372. a continuous stream of characters. Your program also writes data as a 
  4373. continuous stream of characters. 
  4374.  
  4375. In the stream model, a text file is represented as a stream of characters with 
  4376. special new-line characters marking the end of each "line" of text in the 
  4377. stream. A binary file is simply a stream of characters without an inherent line 
  4378. structure. REXX lets you read streams as lines or as characters. 
  4379.  
  4380. To support the stream model, Object REXX includes a Stream class and many 
  4381. methods to use on stream objects. To input or output data, you first create an 
  4382. instance of the Stream class that represents the device or file you want to 
  4383. use. For example, the following clause creates a stream object for the file 
  4384. C:\CONFIG.SYS: 
  4385.  
  4386. /* Create a stream object for CONFIG.SYS */
  4387. file=.stream~new('c:\config.sys')
  4388.  
  4389. Then you send the stream object messages that are appropriate for the device or 
  4390. data. CONFIG.SYS is a text file, so you would normally use methods that read or 
  4391. write data as lines. Some of these methods are LINES, LINEIN, and LINEOUT. 
  4392.  
  4393. If the stream represented a binary file (such as a WAV, GIF, TIF, AVI, or EXE 
  4394. file), you would use methods that read and write data as characters. Some of 
  4395. these methods are CHARS, CHARIN, and CHAROUT. 
  4396.  
  4397. The Stream class includes other methods for opening and closing streams, 
  4398. flushing buffers, seeking, retrieving stream status, and other input/output 
  4399. operations. 
  4400.  
  4401. Many of the methods of the Stream class are also available as REXX built-in 
  4402. functions. While you can use the functions, using the Stream class is 
  4403. preferred. In any case, you should not intermix the use of functions and 
  4404. methods on the same stream. Doing so yields unpredictable results. 
  4405.  
  4406.  
  4407. ΓòÉΓòÉΓòÉ 8.1. More about Stream Objects ΓòÉΓòÉΓòÉ
  4408.  
  4409. To use streams in Object REXX, you create new instances of the Stream class. 
  4410. These "stream objects" represent the various data sources and destinations 
  4411. available to your program, such as hard disks, CD-ROMs. keyboards, displays, 
  4412. printers, serial interfaces, networks, and so on.  Because these sources are 
  4413. represented as objects, you can work with them in similar (but not identical) 
  4414. ways. 
  4415.  
  4416. Stream objects can be "transient" or "persistent."  An example of a transient 
  4417. (or dynamic) stream object is a serial interface. Data can be sent or received 
  4418. from serial interfaces, but the data is not "stored" permanently by the serial 
  4419. interface itself.  Consequently, you cannot, for example, seek to a position in 
  4420. the data stream. Once you read or write it, the data cannot be read again. 
  4421.  
  4422. A disk file is an example of a persistent stream object.  Because the data is 
  4423. stored on disk, you can seek forward and backwards in the stream and read data 
  4424. that you have previously read. REXX maintains separate read and write pointers 
  4425. to a stream. You can move the pointers independently using arguments on methods 
  4426. such as LINEIN, LINEOUT, CHARIN, and CHAROUT. REXX also provides SEEK and 
  4427. POSITION methods for setting the read and write positions. (We'll discuss read 
  4428. and write positioning in a later section.) 
  4429.  
  4430.  
  4431. ΓòÉΓòÉΓòÉ 8.2. Reading a Text File ΓòÉΓòÉΓòÉ
  4432.  
  4433. Let's look at an example of reading a file. The following program, COUNT.CMD, 
  4434. counts the words in a text file. To run the program, enter COUNT followed by 
  4435. the name of the file to be processed: 
  4436.  
  4437. count myfile.txt
  4438. count r:\rexx\articles\devcon7.scr
  4439.  
  4440. COUNT uses the String method WORDS to count the words, so COUNT actually counts 
  4441. blank-delimited tokens: 
  4442.  
  4443. /* COUNT.CMD -- counts the words in a file                         */
  4444. parse arg path              /* Get file name from command line     */
  4445. count=0                     /* Initialize a counter                */
  4446. file=.stream~new(path)      /* Create a stream object for the file */
  4447. do while file~lines<>0      /* Loop while there are lines          */
  4448.   text=file~linein          /* Read a line from the file           */
  4449.   count=count+(text~words)  /* Count words and add to counter      */
  4450. end
  4451. say count                   /* Display the count                   */
  4452.  
  4453. To read a file, COUNT first creates a stream object for the file by sending the 
  4454. NEW message to the Stream class. The file name (with or without a path) is 
  4455. specified as an argument on the NEW method. 
  4456.  
  4457. Within the DO loop, COUNT reads the lines of the file by sending LINEIN 
  4458. messages to the stream object (pointed to by the variable File). The first 
  4459. LINEIN message causes REXX to open the file (the NEW method doesn't open the 
  4460. file). LINEIN, by default, reads one line from the file from the current read 
  4461. position. 
  4462.  
  4463. REXX returns only the text of the line to your program. REXX does not return 
  4464. new-line characters. 
  4465.  
  4466. The DO loop is controlled by the expression "file~lines<>0." The LINES method 
  4467. returns the number of lines remaining to be read in the file, so REXX processes 
  4468. the loop until no lines remain to be read. 
  4469.  
  4470. In the COUNT program, the LINEIN request forced REXX to open the file, but you 
  4471. can also open the file yourself using the OPEN method of the Stream class. By 
  4472. using the OPEN method, you control the mode in which REXX opens the file. When 
  4473. REXX implicitly opens a file because of a LINEIN request, it tries to open the 
  4474. file for both reading and writing. If that fails, it opens the file for 
  4475. reading. To ensure that the file is opened only for reading, you could modify 
  4476. COUNT as follows: 
  4477.  
  4478. /* COUNT.CMD -- counts the words in a file                         */
  4479. parse arg path              /* Get file name from command line     */
  4480. count=0                     /* Initialize a counter                */
  4481. file=.stream~new(path)      /* Create a stream object for the file */
  4482. openrc=file~open('read')    /* Open the file for reading           */
  4483. if openrc<>'READY:' then do /* Check the return code               */
  4484.    say 'Could not open' path||'. RC='||openrc
  4485.    exit openrc              /* Bail out                            */
  4486. end
  4487. do while file~lines<>0      /* Loop while there are lines          */
  4488.   text=file~linein          /* Read a line from the file           */
  4489.   count=count+(text~words)  /* Count words and add to counter      */
  4490. end
  4491. file~close                  /* Close the file                      */
  4492. say count                   /* Display the count                   */
  4493.  
  4494. The CLOSE method, used near the end of the above example, closes the file. A 
  4495. CLOSE isn't required. REXX will close the stream for you when the program ends. 
  4496. However, it's a good idea to CLOSE streams when you are done with them so that 
  4497. the resource is immediately available for other uses (perhaps by other OS/2 
  4498. processes). 
  4499.  
  4500.  
  4501. ΓòÉΓòÉΓòÉ 8.3. Reading a Text File into an Array ΓòÉΓòÉΓòÉ
  4502.  
  4503. REXX provides a Stream method, named MAKEARRAY, that reads the contents of a 
  4504. stream into an array object. MAKEARRAY is very handy when you need to read an 
  4505. entire file into memory for processing. You can read the entire file with a 
  4506. single REXX clause--no looping is necessary. 
  4507.  
  4508. The following example (CVIEW.CMD) uses the MAKEARRAY method to read the entire 
  4509. CONFIG.SYS file into an array object. CVIEW displays selected lines from 
  4510. CONFIG.SYS. A search argument can be specified when starting CVIEW: 
  4511.  
  4512. cview libpath
  4513.  
  4514. CVIEW will prompt for a search argument if you don't specify one. 
  4515.  
  4516. If CVIEW finds the string, it displays the line on which the string is found. 
  4517. CVIEW continues to prompt for new search strings until you enter "Q" in 
  4518. response to the prompt. 
  4519.  
  4520. /* CVIEW -- display lines from CONFIG.SYS                            */
  4521. parse upper arg search_string      /* Get any command line argument  */
  4522. file=.stream~new('c:\config.sys')  /* Create stream object */
  4523. lines=file~makearray(line)         /* Read file into an array object */
  4524.                                    /* LINES points to the array obj. */
  4525. do forever
  4526.    if search_string='' then do     /* Prompt for user input          */
  4527.       say 'Enter a search string or Q to quit:'
  4528.       parse upper pull search_string
  4529.       if search_string='Q' then exit
  4530.    end  /* Do */
  4531.    do i over lines                  /* Scan the array                */
  4532.       if pos(search_string,translate(i))>0 then do
  4533.          say i                      /* Display any line that matches */
  4534.          say '='~copies(20)
  4535.       end  /* Do */
  4536.    end /* do */
  4537.    search_string=''                 /* Reset for next search         */
  4538. end /* do */
  4539.  
  4540.  
  4541. ΓòÉΓòÉΓòÉ 8.4. Reading Specific Lines of a Text File ΓòÉΓòÉΓòÉ
  4542.  
  4543. You can read a specific line of a text file by entering a line number as an 
  4544. argument on the LINEIN method. In this example, line 3 is read from CONFIG.SYS: 
  4545.  
  4546. /* Read and display line 3 of CONFIG.SYS */
  4547. infile=.stream~new('c:\config.sys')
  4548. say infile~linein(3)
  4549.  
  4550. You don't necessarily reduce file I/O by using specific line numbers. Because 
  4551. text files typically do not have a specific record length, REXX must read 
  4552. through the file counting line-end characters to find the line you want. 
  4553.  
  4554.  
  4555. ΓòÉΓòÉΓòÉ 8.5. Writing a Text File ΓòÉΓòÉΓòÉ
  4556.  
  4557. To write lines of text to a file, use the LINEOUT method. By default, LINEOUT 
  4558. appends to an existing file. The following example adds an item to a to-do list 
  4559. that is maintained as a simple text file: 
  4560.  
  4561. /* TODO.CMD -- add to a todo list                              */
  4562. parse arg text
  4563. file=.stream~new('todo.dat')      /* Create a stream object    */
  4564. file~lineout(date() time() text)  /* Append a line to the file */
  4565. exit
  4566.  
  4567. In TODO.CMD, a text string is provided as the only argument on LINEOUT. REXX 
  4568. writes the line of text to the file and then writes a new-line character. You 
  4569. do not have to provide a new-line character in the string being written. 
  4570.  
  4571. If you want to overwrite a file, specify a line number as a second argument. 
  4572. When a line number is specified, REXX uses it to position the write pointer 
  4573. before writing: 
  4574.  
  4575. file~lineout('13760-0006',35)  /* Replace line 35 */
  4576.  
  4577. For text files, write positioning has a somewhat specialized use. REXX does not 
  4578. prevent you from overwriting existing new-line characters in the file.  REXX 
  4579. writes whatever line you give it at whatever write position you tell it to use. 
  4580. Consequently, if you want to replace a line of the file without overlaying 
  4581. following lines, the line you write must be exactly the same length as the line 
  4582. you are replacing. Writing a line that's shorter than an existing line will 
  4583. leave part of the old line in the file. 
  4584.  
  4585. Also, don't assume that positioning the write pointer to line 1 will cause the 
  4586. file to be replaced. Yes, REXX will start writing over the existing data 
  4587. starting at line 1, but if you happen to write fewer bytes than previously 
  4588. existed in the file, your data will be followed by the remainder of the old 
  4589. file. 
  4590.  
  4591. To replace a file, use the OPEN method with WRITE REPLACE or BOTH REPLACE as an 
  4592. argument. In the following example, a file named TEMP.DAT is replaced with a 
  4593. random number of lines. TEMP.DAT is then read and displayed. You can run the 
  4594. example repeatedly to verify that TEMP.DAT is replaced on each run. 
  4595.  
  4596. /* REPFILE.CMD -- demonstrates file replacement                       */
  4597. testfile=.stream~new('temp.dat') /* Create a new stream object        */
  4598. testfile~open('both replace')    /* Open for read, write, and replace */
  4599. numlines=random(1,100)           /* Pick a number from 1 to 100       */
  4600. runid=random(1,9999)             /* Pick a run identifier             */
  4601. do i=1 to numlines               /* Write the lines                   */
  4602.    testfile~lineout('Run ID:'||runid 'Line number' i)
  4603. end
  4604.  
  4605. /* Now read and display the file.  The read pointer is already at the */
  4606. /* beginning of the file.  MAKEARRAY reads from the read position to  */
  4607. /* the end of the file and returns an array object containing the     */
  4608. /* lines.                                                             */
  4609. filedata=testfile~makearray('line')
  4610. do i over filedata
  4611.    say i
  4612. end
  4613. testfile~close
  4614.  
  4615. The REPFILE example also demonstrates that REXX maintains separate read and 
  4616. write pointers to a stream. Notice that we started reading without 
  4617. repositioning the read pointer. Since we hadn't yet read anything, the read 
  4618. pointer was still at the beginning of the file. The write pointer, however, is 
  4619. at the end of the file. 
  4620.  
  4621.  
  4622. ΓòÉΓòÉΓòÉ 8.6. Reading Binary Files ΓòÉΓòÉΓòÉ
  4623.  
  4624. For our purposes, a binary file is any file whose data is not organized into 
  4625. lines by new-line characters. In most cases, you'll use the character I/O 
  4626. methods (such as CHARS, CHARIN, CHAROUT) on these files. There is one 
  4627. exception, however, which will also be discussed. 
  4628.  
  4629. Let's start by reading an entire binary file into a single REXX variable. 
  4630. Suppose, for example, that you feel compelled to read the data in the DOINK.WAV 
  4631. file (supplied with OS/2 multimedia support in c:\mmos2\sounds) into a 
  4632. variable. Here's how to do it: 
  4633.  
  4634. /* GETDOINK -- reads DOINK.WAV into a variable          */
  4635. doinkf=.stream~new('c:\mmos2\sounds\doink.wav')
  4636. say 'Number of characters in the file=' doinkf~chars
  4637.  
  4638. /* Read the whole WAV file into a single REXX variable. */
  4639. /* REXX variables are limited by available memory.      */
  4640. mydoink=doinkf~charin(1,doinkf~chars)
  4641. say 'Number of characters read into variable' mydoink~length
  4642.  
  4643. The CHARIN method returns a string of characters from the stream, which in this 
  4644. case is DOINK.WAV. CHARIN accepts two optional arguments. When no arguments are 
  4645. specified, CHARIN reads one character from the current read position and then 
  4646. advances the read pointer. 
  4647.  
  4648. The first argument is a start position for reading the file. We specified 1 so 
  4649. that CHARIN would begin reading with the first character of the file. We could 
  4650. have omitted the first argument to get the same result. 
  4651.  
  4652. The second argument tells how many characters to read. We want to read all the 
  4653. characters, so we specified doinkf~chars as the second argument. The CHARS 
  4654. method returns the number of characters remaining to be read in the input 
  4655. stream receiving the message. CHARIN then returns all the characters in the 
  4656. stream. DOINK.WAV has about 7500 characters. 
  4657.  
  4658.  
  4659. ΓòÉΓòÉΓòÉ 8.7. Reading Text Files a Character at a Time ΓòÉΓòÉΓòÉ
  4660.  
  4661. You may be wondering whether you can use the CHARIN and other character methods 
  4662. on text files. You can. Because you are reading the file as characters, 
  4663. however, CHARIN returns the line-end characters to your program. Line methods, 
  4664. you'll recall, don't return the line-end characters to your program. 
  4665.  
  4666. The line-end characters on OS/2 consist of a carriage return (ASCII value of 
  4667. 13) and a line feed (ASCII value of 10). REXX adds these characters to the end 
  4668. of every line written using the LINEOUT method. Text-processing applications 
  4669. such as the OS/2 Enhanced Editor also add the characters. When reading a text 
  4670. file with CHARIN, interpret an ASCII sequence of 13 followed by 10 as the end 
  4671. of a line. 
  4672.  
  4673. To see what we mean, run the following program. It writes lines to a file using 
  4674. LINEOUT and then reads those lines using CHARIN. (Yes, you can intermix the use 
  4675. of line methods and character methods.) REXX maintains separate read and write 
  4676. pointers, so there is no need to close the file or seek to another position 
  4677. before reading the lines just written. 
  4678.  
  4679. /* LINECHAR.CMD -- demonstrate line end characters                  */
  4680. file=.stream~new('test.dat')  /* Create a new stream object         */
  4681.  
  4682. file~open('both replace')  /* Open the file for reading and writing */
  4683. do i=1 to 3                /* Write three lines to the file         */
  4684.    file~lineout('Line' i)
  4685. end /* do */
  4686.  
  4687. do while file~chars<>0     /* Read the file a character at a time   */
  4688.    byte=file~charin        /* Read a character                      */
  4689.    ascii_value=byte~c2d    /* Convert character to a decimal value  */
  4690.    if ascii_value=13 then        /* Carriage return?                */
  4691.       say 'Carriage return'
  4692.    else if ascii_value=10 then   /* Line feed?                      */
  4693.       say 'Line feed'
  4694.    else say byte ascii_value     /* Ordinary character              */
  4695. end /* do */
  4696. file~close                       /* Close the file                  */
  4697.  
  4698. Many text-processing programs also write an end-of-file character (ASCII value 
  4699. 26) after the last line. You'll want to check for that character also when 
  4700. processing text files with character methods. To see for yourself, use the OS/2 
  4701. Enhanced Editor for Presentation Manager (EPM) to edit the TEST.DAT file 
  4702. created by the preceding example. From EPM you don't need to make any changes. 
  4703. Simply save and close the file by pressing the F4 key. EPM will add the 
  4704. end-of-file character to the file. Then run the following program to verify it: 
  4705.  
  4706. /* EPMCHAR.CMD -- demonstrate end-of-file characters                */
  4707. file=.stream~new('test.dat')  /* Create a new stream object         */
  4708.  
  4709. do while file~chars<>0     /* Read the file a character at a time   */
  4710.    byte=file~charin        /* Read a character                      */
  4711.    ascii_value=byte~c2d    /* Convert character to a decimal value  */
  4712.    if ascii_value=13 then        /* Carriage return?                */
  4713.       say 'Carriage return'
  4714.    else if ascii_value=10 then   /* Line feed?                      */
  4715.       say 'Line feed'
  4716.    else if ascii_value=26 then   /* End of file?                    */
  4717.       say 'End of File'
  4718.    else say byte ascii_value     /* Ordinary character              */
  4719. end /* do */
  4720.  
  4721. REXX doesn't write end-of-file characters when it closes a file that has been 
  4722. opened for writing. 
  4723.  
  4724. Can you use line methods to read binary files? It's not recommended. Your 
  4725. binary file might not contain any new-line characters. And, if it did, the 
  4726. characters probably aren't meant to be interpreted as new-line characters. 
  4727.  
  4728.  
  4729. ΓòÉΓòÉΓòÉ 8.8. Writing Binary Files ΓòÉΓòÉΓòÉ
  4730.  
  4731. To write a binary file, use CHAROUT. CHAROUT writes only the characters that 
  4732. you specify in an argument to the method. CHAROUT does not add carriage-return 
  4733. and line-feed characters to the end of the string. Here is an example: 
  4734.  
  4735. /* JACK.CMD -- demonstrate that CHAROUT does not add new-line characters */
  4736. filebin=.stream~new('binary.dat')   /* Create a new stream object       */
  4737. filebin~open('replace')             /* Open the file for replacement    */
  4738. do i=1 to 50                        /* Write fifty strings              */
  4739.   filebin~charout('All work and no play makes Jack a dull boy. ')
  4740. end
  4741. filebin~close                  /* Close the file so we can display it   */
  4742. '@echo off'                    /* Suppress echo of OS/2 commands        */
  4743. 'type binary.dat'              /* Use OS/2 TYPE command to display file */
  4744.  
  4745. Because new-line characters are not added, the text displayed by the TYPE 
  4746. command is concatenated. 
  4747.  
  4748. CHAROUT writes the string specified and advances the write pointer. If you want 
  4749. to position the write pointer before writing the string, specify the starting 
  4750. position as a second argument: 
  4751.  
  4752. filebin~charout('Jack is loosing it.',30) /* start writing at character 30 */
  4753.  
  4754. In the example, we explicitly open and close the file. If you don't open the 
  4755. file, REXX attempts to open the file for both reading and writing. If you don't 
  4756. close the file, REXX closes it when the procedure ends. If you omit the CLOSE 
  4757. method in the above example, the OS/2 TYPE command won't type the file. To 
  4758. OS/2, the file doesn't yet exist because it is not yet closed. 
  4759.  
  4760.  
  4761. ΓòÉΓòÉΓòÉ 8.9. Closing Files ΓòÉΓòÉΓòÉ
  4762.  
  4763. If you don't explicitly close a file, REXX closes the file for you at the end 
  4764. of the procedure (that is, the end of the CMD file in which the files were 
  4765. opened). If your procedure is being called as an external procedure by some 
  4766. other REXX program, REXX will close the files before returning to the caller. 
  4767. In any case, it's a good idea to explicitly close files when you are done with 
  4768. them. 
  4769.  
  4770.  
  4771. ΓòÉΓòÉΓòÉ 8.10. Direct File Access ΓòÉΓòÉΓòÉ
  4772.  
  4773. REXX provides several ways for you to read records of a file directly (that is, 
  4774. in random order). The following example, DIRECT.CMD, shows seven different 
  4775. cases that illustrate some of your options. 
  4776.  
  4777. DIRECT opens a file for both reading and writing, which is indicated by the 
  4778. BOTH argument on the OPEN method. The REPLACE argument on the OPEN method 
  4779. causes any existing DIRECT.DAT file to be replaced. 
  4780.  
  4781. The OPEN method also has a couple of arguments we haven't yet seen: BINARY and 
  4782. RECLENGTH. Both of these arguments are useful for direct file access. 
  4783.  
  4784. The BINARY argument opens the stream in binary mode, which means that line-end 
  4785. characters are ignored. Binary mode is useful when you want to process binary 
  4786. data using line methods. From studying the example you'll see that it is easier 
  4787. to use line methods for direct access.  With line methods, you can seek to a 
  4788. position in a file using line numbers.  With character methods, you must 
  4789. calculate a character displacement into the file. 
  4790.  
  4791. The RECLENGTH argument defines a record length of 50 for the file. The 
  4792. RECLENGTH argument makes it possible for you to use line methods on a 
  4793. binary-mode stream. Since REXX now knows how long each record is, it can 
  4794. calculate a displacement into a file for a given record number and read the 
  4795. record directly. 
  4796.  
  4797. /* DIRECT -- demonstration of direct file access                      */
  4798. db=.stream~new('direct.dat')
  4799. db~open('both replace binary reclength 50')
  4800.  
  4801. /* Write three records of 50 bytes each using LINEOUT                 */
  4802. db~lineout('Cole, Gary:  Blue')
  4803. db~lineout('McGuire, Rick: Red')
  4804. db~lineout('Pritko, Steve: Red. Oops.. I mean blue!')
  4805.  
  4806. /* Case 1: Read the records in order using LINEIN.                    */
  4807. say 'Case 1: Sequential reads with LINEIN...'
  4808. do i=1 to 3
  4809.    say db~linein
  4810. end
  4811. say 'Press Enter to continue'; parse pull resp
  4812.  
  4813. /* Case 2: Read records in random order using LINEIN                  */
  4814. say 'Case 2: Random reads with LINEIN...'
  4815. do i=1 to 5
  4816.    lineno=random(1,3)
  4817.    say 'Record' lineno '=' db~linein(lineno)
  4818. end
  4819. say 'Press Enter to continue'; parse pull resp
  4820.  
  4821. /* Case 3: Read entire file with CHARIN                               */
  4822. say 'Case 3: Read entire file with a single CHARIN...'
  4823. say db~charin(1,150)
  4824. say 'Press Enter to continue'; parse pull resp
  4825.  
  4826. /* Case 4: Read file sequentially with CHARIN                         */
  4827. say 'Case 4: Sequential reads with CHARIN...'
  4828. db~seek(1 read)         /* Reposition read pointer                    */
  4829. do i=1 to 3
  4830.    say db~charin(,50)
  4831. end
  4832. say 'Press Enter to continue'; parse pull resp
  4833.  
  4834. /* Case 5: Read records in random order with CHARIN                   */
  4835. say 'Case 5: Random reads with CHARIN...'
  4836. do i=1 to 5
  4837.    lineno=random(1,3)
  4838.    charno=((lineno-1)*50)+1
  4839.    say 'Record' lineno 'Character' charno '=' db~charin(charno,50)
  4840. end
  4841. say 'Press Enter to continue'; parse pull resp
  4842.  
  4843. /* Case 6: Write records in random order with LINEOUT                 */
  4844. say 'Case 6: Replace record 2 with LINEOUT'
  4845. db~lineout('This should replace line 2',2)
  4846. do i=1 to 3
  4847.    say db~linein(i)
  4848. end
  4849. say 'Press Enter to continue'; parse pull resp
  4850.  
  4851. /* Case 7: Write records in random order with CHAROUT                 */
  4852. say 'Case 7: Replace record 2 with CHARIN...'
  4853. db~charout('New record 2 from CHAROUT'~left(50,'.'),51)
  4854. db~seek(1 read)         /* Reposition read pointer                    */
  4855. do i=1 to 3
  4856.    say db~charin(,50)
  4857. end
  4858. say 'Press Enter to continue'; parse pull resp
  4859. db~close
  4860.  
  4861. After opening the file, DIRECT writes three records using LINEOUT. Notice that 
  4862. we didn't pad the records to 50 characters. REXX handles that for us. Because 
  4863. the file is opened in binary mode, REXX does not write line-end characters at 
  4864. the end of each line. It just writes the strings one after another to the 
  4865. stream. 
  4866.  
  4867. In Case 1, the LINEIN method is used to read the file. Because the file is open 
  4868. in binary mode, LINEIN doesn't look for line-end characters to mark the end of 
  4869. a line. Instead, it relies on the record length that you specify on open. In 
  4870. fact, if there happened to be a carriage-return/line-feed sequence of the line, 
  4871. REXX would return those characters to your program. 
  4872.  
  4873. Case 2 demonstrates how to read the file in random order. In this case, we use 
  4874. the RANDOM function to choose a record to retrieve. Then we specify the desired 
  4875. record number as an argument on LINEIN. Note that records are numbered starting 
  4876. from 1, not from 0. Because the file is opened in binary mode, REXX doesn't 
  4877. look for line-end characters.  It uses the RECLENGTH to determine where to 
  4878. read. When used in this way, the LINEIN method can retrieve a line directly, 
  4879. without having to scan through the file counting line-end characters. 
  4880.  
  4881. Case 3 proves that no line-end characters exist in the file. The CHARIN method 
  4882. reads the entire file. SAY displays the returned string as one long string. If 
  4883. REXX inserted line-end characters, each record would be displayed on a separate 
  4884. line. 
  4885.  
  4886. Case 4 shows how to read the binary mode file sequentially using CHARIN. But 
  4887. before reading the file, we need to reset the read pointer to the beginning of 
  4888. the file. (Case 3 leaves the read pointer at the end of the file.) We used a 
  4889. SEEK method to reset the read pointer to character 1, which is the beginning of 
  4890. the file. As with lines, REXX numbers characters starting with 1, not 0. 
  4891. Position 1 is the first character of the file. 
  4892.  
  4893. By default, the number specified on SEEK refers to a character positioning. You 
  4894. can also seek by line number or by offsets. SEEK allows offsets from the 
  4895. current read or write position, or from the beginning or ending of the file. If 
  4896. you prefer typing longer method names, you can use POSITION as a synonym for 
  4897. SEEK. 
  4898.  
  4899. In the loop in Case 4, the first argument on CHARIN is omitted. The first 
  4900. argument tells where to position the read pointer. If it is omitted, REXX 
  4901. automatically advances the read pointer based on the number of characters you 
  4902. are reading. 
  4903.  
  4904. Case 5 demonstrates how to read records in random order with CHARIN. In the 
  4905. loop, a random record number is selected and assigned to variable lineno. This 
  4906. record number is then converted to a character number, which can be used to 
  4907. specify the read position on CHARIN. Compare Case 5 with Case 2. In Case 2, 
  4908. which uses line methods, it isn't necessary to perform a calculation, you just 
  4909. request the record you want. 
  4910.  
  4911. Cases 6 and 7 write records in random order. Case 6 uses LINEOUT, while Case 7 
  4912. uses CHAROUT. Because the file is opened in binary mode, LINEOUT doesn't write 
  4913. line-end characters. You can write over a line by specifying a line number. 
  4914. With CHAROUT, you need to calculate the character position of the line to be 
  4915. replaced. Also unlike LINEOUT, you need to ensure that the string being written 
  4916. with CHAROUT is padded to the appropriate record length. Otherwise, part of the 
  4917. record being replaced will remain in the file. 
  4918.  
  4919. Consequently, for random reading of files with fixed length records, line 
  4920. methods are often the better choice. However, one limitation of the line 
  4921. methods is that you cannot use them to write sparse records. That is, if a file 
  4922. already has 200 records, you can use LINEOUT to write record 201, but you 
  4923. cannot use LINEOUT to write record 300. With CHAROUT, you can open a new file 
  4924. and start writing at character position 5000 if you choose. 
  4925.  
  4926.  
  4927. ΓòÉΓòÉΓòÉ 8.11. Does the File Exist? ΓòÉΓòÉΓòÉ
  4928.  
  4929. To check for the existence of a file, use the QUERY method of the Stream class. 
  4930. The following ISTHERE.CMD program accepts a file name as a command line 
  4931. argument and checks for the existence of that file. 
  4932.  
  4933. /* ISTHERE.CMD -- test for the existence of a file       */
  4934. parse arg fid                    /* Get the file name    */
  4935. qfile=.stream~new(fid)           /* Create stream object */
  4936. if qfile~query('exists')='' then /* Check for existence  */
  4937.    say fid 'does not exist.'
  4938. else
  4939.    say fid 'exists.'
  4940.  
  4941. In the example, a stream object is created for the file even though it may not 
  4942. exist. This is perfectly acceptable. Remember that the file is not opened when 
  4943. the stream object is created. 
  4944.  
  4945. The QUERY method accepts one argument. To check for existence, specify the 
  4946. string 'exists' as shown above. If the file exists, QUERY returns the full-path 
  4947. specification of the stream object. Otherwise, QUERY returns a null string. 
  4948.  
  4949.  
  4950. ΓòÉΓòÉΓòÉ 8.12. Getting Other Information about a File ΓòÉΓòÉΓòÉ
  4951.  
  4952. The QUERY method can do more than check for the existence of a file. It can 
  4953. return date and time stamps, read position, write position, the size of the 
  4954. file, and so on. The following example shows most of the QUERY arguments. 
  4955.  
  4956. /* INFOON.CMD -- display information about a file */
  4957. parse arg fid
  4958. qfile=.stream~new(fid)
  4959. fullpath=qfile~query('exists')
  4960. if fullpath='' then do
  4961.    say fid 'does not exist.'
  4962.    exit
  4963. end
  4964. qfile~open('both')
  4965. say ''
  4966. say 'Full path name:' fullpath
  4967. say 'Date and time stamps (U.S. format):' qfile~query('datetime')
  4968. say '            (International format):' qfile~query('timestamp')
  4969. say ''
  4970. say 'Handle associated with stream:' qfile~query('handle')
  4971. say '                  Stream type:' qfile~query('streamtype')
  4972. say ''
  4973. say '          Size of the file (characters):' qfile~query('size')
  4974. say ' Read position (in terms of characters):' qfile~query('seek
  4975. read')
  4976. say 'Write position (in terms of characters):' qfile~query('seek
  4977. write') qfile~close
  4978.  
  4979.  
  4980. ΓòÉΓòÉΓòÉ 8.13. Using Standard I/O ΓòÉΓòÉΓòÉ
  4981.  
  4982. All of the preceding topics dealt with reading and writing files. You can use 
  4983. the same methods to read from standard input (usually the keyboard) and to 
  4984. write to standard output (usually the display). You can also use the methods to 
  4985. write to the standard error stream. In Object REXX, these default streams are 
  4986. represented by public objects of the Monitor class: .input, .output, and 
  4987. .error. 
  4988.  
  4989. The streams STDIN, STDOUT, and STDERR are transient streams. For transient 
  4990. streams, you cannot use any method or method argument for positioning the read 
  4991. and write pointers. (You can't, for example, use the SEEK method on STDOUT.) 
  4992.  
  4993. Writing to STDOUT has the same effect as using the SAY instruction. However, 
  4994. the SAY instruction always writes line-end characters at the end of the string. 
  4995. By using the CHAROUT method to write to STDOUT, you can control when line-end 
  4996. characters are written. 
  4997.  
  4998. The following example shows a modified COUNT program. COUNT was introduced 
  4999. earlier in this section. We've modified COUNT to display a progress indicator. 
  5000. For every line processed, COUNT now uses CHAROUT to display a single period. 
  5001. COUNT doesn't write any line-end characters, so the periods wrap to the next 
  5002. line when they reach the end of the line in the OS/2 window. 
  5003.  
  5004. /* COUNT counts the words in a file                    */
  5005. parse arg path                    /* Get the file name */
  5006. count=0                                 /* Initialize the count */
  5007. file=.stream~new(path)     /* Create a stream object for the input file */
  5008. do while file~lines<>0        /* Process each line of the file */
  5009.    text=file~linein           /* Read a line                   */
  5010.    count=count+(text~words)   /* Count blank-delimited tokens  */
  5011.    .output~charout('.')       /* Write period to STDOUT        */
  5012. end
  5013. say ''
  5014. say count
  5015.  
  5016. Reading from STDIN using LINEIN is similar to reading with the PARSE PULL 
  5017. instruction: 
  5018.  
  5019. /* INEXAM.CMD -- example of reading STDIN with LINEIN */
  5020.  
  5021. /* Prompt for input with SAY and PARSE instructions   */
  5022. say 'What is your name?'
  5023. parse pull response
  5024. say 'Hi' response
  5025. say ''
  5026.  
  5027. /* Now prompt using LINEOUT and LINEIN                */
  5028. .output~lineout('What is your name?')
  5029. response=.input~linein
  5030. .output~lineout('Hi' response)
  5031.  
  5032. Using character methods with STDIN and STDOUT gives you more control over the 
  5033. reading and writing of line-end characters. In the following example, the 
  5034. prompting string is written to STDOUT using CHAROUT. Because CHAROUT doesn't 
  5035. add any line-end characters to the stream, the display cursor is positioned 
  5036. after the prompt string on the same line. 
  5037.  
  5038. /* INCHAR.CMD -- example of reading STDIN with CHARIN */
  5039. .output~charout('What is your name? ')
  5040. response=.input~charin(,10)
  5041. .output~charout('Hi' response)
  5042.  
  5043. CHARIN is used to read the user's response. The user's keystrokes are not 
  5044. returned to your program until the user presses the Enter key. In the example, 
  5045. a length of 10 is specified. If fewer characters than the specified length are 
  5046. available, CHARIN waits until they become available. Otherwise, the characters 
  5047. are returned to your program. As usual, CHARIN does not strip any 
  5048. carriage-return or line-feed characters before returning the string to your 
  5049. program. You can observe this with INCHAR by typing several strings that are 
  5050. fewer than ten characters and pressing Enter after each string: 
  5051.  
  5052. [C:\]inchar
  5053. What is your name? John
  5054. Q.
  5055. Public
  5056. Hi John
  5057. Q.
  5058. Pu
  5059.  
  5060.  
  5061. ΓòÉΓòÉΓòÉ 8.14. Using Devices ΓòÉΓòÉΓòÉ
  5062.  
  5063. You can use devices by substituting a device name (such as PRN, LPT1, LPT2, 
  5064. COM1, and so on) for the file name when you create a stream object. Then use 
  5065. line or character methods to read or write the device. 
  5066.  
  5067. The following example sends data to a printer (device name PRN in the example). 
  5068. In addition to sending text data, the example also sends a control character 
  5069. for starting a new page. You can send other control characters or escape 
  5070. sequences in a similar manner. (Generally, these are listed in the manual for 
  5071. the device.) 
  5072.  
  5073. Usually the control characters are characters that you cannot type at the 
  5074. keyboard. To use them in your program, send a D2C message to the character's 
  5075. ASCII value as shown in the example. 
  5076.  
  5077. /* PRINTIT.CMD -- Prints a text file                                   */
  5078. say 'Type file name: '           /* prompt for a file name */
  5079. pull filename                   /* ...and get it from the user       */
  5080. infile=.stream~new(filename)
  5081. printer=.stream~new('prn:')
  5082.  
  5083. newpage = 12~d2c                  /* save page-eject character         */
  5084.  
  5085. /* Repeat this loop until no lines remain in the file */
  5086. /* and keep track of the line count with COUNT        */
  5087.  
  5088. do count = 1 until filename~lines = 0
  5089.    if printer~lineout(infile~linein) <>0 then do
  5090.       say 'Error: unable to write to printer'
  5091.       leave
  5092.    end
  5093.    if count // 50 = 0 then                 /* if the line count is a */
  5094.       printer~charout(newpage)             /* multiple of 50, then   */
  5095.                                            /* start a new page by    */
  5096.                                            /* sending the form feed  */
  5097.  
  5098. end                               /* go back to the start of loop    */
  5099.                                   /* until no lines remain           */
  5100.  
  5101. infile~close                      /* close the file                  */
  5102. exit                              /* end the program normally        */
  5103.  
  5104.  
  5105. ΓòÉΓòÉΓòÉ 9. Using SOM Objects ΓòÉΓòÉΓòÉ
  5106.  
  5107. In addition to creating your own classes with REXX, you can use classes, 
  5108. objects, and methods created with the OS/2 System Object Model, or SOM. You no 
  5109. longer need to work in C or C++ to use SOM objects. 
  5110.  
  5111. To build SOM classes for use in REXX, you need to use the SOMobjects Developer 
  5112. Toolkit, Release 2.1 or later. The interface repository files must be available 
  5113. and specified correctly in the SOMIR environment variable. (See Building SOM 
  5114. classes for Use within REXX and the SOMObjects Developer Toolkit publications 
  5115. for more information.) 
  5116.  
  5117. Because the OS/2 Workplace Shell is composed of SOM objects, you now also have 
  5118. complete control over the Workplace Shell from a REXX program. 
  5119.  
  5120. Previously, traditional REXX provided some access to Workplace Shell objects 
  5121. from REXX utility functions (such as SysQueryClassList, SysCreateObject, 
  5122. SysSetObjectData and so on). Now you have access to all workplace classes and 
  5123. methods. The following example shows how to create a folder on the desktop by 
  5124. sending a wpclsNew message to the WPFolder class. 
  5125.  
  5126. folder = .wpFolder~wpclsNew('New Folder', /* Folder will have title "New Folder" */
  5127.                           '',             /* No Specific Setup String            */
  5128.                           .wpDeskTop,     /* Create new folder on the Desktop    */
  5129.                            1)             /* Lock the object to start with       */
  5130. folder~wpOpen(0,0,0)                      /* Open the folder (Default View)      */
  5131. folder~wpClose                            /* Now close the folder.               */
  5132.  
  5133. This REXX information does not include documentation for the workplace classes 
  5134. and methods. They are documented with the reference information for the 
  5135. Workplace Shell in the OS/2 Technical Library. The documentation for the 
  5136. methods is in the form of C-language function calls. To use the function calls 
  5137. to REXX, do the following: 
  5138.  
  5139.    1. Use the function name as the REXX method name. 
  5140.  
  5141.    2. Omit the first parameter (usually a pointer to a class object or a 
  5142.       pointer to an object) as an argument on the REXX call. 
  5143.  
  5144.    3. Use the other parameters in order. When string input is required, simply 
  5145.       use a REXX string. You don't need to worry about supplying a zero 
  5146.       terminator. For numeric or Boolean values, use REXX numbers (which are 
  5147.       actually strings). 
  5148.  
  5149.       In some cases, you'll be using several methods to do a task. Often, one 
  5150.       of these methods will return a pointer to an object, and this pointer 
  5151.       will be needed on other calls. To do this, assign the pointer to a 
  5152.       regular REXX variable and then pass this variable on subsequent methods. 
  5153.  
  5154.       For functions that require pointers to classes, use the class name as 
  5155.       shown in the preceding example (.wpDesktop). Remember to precede the 
  5156.       class name with a period. 
  5157.  
  5158.  In addition to Workplace Shell objects, REXX can also create objects and run 
  5159.  methods for classes created using SOM. 
  5160.  
  5161.  
  5162. ΓòÉΓòÉΓòÉ 9.1. Importing SOM Classes ΓòÉΓòÉΓòÉ
  5163.  
  5164. To use a SOM class in your program, you must first import it. There are two 
  5165. ways to import a SOM class. You can use a ::CLASS directive, or you can send 
  5166. IMPORT message to the SOM class. 
  5167.  
  5168. To import a SOM class named Animal using a directive, specify the keyword 
  5169. EXTERNAL as follows: 
  5170.  
  5171. ::class beasts external 'SOM Animal'
  5172.  
  5173. The literal string following EXTERNAL indicates where we are to import the 
  5174. class from and the name of that class. In this case we are importing the Animal 
  5175. class from SOM. The name Beasts is given to the REXX class. You can use the 
  5176. same name (Animal) if you wish. 
  5177.  
  5178. The second way to import a class is by sending a message to a REXX object in 
  5179. the global environment named SOM. The SOM object has an IMPORT method for 
  5180. importing classes: 
  5181.  
  5182. beastclass = .som~import('animal')
  5183.  
  5184. The argument 'animal' tells the SOM object the name of the class to import from 
  5185. SOM. An object representing this SOM class is returned and assigned to 
  5186. Beastclass. The class name in REXX will be the same as the name of the SOM 
  5187. class. 
  5188.  
  5189. In addition to importing regular SOM classes, you can also import DSOM classes. 
  5190. Importing DSOM classes is very similar to importing a SOM class. To import 
  5191. using directives, you use the ::CLASS directive and must specify DSOM instead 
  5192. of SOM after the EXTERNAL keyword. For example, suppose the Animal class 
  5193. described earlier is a DSOM class. In this case you would code: 
  5194.  
  5195. ::CLASS beasts EXTERNAL 'DSOM Animal'
  5196.  
  5197. For dynamic loading you must first initialize the DSOM environment in REXX. You 
  5198. do this by using: 
  5199.  
  5200. .som~SOMD_INIT
  5201.  
  5202. This installs a new object into the local environment. This object is .DSOM. It 
  5203. functions the same as .SOM, but for DSOM rather than SOM classes. You can now 
  5204. import dynamically, using: 
  5205.  
  5206. beastclass = .DSOM~import('Animal')
  5207.  
  5208.  
  5209. ΓòÉΓòÉΓòÉ 9.2. Sending Messages to SOM Objects ΓòÉΓòÉΓòÉ
  5210.  
  5211. When you import a class using REXX, the REXX class has all the methods included 
  5212. in the SOM class, as well as the methods in REXX's own Class class. This means 
  5213. you can use all the methods of the Class class and the SOM class. You cannot, 
  5214. however, create new methods for SOM classes from REXX. 
  5215.  
  5216. For example, the NEW method (for creating new instances of a class) is part of 
  5217. the Class class. You can send a NEW message to Beastclass to create a new 
  5218. beast: 
  5219.  
  5220. beast=beastclass~new
  5221.  
  5222. As part of its processing, the NEW method calls the somNew method on the SOM 
  5223. class to create the SOM object. NEW returns this newly created object. Use this 
  5224. instance of Beastclass just as you would any other REXX object. You can send it 
  5225. any of the SOM messages appropriate for the object. The following statement, 
  5226. for example, returns the name of the SOM class to which the object belongs: 
  5227.  
  5228. beast~somGetClassName
  5229.  
  5230. Note that we do not need to worry about any conversions from REXX objects 
  5231. (Beastclass) to the real SOM object (the Animal class itself). REXX takes care 
  5232. of that for us. 
  5233.  
  5234.  
  5235. ΓòÉΓòÉΓòÉ 9.3. Conversions from REXX Objects to C/SOM Method Argument Types ΓòÉΓòÉΓòÉ
  5236.  
  5237. When a SOM method is called, a conversion needs to take place from the REXX 
  5238. object to a native SOM type. The method is dispatched using somApply, so some 
  5239. additional conversions occur because the arguments must be passed in a widened 
  5240. form as ANSI defines for va_lists. In general this causes no problems; however 
  5241. in some cases, such as with float or double parameters, a loss of precision may 
  5242. occur because of converting between a double (widened form) and a float. Also 
  5243. because of some rounding conditions, the conversion from the REXX object to a 
  5244. double or float may cause loss of precision. 
  5245.  
  5246. Keep in mind that the default REXX NUMERIC DIGITS setting is 9 (See the Object 
  5247. REXX Reference for details on NUMERIC). This can cause unexpected results if 
  5248. you call a SOM method and pass it a value greater than 999999999 or less than 
  5249. -999999999. You may want to change the NUMERIC DIGITS setting, for example: 
  5250.  
  5251. NUMERIC DIGITS 10
  5252.  
  5253. if you are using large long or ulong values. 
  5254.  
  5255. The limits on the various supported SOM types follow: 
  5256.  
  5257. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5258. ΓöéTYPE             ΓöéMINIMUM                  ΓöéMAXIMUM                  Γöé
  5259. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5260. Γöéboolean          Γöé0 (false)                Γöé1 (true)                 Γöé
  5261. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5262. Γöéchar(*)          Γöé'80'x (-128)             Γöé'7f'x  (127)             Γöé
  5263. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5264. Γöédouble           Γöé2.2250738585072014e-308  Γöé1.7976931348623158e+308  Γöé
  5265. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5266. Γöéfloat(**)        Γöé1.175494351e-38          Γöé3.402823466e+38          Γöé
  5267. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5268. Γöélong             Γöé-2147483648              Γöé2147483647               Γöé
  5269. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5270. Γöéoctet(*)         Γöé'00'x   (0)              Γöé'ff'x (255)              Γöé
  5271. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5272. Γöéshort            Γöé-32768                   Γöé32767                    Γöé
  5273. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5274. Γöéunsigned long    Γöé0                        Γöé4294967295               Γöé
  5275. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5276. Γöéunsigned short   Γöé0                        Γöé65535                    Γöé
  5277. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5278.  
  5279. Note:  The use of types char and octet is not always obvious. Because these are 
  5280.        treated as "8-bit quantity," the parameter from REXX should be a single 
  5281.        character. However, not all characters are exactly representable, so you 
  5282.        may need to use the D2C and X2C built-in functions to achieve the 
  5283.        desired results (see the Object REXX Reference for details about these 
  5284.        functions). 
  5285.  
  5286. For example, to pass the hexadecimal value 'FF'x to a SOM method as type char 
  5287. you would code: 
  5288.  
  5289. x2c('FF'x)
  5290.  
  5291. Or, if you know the decimal value of the code, you can use it (for example, the 
  5292. decimal equivalent of 'FF'x is -1): 
  5293.  
  5294. d2c(-1,1)
  5295.  
  5296. To convert a returned value back to the decimal equivalent, use the C2D 
  5297. function (see the Object REXX Reference for details). For type char, remember 
  5298. to process the value as a signed number (specify 1 as the second argument of 
  5299. the C2D function). 
  5300.  
  5301. For example, if a returned value is 'FF'x, then: 
  5302.  
  5303. c2d(returned_value,1)   /* Returns -2 for type char    */
  5304. c2d(returned_value)     /* Returns +254 for type octet */
  5305.  
  5306.  REXX supports the following parameter or return types: void, short, ushort, 
  5307.  long, ulong, float, double, boolean, char, string, octet, objref, pointer, 
  5308.  struct, and somId, array, and sequence. The support for the struct type is 
  5309.  passthru only. That is, you cannot directly change the individual elements of 
  5310.  a structure, but you can receive it as a return and then pass it back out as a 
  5311.  method parameter. Array and sequence parameters must be REXX array objects or 
  5312.  be capable of returning an array with the MAKEARRAY method. 
  5313.  
  5314.  
  5315. ΓòÉΓòÉΓòÉ 9.4. Methods Requiring INOUT and OUT Arguments ΓòÉΓòÉΓòÉ
  5316.  
  5317. Currently REXX supports only the following types as INOUT and OUT arguments: 
  5318. boolean, char, octet, short, ushort, long, ulong, float, double, and string. 
  5319. Because INOUT and OUT arguments actually update the object data directly, you 
  5320. must use special objects for these arguments. REXX provides a set of SOM 
  5321. objects specifically for these arguments. 
  5322.  
  5323. For each supported INOUT or OUT argument type, there is a matching class that 
  5324. you must use to create the object for a method requiring that type of argument. 
  5325. New instances of these supplied classes have a default value of 0 or '' (a null 
  5326. string). The following table lists the types with the matching Class names and 
  5327. the default values assigned to new instances: 
  5328.  
  5329. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5330. Γöé Table 2. Class names for SOM types       Γöé
  5331. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5332. Γöé CLASS NAME Γöé CLASS TYPE    Γöé DEFAULT VALUE  Γöé
  5333. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5334. Γöé boolean   Γöé DLFBoolean    Γöé 0 (false)    Γöé
  5335. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5336. Γöé char    Γöé DLFChar     Γöé 0 (NULL)     Γöé
  5337. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5338. Γöé octet    Γöé DLFOctet     Γöé 0 (NULL)     Γöé
  5339. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5340. Γöé short    Γöé DLFShort     Γöé 0        Γöé
  5341. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5342. Γöé ushort   Γöé DLFUShort    Γöé 0        Γöé
  5343. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5344. Γöé long    Γöé DLFLong     Γöé 0        Γöé
  5345. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5346. Γöé ulong    Γöé DLFULong     Γöé 0        Γöé
  5347. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5348. Γöé float    Γöé DLFFloat     Γöé 0        Γöé
  5349. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5350. Γöé double   Γöé DLFDouble    Γöé 0        Γöé
  5351. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5352. Γöé string   Γöé DLFString    Γöé '' (a null    Γöé
  5353. Γöé       Γöé         Γöé string)     Γöé
  5354. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5355.  
  5356. This means that to call a method that requires an INOUT argument of type long, 
  5357. you must pass an object of the DLFLong class as the argument for that method. 
  5358. This restriction is only for INOUT and OUT arguments; for any IN argument you 
  5359. can specify an instance of any of the special classes or appropriate REXX 
  5360. classes. 
  5361.  
  5362. To use any of the special classes within REXX you simply need to import the 
  5363. classes (see Importing SOM Classes). 
  5364.  
  5365. All instances of these classes support the following methods: 
  5366.  
  5367.  _get_value Retrieves the current value of the object. 
  5368.  
  5369.  _set_value(newValue) Sets the current value of the object to newValue. 
  5370.  
  5371.  asString Retrieves a string representation of the current value. 
  5372.  
  5373.  In addition, DLFString has the following methods: 
  5374.  
  5375.  _get_maxSize Is the length of the largest string that can be stored into the 
  5376.      object, when using this object as an INOUT or OUT parameter. 
  5377.  
  5378.  _set_maxSize(size) Makes size the length of the largest string that can be 
  5379.      stored into the object, when using this object as an INOUT or OUT 
  5380.      parameter. If _set_value is called with a string longer than size, it 
  5381.      calls _set_maxSize with the new larger value. 
  5382.  
  5383.  
  5384. ΓòÉΓòÉΓòÉ 9.4.1. Building SOM classes for Use within REXX ΓòÉΓòÉΓòÉ
  5385.  
  5386. To build SOM classes for use in REXX, you need to use the SOMobjects Developer 
  5387. Toolkit, Release 2.1 or later, or the Warp Toolkit. You must build the classes 
  5388. into a DLL that can be dynamically loaded, and the loading of the DLL should 
  5389. result in the building of all SOM classes within that DLL. The SOMobjects Users 
  5390. Guide explains how to do this. It is necessary because REXX calls the 
  5391. somFindClass on the SOMClassMgrObject to locate the SOM classes on import. The 
  5392. dllname modifier must be in your IDL file so that SOMClassMgrObject knows which 
  5393. DLL to load for the class. 
  5394.  
  5395. You also need to define the class in the Interface Repository, so that REXX can 
  5396. get information about the class's methods, method parameters, and return types. 
  5397.  
  5398.  
  5399. ΓòÉΓòÉΓòÉ 9.5. REXX and the Workplace Shell ΓòÉΓòÉΓòÉ
  5400.  
  5401. If you are an OS/2 user, you are familiar with the Workplace Shell. The shell 
  5402. provides many objects, including folders, programs, and special-purpose objects 
  5403. such as the shredder. You can manipulate objects with actions such as 
  5404. double-click and dragging and dropping one object on another. These actions 
  5405. send messages to the shell objects. For example, double-click sends a "wpopen" 
  5406. message. Objects respond to these messages by running methods that perform the 
  5407. requested actions. The class of the object receiving the message determines the 
  5408. method used for each action; therefore, opening a folder does something 
  5409. different than opening a program. 
  5410.  
  5411.  
  5412. ΓòÉΓòÉΓòÉ 9.5.1. Sending Messages ΓòÉΓòÉΓòÉ
  5413.  
  5414. You can use REXX to program the shell objects by sending them messages. This 
  5415. lets programs control actions that direct user interaction generally controls. 
  5416. For example, you can create a folder and place a number of program objects in 
  5417. it. REXX supports both procedural and object-oriented access to the Workplace 
  5418. Shell objects. 
  5419.  
  5420.  
  5421. ΓòÉΓòÉΓòÉ 9.5.1.1. Procedural Support ΓòÉΓòÉΓòÉ
  5422.  
  5423. The RexxUtil package includes several functions useful for manipulating the 
  5424. shell. The RexxUtil functions are very easy to use, but are not as extensive as 
  5425. the object-oriented support. 
  5426.  
  5427.  
  5428. ΓòÉΓòÉΓòÉ 9.5.1.2. Object-Oriented Support ΓòÉΓòÉΓòÉ
  5429.  
  5430. Because the Workplace Shell objects are implemented using SOM, REXX provides 
  5431. very powerful and flexible direct access to the shell objects, but accessing 
  5432. the shell objects directly requires programmers to have considerably more 
  5433. knowledge of how the Workplace Shell works. In addition, programming Workplace 
  5434. Shell objects always involves some risk of damaging the shell in a way that 
  5435. might require re-installation of OS/2. 
  5436.  
  5437. As with other SOM classes, the REXX documentation does not include 
  5438. documentation for the workplace classes and methods. These are documented in 
  5439. the OS/2 Technical Library, and the documentation for the methods is in the 
  5440. form of C-language function calls. Before trying any object-oriented REXX 
  5441. programming of the Workplace Shell, you should read this reference material. 
  5442. REXX provides interfaces to the objects, but cannot enforce correct Workplace 
  5443. Shell programming. 
  5444.  
  5445. Do not use any Workplace Shell methods containing INOUT or OUT parameters (for 
  5446. example, wpQueryProgDetails). 
  5447.  
  5448. Some Workplace Shell objects by default cannot be deleted. You may want to 
  5449. issue a wpSetup method to the new object and to make it able to be deleted: 
  5450.  
  5451. wpShredder = .wps~import('WPShredder')
  5452. xshred = wpShredder~new('myShred','',folder,1)
  5453. xshred~wpsetup('NODELETE=NO')
  5454.  
  5455. REXX currently does not support complex Workplace Shell parameters; it supports 
  5456. only string, integer, or boolean. (For example, it cannot support 
  5457. PPROGDETAILS.) 
  5458.  
  5459. REXX Workplace Shell initialization adds a hidden object, OrxInit, to your 
  5460. desktop. This is a WPZORXINIT object. You will notice this only if you query 
  5461. the contents of the desktop folder. 
  5462.  
  5463.  
  5464. ΓòÉΓòÉΓòÉ 9.6. Accessing Workplace Shell Objects ΓòÉΓòÉΓòÉ
  5465.  
  5466. REXX automatically imports several workplace classes and adds them to the 
  5467. global environment. These include: 
  5468.  
  5469.       WPObject 
  5470.       WPTransient 
  5471.       WPAbstract 
  5472.       WPProgram 
  5473.       WPFolder 
  5474.  
  5475.  You can import other workplace classes just as you can import SOM classes, 
  5476.  except for Workplace Shell classes the class server is WPS instead of SOM. 
  5477.  Here are two ways to import the WPClock class: 
  5478.  
  5479.   ::class WPClock external 'WPS WPClock'
  5480.  
  5481.   WPClock = .wps~import('WPClock')
  5482.  
  5483.  REXX also creates an entry in the environment for one other workplace object, 
  5484.  WPDesktop. The other explicitly named system folders can be added to the 
  5485.  environment by running the WPSYSOBJ.CMD utility. The REXX folder names 
  5486.  followed by their workplace functions are: 
  5487.  
  5488.  WPNoWhere The hidden folder 
  5489.  
  5490.  WPOS2SYS The system folder 
  5491.  
  5492.  WPTemps The templates folder 
  5493.  
  5494.  WPStart The startup folder 
  5495.  
  5496.  WPInfo The information folder 
  5497.  
  5498.  WPDrives The drives folder 
  5499.  
  5500.  WPConfig The system setup folder 
  5501.  
  5502.  After calling WPSYSOBJ.CMD, you can refer to the information folder directly 
  5503.  by using .wpinfo. 
  5504.  
  5505.  It is easy to locate other items on the desktop using the WPFIND.CMD utility. 
  5506.  You can use WPFIND directly from a command line or within a program. From a 
  5507.  command line, the syntax is: 
  5508.  
  5509.   wpfind -p name path
  5510.  
  5511.  The path is the title of a workplace object to locate and place into the 
  5512.  global environment name specifies. 
  5513.  
  5514.  From within a program, the syntax is: 
  5515.  
  5516.   obj = wpfind(path)
  5517.  
  5518.  The path is the title of a workplace object that obj will reference. 
  5519.  
  5520.  The path must always be a string. If you are looking for a folder with the 
  5521.  title "Folder2" and know it is inside the folder entitled "Folder1," which 
  5522.  resides on the desktop, you can call it as follows: 
  5523.  
  5524.   is_found=wpfind('Folder1;Folder2')
  5525.  
  5526.  Another way to call WPFIND is to use the folder itself directly. If f1 is the 
  5527.  folder entitled "Folder1" and f2 is the folder entitled "Folder2," the call: 
  5528.  
  5529.   is_found = wpfind(f1~wpQueryTitle';'f2~wpQueryTitle)
  5530.  
  5531.  changes everything in parenthesis to a valid string. 
  5532.  
  5533.  The basic assumption is that the very first folder that using WPFIND searches 
  5534.  is .wpDesktop. WPFIND returns the object itself. If the requested object is 
  5535.  not found, WPFIND returns the NIL object. 
  5536.  
  5537.  The Workplace documentation frequently uses named constant values. REXX 
  5538.  provides the WPCONST.CMD utility to let programmers use the named constants 
  5539.  instead of looking up their values. Running WPCONST.CMD sets up a directory 
  5540.  called WPCONST in the global environment that contains the names and their 
  5541.  values. For example, the OPEN_SETTINGS constant could be referenced as: 
  5542.  
  5543.   .wpconst['OPEN_SETTINGS'].
  5544.  
  5545.  Note:  Use quotation marks around constant names, such as "OPEN_SETTINGS" in 
  5546.         the preceding example. 
  5547.  
  5548.  
  5549. ΓòÉΓòÉΓòÉ 9.6.1. Workplace Shell Example:  Creating Folders ΓòÉΓòÉΓòÉ
  5550.  
  5551. Here is a simple example showing how to create a folder and add objects to it: 
  5552.  
  5553. /* Add the workplace constants to the global environment         */
  5554. call wpconst
  5555.  
  5556. /* Create a new folder with title 'My Folder' on the desktop     */
  5557. newfolder = .wpfolder~new('My Folder','',.wpdesktop,1)
  5558.  
  5559. You may have to rearrange your windows a little bit to make the new folder's 
  5560. icon visible. 
  5561.  
  5562. /* Send a message to the new folder object and show the result   */
  5563. say newfolder~wpquerytitle
  5564.  
  5565. /* Change the title of the new folder                            */
  5566. newfolder~wpsettitle('My Excellent Folder')
  5567.  
  5568. /* Add a program object to the new folder                        */
  5569. .wpprogram~new('REXXTRY','EXENAME=pmrexx.exe;PARAMETERS=REXXTRY',newfolder,1)
  5570.  
  5571. /* Open the new folder and make it current                       */
  5572. newfolder~~wpopen(0,.wpconst['OPEN_DEFAULT'],0)~wpswitchto(0)
  5573.  
  5574. Now double click the REXXTRY icon to verify that the program was added 
  5575. correctly and works as expected. 
  5576.  
  5577. /* All done, close the folder                                    */
  5578. newfolder~wpclose
  5579.  
  5580.  
  5581. ΓòÉΓòÉΓòÉ 9.6.2. A Workplace Shell Example:  Animated Icons ΓòÉΓòÉΓòÉ
  5582.  
  5583. Here is another example showing how to animate a folder's icon. 
  5584.  
  5585. /* Put the workplace system folder names into the environment    */
  5586. call wpsysobj
  5587.  
  5588. sysicon = .wpos2sys~wpqueryicon
  5589.  
  5590. configicon = .wpconfig~wpqueryicon
  5591.  
  5592. /* Create a new folder with title 'My Folder' on the desktop     */
  5593. newfolder = .wpfolder~new('My Folder','',.wpdesktop,1)
  5594.  
  5595. do 20;newfolder~wpseticon(sysicon);newfolder~wpseticon(configicon);end
  5596.  
  5597. For additional examples, see the SOM section of the Object REXX Reference. 
  5598.  
  5599.  
  5600. ΓòÉΓòÉΓòÉ 10. REXX Application Programming Interfaces ΓòÉΓòÉΓòÉ
  5601.  
  5602. This appendix describes how to interface applications to REXX or extend the 
  5603. REXX language by using REXX application programming interfaces (APIs). As used 
  5604. here, the term application refers to programs written in languages other than 
  5605. REXX. Commonly this is the C language. Conventions in this appendix are based 
  5606. on the C language. Refer to a C programming reference manual if you need a 
  5607. better understanding of these conventions. 
  5608.  
  5609. The features described here let an application extend many parts of the REXX 
  5610. language or extend an application with REXX. This includes creating handlers 
  5611. for subcommands, external functions, and system exits. 
  5612.  
  5613.  Subcommands are commands issued from a REXX program. A REXX expression is 
  5614.      evaluated and the result is passed as a command to the currently 
  5615.      "addressed" subcommand handler. Subcommands are used in REXX programs 
  5616.      running as application macros. 
  5617.  
  5618.  Functions are direct extensions of the REXX language. An application can 
  5619.      create functions that extend the native REXX function set. Functions may 
  5620.      be general- purpose extensions or specific to an application. 
  5621.  
  5622.  System exits are programmer-defined variations of the operating system. The 
  5623.      application programmer can tailor the REXX interpreter behavior by 
  5624.      replacing REXX system requests. 
  5625.  
  5626.  Subcommand, function, and system exit handlers have similar coding, 
  5627.  compilation, and packaging characteristics. 
  5628.  
  5629.  In addition, applications can manipulate the variables in REXX programs (see 
  5630.  Variable Pool Interface), and execute REXX routines directly from memory (see 
  5631.  Macrospace Interface). 
  5632.  
  5633.  
  5634. ΓòÉΓòÉΓòÉ 10.1. Handler Characteristics ΓòÉΓòÉΓòÉ
  5635.  
  5636. The basic requirements for subcommand, function, and system exit handlers are: 
  5637.  
  5638.      REXX handlers must use the system linkage convention. Handler functions 
  5639.       should be declared with the appropriate type definition from the 
  5640.       REXXSAA.H include file: 
  5641.  
  5642.         -  RexxSubcomHandler 
  5643.         -  RexxFunctionHandler 
  5644.         -  RexxExitHandler 
  5645.  
  5646.      A REXX handler must be packaged as either: 
  5647.  
  5648.         -  An exported routine within a Dynamic Link Library (DLL) 
  5649.         -  An entry point within an executable (EXE) module 
  5650.  
  5651.      A handler must be registered with REXX before it can be used. REXX uses 
  5652.       the registration information to locate and call the handler. For example, 
  5653.       external function registration of a dynamic link library external 
  5654.       function identifies both the dynamic link library and routine that 
  5655.       contains the external function. Also note: 
  5656.  
  5657.         -  Dynamic link library handlers are global to the OS/2 system; any 
  5658.            REXX program can call them. 
  5659.  
  5660.         -  EXE file handlers are local to the registering process; only a REXX 
  5661.            program running in the same process as an EXE module can call a 
  5662.            handler packaged within that EXE module. 
  5663.  
  5664.  
  5665. ΓòÉΓòÉΓòÉ 10.2. RXSTRINGs ΓòÉΓòÉΓòÉ
  5666.  
  5667. Many of the REXX application programming interfaces pass REXX character strings 
  5668. to and from a REXX procedure. The RXSTRING data structure is used to describe 
  5669. REXX character strings. An RXSTRING is a content-insensitive, flat model 
  5670. character string with a theoretical maximum length of 4 gigabytes. The 
  5671. following structure defines an RXSTRING: 
  5672.  
  5673.  
  5674. RXSTRING data structure
  5675.  
  5676. typedef struct {
  5677.    ULONG           strlength;     /* length of string             */
  5678.    PCH             strptr;        /* pointer to string            */
  5679. } RXSTRING;
  5680. typedef RXSTRING *PRXSTRING;      /* pointer to an RXSTRING       */
  5681.  
  5682. Notes: 
  5683.  
  5684.    1. The REXXSAA.H include file contains a number of convenient macros for 
  5685.       setting and testing RXSTRING values. 
  5686.  
  5687.    2. An RXSTRING can have a value (including the null string, "") or it can be 
  5688.       empty. 
  5689.  
  5690.           If an RXSTRING has a value, the strptr field is non-NULL. The 
  5691.            RXSTRING macro RXVALIDSTRING(string) returns TRUE. 
  5692.  
  5693.           If an RXSTRING is the REXX null string (""), the strptr field is 
  5694.            non-NULL and the strlength field is zero. The RXSTRING macro 
  5695.            RXZEROLENSTRING(string) returns TRUE. 
  5696.  
  5697.           If an RXSTRING is empty, the field strptr is NULL. The RXSTRING 
  5698.            macro RXNULLSTRING(string) returns TRUE. 
  5699.  
  5700.    3. When the REXX interpreter passes an RXSTRING to a subcommand handler, 
  5701.       external function, or exit handler, the interpreter adds a null character 
  5702.       (hexadecimal zero) at the end of the RXSTRING data. You can use the C 
  5703.       string library functions on these strings. However, the RXSTRING data may 
  5704.       also contain null characters. There is no guarantee that the first null 
  5705.       character encountered in an RXSTRING marks the end of the string. Use the 
  5706.       C string functions only when you do not expect null characters in the 
  5707.       RXSTRINGs (such as file names passed to external functions). The 
  5708.       strlength field in the RXSTRING does not include the terminating null 
  5709.       character. 
  5710.  
  5711.    4. On calls to subcommand and external functions handlers, as well as some 
  5712.       of the exit handlers, the REXX interpreter expects an RXSTRING value 
  5713.       returned. The REXX interpreter provides a default RXSTRING with a 
  5714.       strlength of 256 for the returned information. If the returned data is 
  5715.       shorter than 256 characters, the handler can copy the data into the 
  5716.       default RXSTRING and set the strlength field to the length returned. 
  5717.  
  5718.       If the returned data is longer than 256 characters, a new RXSTRING can be 
  5719.       allocated using DosAllocMem. The strptr field must point to the new 
  5720.       storage and the strlength must be set to the string length. The REXX 
  5721.       interpreter will return the newly allocated storage to the system for the 
  5722.       handler routine. 
  5723.  
  5724.  
  5725. ΓòÉΓòÉΓòÉ 10.3. Calling the REXX Interpreter ΓòÉΓòÉΓòÉ
  5726.  
  5727. A REXX program may be run directly by the operating system or from within an 
  5728. application program. 
  5729.  
  5730.  
  5731. ΓòÉΓòÉΓòÉ 10.3.1. From the Operating System ΓòÉΓòÉΓòÉ
  5732.  
  5733. The CMD.EXE command shell calls the REXX interpreter for the user: 
  5734.  
  5735.      At command prompts 
  5736.  
  5737.      In calls from CMD (batch) files 
  5738.  
  5739.       Note:  Use the OS/2 CALL command to call a REXX program in a batch file 
  5740.              if you want control to return to the caller. 
  5741.  
  5742.      From the object that represents the program 
  5743.  
  5744.  
  5745. ΓòÉΓòÉΓòÉ 10.3.2. From within an Application ΓòÉΓòÉΓòÉ
  5746.  
  5747. The REXX interpreter is an dynamic link library (DLL) routine. Any application 
  5748. can call the REXX interpreter to run a REXX program. The interpreter is fully 
  5749. re-entrant and supports REXX procedures running on multiple threads within the 
  5750. same process. 
  5751.  
  5752. A C-language prototype for calling REXX is in the REXXSAA.H include file. 
  5753.  
  5754.  
  5755. ΓòÉΓòÉΓòÉ 10.3.3. The RexxStart Function ΓòÉΓòÉΓòÉ
  5756.  
  5757. RexxStart calls the REXX interpreter to run a REXX procedure. 
  5758.  
  5759. Topics: 
  5760.  
  5761.      Syntax 
  5762.  
  5763.      Parameters 
  5764.  
  5765.      Returns 
  5766.  
  5767.      Example 
  5768.  
  5769.  
  5770. ΓòÉΓòÉΓòÉ 10.3.3.1. RexxStart - Syntax ΓòÉΓòÉΓòÉ
  5771.  
  5772. RexxStart(ArgCount, ArgList, ProgramName, Instore, EnvName, CallType,
  5773. Exits, ReturnCode, Result)
  5774.  
  5775.  
  5776. ΓòÉΓòÉΓòÉ 10.3.3.2. RexxStart - Parameters ΓòÉΓòÉΓòÉ
  5777.  
  5778.  ArgCount (LONG) - input 
  5779.            The number of elements in the ArgList array. This is the value that 
  5780.            the ARG() built-in function in the REXX program returns. ArgCount 
  5781.            includes RXSTRINGs that represent omitted arguments. Omitted 
  5782.            arguments are empty RXSTRINGs (strptr is NULL). 
  5783.  
  5784.  ArgList (PRXSTRING) - input 
  5785.            An array of RXSTRING structures that are the REXX program arguments. 
  5786.  
  5787.  ProgramName (PSZ) - input 
  5788.            Address of the ASCIIZ name of the REXX procedure. If Instore is 
  5789.            NULL, ProgramName must contain at least the file name of the REXX 
  5790.            procedure. You can also provide an extension, drive, and path 
  5791.            specification. If you do not specify a file extension, the default 
  5792.            is ".CMD". A REXX program can use any extension. If you do not 
  5793.            provide the path and drive, the REXX interpreter uses the usual file 
  5794.            search (current directory, then environment path). 
  5795.  
  5796.            If Instore is not NULL, ProgramName is the name used in the PARSE 
  5797.            SOURCE instruction. If Instore requests a REXX procedure from the 
  5798.            macrospace, ProgramName is the macrospace function name (see 
  5799.            Macrospace Interface). 
  5800.  
  5801.  Instore (PRXSTRING) - input 
  5802.            An array of two RXSTRING descriptors for in-storage REXX procedures. 
  5803.            If the strptr fields of both RXSTRINGs are NULL, the interpreter 
  5804.            searches for REXX procedure ProgramName in the REXX macrospace (see 
  5805.            Macrospace Interface). If the procedure is not in the macrospace, 
  5806.            the call to RexxStart terminates with an error return code. 
  5807.  
  5808.            If either Instore strptr field is not NULL, Instore is used to run a 
  5809.            REXX procedure directly from storage. 
  5810.  
  5811.            Instore[0] 
  5812.                           An RXSTRING describing a memory buffer containing the 
  5813.                           REXX procedure source. The source must be an exact 
  5814.                           image of a REXX procedure disk file (complete with 
  5815.                           carriage returns, line feeds, and end-of-file 
  5816.                           characters). 
  5817.  
  5818.            Instore[1] 
  5819.                           An RXSTRING containing the translated image of the 
  5820.                           REXX procedure. If Instore[1] is empty, the REXX 
  5821.                           interpreter returns the translated image in 
  5822.                           Instore[1] when the REXX procedure finishes running. 
  5823.                           The translated image may be used in Instore[1] on 
  5824.                           subsequent RexxStart calls. 
  5825.  
  5826.                           If Instore[1] is not empty, the interpreter runs the 
  5827.                           translated image directly. The program source 
  5828.                           provided in Instore[0] is used only if the REXX 
  5829.                           procedure uses the SOURCELINE built-in function. 
  5830.                           Instore[0] can be empty if SOURCELINE is not used. If 
  5831.                           Instore[0] is empty and the procedure uses the 
  5832.                           SOURCELINE built-in function, SOURCELINE() returns 0 
  5833.                           lines and any attempt to access the source returns 
  5834.                           Error 40. 
  5835.  
  5836.                           If Instore[1] is not empty, but does not contain a 
  5837.                           valid REXX translated image, unpredictable results 
  5838.                           can occur. The REXX interpreter may be able to 
  5839.                           determine that the translated image is incorrect and 
  5840.                           retranslate the source. 
  5841.  
  5842.                           Instore[1] is both an input and an output parameter. 
  5843.  
  5844.            If the procedure is executed from disk, the Instore pointer must be 
  5845.            NULL. If the first argument string in Arglist contains the string 
  5846.            "//T" and the CallType is RXCOMMAND, the interpreter translates the 
  5847.            procedure source and writes the translated image to disk. Since the 
  5848.            Instore pointer is NULL, the translated image is not returned in an 
  5849.            Instore parameter. 
  5850.  
  5851.            The program calling RexxStart must release Instore[1] using 
  5852.            DosFreeMem when the translated image is no longer needed. 
  5853.  
  5854.            The format of the translated image of a REXX program is not a 
  5855.            programming interface. Only the interpreter version that created the 
  5856.            image can run the translated image. Therefore, do not move a 
  5857.            translated image to other systems or save it for later use. You can, 
  5858.            however, use the translated image multiple times during a single 
  5859.            application instance. 
  5860.  
  5861.  EnvName (PSZ) - input 
  5862.            Address of the ASCIIZ initial ADDRESS environment name. The ADDRESS 
  5863.            environment is a subcommand handler registered using 
  5864.            RexxRegisterSubcomExe or RexxRegisterSubcomDll. EnvName is used as 
  5865.            the initial setting for the REXX ADDRESS instruction. 
  5866.  
  5867.            If EnvName is NULL, the file extension is used as the initial 
  5868.            ADDRESS environment. The environment name cannot be longer than 250 
  5869.            characters. 
  5870.  
  5871.  CallType (LONG) - input 
  5872.            The type of REXX procedure execution. Allowed execution types are: 
  5873.  
  5874.            RXCOMMAND           The REXX procedure is a system or application 
  5875.                                command. REXX commands usually have a single 
  5876.                                argument string. The REXX PARSE SOURCE 
  5877.                                instruction returns COMMAND as the second token. 
  5878.  
  5879.            RXSUBROUTINE        The REXX procedure is a subroutine of another 
  5880.                                program. The subroutine can have multiple 
  5881.                                arguments and does not need to return a result. 
  5882.                                The REXX PARSE SOURCE instruction returns 
  5883.                                SUBROUTINE as the second token. 
  5884.  
  5885.            RXFUNCTION          The REXX procedure is a function called from 
  5886.                                another program. The subroutine may have 
  5887.                                multiple arguments and must return a result. The 
  5888.                                REXX PARSE SOURCE instruction returns FUNCTION 
  5889.                                as the second token. 
  5890.  
  5891.  Exits (PRXSYSEXIT) - input 
  5892.            An array of RXSYSEXIT structures defining exits for the REXX 
  5893.            interpreter to use. The RXSYSEXIT structures have the following 
  5894.            form: 
  5895.  
  5896.                       typedef struct {
  5897.                          PSZ             sysexit_name;  /* name of exit handler        */
  5898.                          LONG            sysexit_code;  /* system exit function code   */
  5899.                       } RXSYSEXIT;
  5900.  
  5901.            The sysexit_name is the address of an ASCIIZ exit handler name 
  5902.            registered with RexxRegisterExitExe or RexxRegisterExitDll. 
  5903.            Sysexit_code is a code identifying the handler exit type. System 
  5904.            Exits provides exit code definitions. An RXENDLST entry identifies 
  5905.            the system exit list end. Exits must be NULL if exits are not used. 
  5906.  
  5907.  ReturnCode (PSHORT) - output 
  5908.            The integer form of the Result string. If the Result string is a 
  5909.            whole number in the range -(2**15) to 2**15-1, it is converted to an 
  5910.            integer and also returned in ReturnCode. 
  5911.  
  5912.  Result (PRXSTRING) - output 
  5913.            The string returned from the REXX procedure with the REXX RETURN or 
  5914.            EXIT instruction. A default RXSTRING can be provided for the 
  5915.            returned result. If a default RXSTRING is not provided or the 
  5916.            default is too small for the returned result, the REXX interpreter 
  5917.            allocates an RXSTRING using DosAllocMem. The caller of RexxStart is 
  5918.            responsible for releasing the RXSTRING storage with DosFreeMem. 
  5919.  
  5920.            The REXX interpreter does not add a terminating null to Result. 
  5921.  
  5922.  
  5923. ΓòÉΓòÉΓòÉ 10.3.3.3. RexxStart - Returns ΓòÉΓòÉΓòÉ
  5924.  
  5925. The RexxStart return values are: 
  5926.  
  5927.  negative       Interpreter errors. See Appendix A in the Object REXX Reference 
  5928.                 for the list of REXX errors. 
  5929.  
  5930.  0              No errors occurred. The REXX procedure ran normally. 
  5931.  
  5932.  positive       A system return code indicating problems finding or loading the 
  5933.                 interpreter. See the return codes for the OS/2 functions 
  5934.                 DosLoadModule and DosQueryProcAddr for details. 
  5935.  
  5936.  When a macrospace REXX procedure (see Macrospace Interface) is not loaded in 
  5937.  the macrospace, the return code is -3 ("Program is unreadable"). 
  5938.  
  5939.  
  5940. ΓòÉΓòÉΓòÉ 10.3.3.4. RexxStart - Example ΓòÉΓòÉΓòÉ
  5941.  
  5942. The following is an example of a sample call to the REXX interpreter: 
  5943.  
  5944.  
  5945. Sample call to the REXX interpreter
  5946.  
  5947. LONG      return_code;                 /* interpreter return code    */
  5948. RXSTRING  argv[1];                     /* program argument string    */
  5949. RXSTRING  retstr;                      /* program return value       */
  5950. SHORT     rc;                          /* converted return code      */
  5951. CHAR      return_buffer[250];          /* returned buffer            */
  5952.                                        /* build the argument string  */
  5953.   MAKERXSTRING(argv[0], macro_argument,
  5954.       strlen(macro_argument));
  5955.                                        /* set up default return      */
  5956.   MAKERXSTRING(retstr, return_buffer, sizeof(return_buffer));
  5957.   return_code = RexxStart(1,           /* one argument               */
  5958.                           argv,        /* argument array             */
  5959.                           "CHANGE.ED", /* REXX procedure name        */
  5960.                           NULL,        /* use disk version           */
  5961.                           "Editor",    /* default address name       */
  5962.                           RXCOMMAND,   /* calling as a subcommand    */
  5963.                           NULL,        /* no exits used              */
  5964.                           &rc,         /* converted return code      */
  5965.                           &retstr);    /* returned result            */
  5966.                                        /* process return value       */
  5967. .
  5968. .
  5969. .
  5970.                                        /* need to return storage?    */
  5971.   if (RXSTRPTR(retval) != return_buffer)
  5972.     DosFreeMem(RXSTRPTR(retval));      /* release the RXSTRING       */
  5973.  
  5974.  
  5975. ΓòÉΓòÉΓòÉ 10.4. Subcommand Interface ΓòÉΓòÉΓòÉ
  5976.  
  5977. An application can create handlers to process commands from a REXX program. 
  5978. Once created, the subcommand handler name can be used with the RexxStart 
  5979. function or the REXX ADDRESS instruction. Subcommand handlers must be 
  5980. registered with the RexxRegisterSubcomExe or RexxRegisterSubcomDll function 
  5981. before use. 
  5982.  
  5983.  
  5984. ΓòÉΓòÉΓòÉ 10.4.1. Registering Subcommand Handlers ΓòÉΓòÉΓòÉ
  5985.  
  5986. A subcommand handler can reside in the same module (EXE or DLL) as an 
  5987. application, or it can reside in a separate dynamic link library. An 
  5988. application that runs REXX procedures with RexxStart should use 
  5989. RexxRegisterSubcomExe to register subcommand handlers. The REXX interpreter 
  5990. passes commands to the application subcommand handler entry point. Subcommand 
  5991. handlers created using RexxRegisterSubcomExe are available only to REXX 
  5992. programs called from the registering application. 
  5993.  
  5994. The RexxRegisterSubcomDll interface creates subcommand handlers that reside in 
  5995. a dynamic link library. Any REXX program using the REXX ADDRESS instruction can 
  5996. access a dynamic link library subcommand handler. A dynamic link library 
  5997. subcommand handler can also be registered directly from a REXX program using 
  5998. the RXSUBCOM command. 
  5999.  
  6000.  
  6001. ΓòÉΓòÉΓòÉ 10.4.1.1. Creating Subcommand Handlers ΓòÉΓòÉΓòÉ
  6002.  
  6003. The following example is a sample subcommand handler definition. 
  6004.  
  6005.  
  6006. Sample definition of a subcommand handler
  6007.  
  6008. ULONG command_handler(
  6009.   PRXSTRING Command,    /* Command string from REXX            */
  6010.   PUSHORT   Flags,      /* Returned Error/Failure flags        */
  6011.   PRXSTRING Retstr);    /* Returned RC string                  */
  6012.  
  6013.  Command   The command string created by REXX. 
  6014.  
  6015.            Command is a null-terminated RXSTRING containing the issued command. 
  6016.  
  6017.  Flags     Subcommand completion status. The subcommand handler can indicate 
  6018.            success, error, or failure status. The subcommand handler can set 
  6019.            Flags to one of the following values: 
  6020.  
  6021.            RXSUBCOM_OK 
  6022.                           The subcommand completed normally. No errors occurred 
  6023.                           during subcommand processing and the REXX procedure 
  6024.                           continues when the subcommand handler returns. 
  6025.  
  6026.            RXSUBCOM_ERROR 
  6027.                           A subcommand error occurred. RXSUBCOM_ERROR indicates 
  6028.                           a subcommand error occurred; for example, incorrect 
  6029.                           command options or syntax. 
  6030.  
  6031.                           If the subcommand handler sets Flags to 
  6032.                           RXSUBCOM_ERROR, the REXX interpreter raises an ERROR 
  6033.                           condition if SIGNAL ON ERROR or CALL ON ERROR traps 
  6034.                           have been created. If TRACE ERRORS has been issued, 
  6035.                           REXX traces the command when the subcommand handler 
  6036.                           returns. 
  6037.  
  6038.            RXSUBCOM_FAILURE 
  6039.                           A subcommand failure occurred. RXSUBCOM_FAILURE 
  6040.                           indicates that general subcommand processing errors 
  6041.                           have occurred. For example, unknown commands usually 
  6042.                           return RXSUBCOM_FAILURE. 
  6043.  
  6044.                           If the subcommand handler sets Flags to 
  6045.                           RXSUBCOM_FAILURE, the REXX interpreter raises a 
  6046.                           FAILURE condition if SIGNAL ON FAILURE or CALL ON 
  6047.                           FAILURE traps have been created. If TRACE FAILURES 
  6048.                           has been issued, REXX traces the command when the 
  6049.                           subcommand handler returns. 
  6050.  
  6051.  Retstr    Address of an RXSTRING for the return code. Retstr is a character 
  6052.            string return code that is assigned to the REXX special variable RC 
  6053.            when the subcommand handler returns to REXX. The REXX interpreter 
  6054.            provides a default 256-byte RXSTRING in Retstr. A longer RXSTRING 
  6055.            may be allocated with DosAllocMem if the return string is longer 
  6056.            than the default RXSTRING. If the subcommand handler sets Retstr to 
  6057.            an empty RXSTRING (a NULL strptr), REXX assigns the string "0" to 
  6058.            RC. 
  6059.  
  6060.  
  6061. ΓòÉΓòÉΓòÉ 10.4.1.1.1. Example ΓòÉΓòÉΓòÉ
  6062.  
  6063. The following is a sample subcommand handler: 
  6064.  
  6065.  
  6066. Sample subcommand handler
  6067.  
  6068. ULONG Edit_Commands(
  6069.   PRXSTRING Command,    /* Command string passed from the caller    */
  6070.   PUSHORT   Flags,      /* pointer to short for return of flags     */
  6071.   PRXSTRING Retstr)     /* pointer to RXSTRING for RC return        */
  6072. {
  6073.   LONG      command_id;                /* command to process         */
  6074.   LONG      rc;                        /* return code                */
  6075.   PSZ       scan_pointer;              /* current command scan       */
  6076.   PSZ       target;                    /* general editor target      */
  6077.   scan_pointer = command->strptr;      /* point to the command       */
  6078.                                        /* resolve command            */
  6079.   command_id = resolve_command(&scan_pointer);
  6080.   switch (command_id) {                /* process based on command   */
  6081.     case   LOCATE:                     /* locate command             */
  6082.                                        /* validate rest of command   */
  6083.       if (rc = get_target(&scan_pointer, &target)) {
  6084.         *Flags = RXSUBCOM_ERROR;       /* raise an error condition   */
  6085.         break;                         /* return to REXX             */
  6086.       }
  6087.       rc = locate(target);             /* look target in the file    */
  6088.       *Flags = RXSUBCOM_OK;            /* not found is not an error  */
  6089.       break;                           /* go finish up               */
  6090. .
  6091. .
  6092. .
  6093.  
  6094.     default:                           /* unknown command            */
  6095.       rc = 1;                          /* return code for unknown    */
  6096.       *Flags = RXSUBCOM_FAILURE;       /* this is a command failure  */
  6097.       break;
  6098.   }
  6099.   sprintf(Retstr->strptr, "%d", rc);   /* format return code string  */
  6100.                                        /* and set the correct length */
  6101.   Retstr->strlength = strlen(Retstr->strptr);
  6102.   return 0;                            /* processing completed       */
  6103. }
  6104.  
  6105.  
  6106. ΓòÉΓòÉΓòÉ 10.4.2. Subcommand Interface Functions ΓòÉΓòÉΓòÉ
  6107.  
  6108. The functions for registering and using subcommand handlers are: 
  6109.  
  6110.       RexxRegisterSubcomDll 
  6111.       RexxRegisterSubcomExe 
  6112.       RexxDeregisterSubcom 
  6113.       RexxQuerySubcom 
  6114.  
  6115.  
  6116. ΓòÉΓòÉΓòÉ 10.4.2.1. RexxRegisterSubcomDll ΓòÉΓòÉΓòÉ
  6117.  
  6118. RexxRegisterSubcomDll registers a subcommand handler that resides in a dynamic 
  6119. link library routine. 
  6120.  
  6121. Topics: 
  6122.  
  6123.      Syntax 
  6124.  
  6125.      Parameters 
  6126.  
  6127.      Returns 
  6128.  
  6129.      Remarks 
  6130.  
  6131.  
  6132. ΓòÉΓòÉΓòÉ 10.4.2.1.1. RexxRegisterSubcomDll - Syntax ΓòÉΓòÉΓòÉ
  6133.  
  6134. RexxRegisterSubcomDll(EnvName, ModuleName, EntryPoint, UserArea,
  6135. DropAuth)
  6136.  
  6137.  
  6138. ΓòÉΓòÉΓòÉ 10.4.2.1.2. RexxRegisterSubcomDll - Parameters ΓòÉΓòÉΓòÉ
  6139.  
  6140.  EnvName (PSZ) - input 
  6141.            Address of an ASCIIZ subcommand handler name. 
  6142.  
  6143.  ModuleName (PSZ) - input 
  6144.            Address of an ASCIIZ dynamic link library name. ModuleName is the 
  6145.            DLL file containing the subcommand handler routine. 
  6146.  
  6147.  EntryPoint (PSZ) - input 
  6148.            Address of an ASCIIZ dynamic link library procedure name. EntryPoint 
  6149.            is the name of the exported routine within ModuleName that REXX 
  6150.            calls as a subcommand handler. 
  6151.  
  6152.  UserArea (PUCHAR) - input 
  6153.            Address of an 8-byte area of user-defined information. The 8 bytes 
  6154.            UserArea addresses are saved with the subcommand handler 
  6155.            registration. UserArea can be NULL if there is no user information 
  6156.            to save. The RexxQuerySubcom function can retrieve the saved user 
  6157.            information. 
  6158.  
  6159.  DropAuth (ULONG) - input 
  6160.            The drop authority. DropAuth identifies the processes that can 
  6161.            deregister the subcommand handler. The possible DropAuth values are: 
  6162.  
  6163.            RXSUBCOM_DROPPABLE 
  6164.                           Any process can deregister the subcommand handler 
  6165.                           with RexxDeregisterSubcom. 
  6166.  
  6167.            RXSUBCOM_NONDROP 
  6168.                           Only a thread within the same process as the thread 
  6169.                           that registered the handler can deregister the 
  6170.                           handler with RexxDeregisterSubcom. 
  6171.  
  6172.  
  6173. ΓòÉΓòÉΓòÉ 10.4.2.1.3. RexxRegisterSubcomDll - Returns ΓòÉΓòÉΓòÉ
  6174.  
  6175. The RexxRegisterSubcomDll return values are: 
  6176.  
  6177. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6178.  0      RXSUBCOM_OK                A subcommand has executed
  6179.                                    successfully.
  6180.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6181.  10     RXSUBCOM_DUP               A duplicate handler name has been
  6182.                                    successfully registered.  There is
  6183.                                    either an EXE handler with the same
  6184.                                    name registered in another process,
  6185.                                    or a DLL handler with the same name
  6186.                                    registered in another DLL.  (To
  6187.                                    address this subcommand you must
  6188.                                    specify its library name.)
  6189.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6190.  1002   RXSUBCOM_NOEMEM            There is insufficient memory to
  6191.                                    complete this request.
  6192. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6193.  
  6194.  
  6195. ΓòÉΓòÉΓòÉ 10.4.2.1.4. RexxRegisterSubcomDll - Remarks ΓòÉΓòÉΓòÉ
  6196.  
  6197. EntryPoint can be either a 16-bit or a 32-bit routine. REXX calls the handler 
  6198. in the correct addressing mode. 
  6199.  
  6200.  
  6201. ΓòÉΓòÉΓòÉ 10.4.2.2. RexxRegisterSubcomExe ΓòÉΓòÉΓòÉ
  6202.  
  6203. RexxRegisterSubcomExe registers a subcommand handler that resides within 
  6204. application code. 
  6205.  
  6206. Topics: 
  6207.  
  6208.      Syntax 
  6209.  
  6210.      Parameters 
  6211.  
  6212.      Returns 
  6213.  
  6214.      Remarks 
  6215.  
  6216.      Example 
  6217.  
  6218.  
  6219. ΓòÉΓòÉΓòÉ 10.4.2.2.1. RexxRegisterSubcomExe - Syntax ΓòÉΓòÉΓòÉ
  6220.  
  6221. RexxRegisterSubcomExe(EnvName, EntryPoint, UserArea)
  6222.  
  6223.  
  6224. ΓòÉΓòÉΓòÉ 10.4.2.2.2. RexxRegisterSubcomExe - Parameters ΓòÉΓòÉΓòÉ
  6225.  
  6226.  EnvName (PSZ) - input 
  6227.            Address of an ASCIIZ subcommand handler name. 
  6228.  
  6229.  EntryPoint (PFN) - input 
  6230.            Address of the subcommand handler entry point within the application 
  6231.            EXE code. 
  6232.  
  6233.  UserArea (PUCHAR) - input 
  6234.            Address of an 8-byte area of user-defined information. The 8 bytes 
  6235.            UserArea addresses are saved with the subcommand handler 
  6236.            registration. UserArea can be NULL if there is no user information 
  6237.            to save. The RexxQuerySubcom function can retrieve the user 
  6238.            information. 
  6239.  
  6240.  
  6241. ΓòÉΓòÉΓòÉ 10.4.2.2.3. RexxRegisterSubcomExe - Returns ΓòÉΓòÉΓòÉ
  6242.  
  6243. The RexxRegisterSubcomExe return values are: 
  6244.  
  6245. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6246.  0      RXSUBCOM_OK                A subcommand has executed
  6247.                                    successfully.
  6248.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6249.  10     RXSUBCOM_DUP               A duplicate handler name has been
  6250.                                    successfully registered.  There is
  6251.                                    either an EXE handler with the same
  6252.                                    name registered in another process,
  6253.                                    or a DLL handler with the same name
  6254.                                    registered in another DLL.  (To
  6255.                                    address this subcommand you must
  6256.                                    specify its library name.)
  6257.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6258.  30     RXSUBCOM_NOTREG            Registration was unsuccessful due to
  6259.                                    duplicate handler and dynalink names
  6260.                                    (RexxRegisterSubcomExe or
  6261.                                    RexxRegisterSubcomDll); the
  6262.                                    subroutine environment is not
  6263.                                    registered (other REXX subcommand
  6264.                                    functions).
  6265.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6266.  1002   RXSUBCOM_NOEMEM            There is insufficient memory to
  6267.                                    complete this request.
  6268. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6269.  
  6270.  
  6271. ΓòÉΓòÉΓòÉ 10.4.2.2.4. RexxRegisterSubcomExe - Remarks ΓòÉΓòÉΓòÉ
  6272.  
  6273. If EnvName is the same as a subcommand handler already registered with 
  6274. RexxRegisterSubcomDll, RexxRegisterSubcomExe returns RXSUBCOM_DUP. This is not 
  6275. an error condition. RexxRegisterSubcomExe has successfully registered the new 
  6276. subcommand handler. 
  6277.  
  6278. A REXX procedure can register dynamic link library subcommand handlers with the 
  6279. RXSUBCOM command. For example: 
  6280.  
  6281.                                  /* register Dialog Manager       */
  6282.                                  /* subcommand handler            */
  6283.   'RXSUBCOM REGISTER ISPCIR ISPCIR ISPCIR'
  6284.   Address ispcir                 /* send commands to dialog mgr   */
  6285.  
  6286. The RXSUBCOM command registers the Dialog Manager subcommand handler ISPCIR as 
  6287. routine ISPCIR in the ISPCIR dynamic link library. 
  6288.  
  6289.  
  6290. ΓòÉΓòÉΓòÉ 10.4.2.2.5. RexxRegisterSubcomExe - Example ΓòÉΓòÉΓòÉ
  6291.  
  6292. The following is a sample subcommand handler registration: 
  6293.  
  6294.  
  6295. Sample subcommand handler registration
  6296.  
  6297.   WORKAREARECORD  *user_info[2];       /* saved user information     */
  6298.   user_info[0] = global_workarea;      /* save global work area for  */
  6299.   user_info[1] = NULL;                 /* re-entrancy                */
  6300.   rc = RexxRegisterSubcomExe("Editor", /* register editor handler    */
  6301.       &Edit_Commands,                  /* located at this address    */
  6302.       user_info);                      /* save global pointer        */
  6303.  
  6304.  
  6305. ΓòÉΓòÉΓòÉ 10.4.2.3. RexxDeregisterSubcom ΓòÉΓòÉΓòÉ
  6306.  
  6307. RexxDeregisterSubcom deregisters a subcommand handler. 
  6308.  
  6309. Topics: 
  6310.  
  6311.      Syntax 
  6312.  
  6313.      Parameters 
  6314.  
  6315.      Returns 
  6316.  
  6317.      Remarks 
  6318.  
  6319.  
  6320. ΓòÉΓòÉΓòÉ 10.4.2.3.1. RexxDeregisterSubcom - Syntax ΓòÉΓòÉΓòÉ
  6321.  
  6322. RexxDeregisterSubcom(EnvName, ModuleName)
  6323.  
  6324.  
  6325. ΓòÉΓòÉΓòÉ 10.4.2.3.2. RexxDeregisterSubcom - Parameters ΓòÉΓòÉΓòÉ
  6326.  
  6327.  EnvName (PSZ) - input 
  6328.            Address of an ASCIIZ subcommand handler name. 
  6329.  
  6330.  ModuleName (PSZ) - input 
  6331.            Address of an ASCIIZ dynalink library name. ModuleName is the name 
  6332.            of the dynalink library containing the registered subcommand 
  6333.            handler. When ModuleName is NULL, RexxDeregisterSubcom searches the 
  6334.            RexxRegisterSubcomExe subcommand handler list for a handler within 
  6335.            the current process. If RexxDeregisterSubcom does not find a 
  6336.            RexxRegisterSubcomExe handler, it searches the RexxRegisterSubcomDll 
  6337.            subcommand handler list. 
  6338.  
  6339.  
  6340. ΓòÉΓòÉΓòÉ 10.4.2.3.3. RexxDeregisterSubcom - Returns ΓòÉΓòÉΓòÉ
  6341.  
  6342. The RexxDeregisterSubcom return values are: 
  6343.  
  6344. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6345.  0      RXSUBCOM_OK                A subcommand has executed
  6346.                                    successfully.
  6347.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6348.  30     RXSUBCOM_NOTREG            Registration was unsuccessful due to
  6349.                                    duplicate handler and dynalink names
  6350.                                    (RexxRegisterSubcomExe or
  6351.                                    RexxRegisterSubcomDll); the
  6352.                                    subroutine environment is not
  6353.                                    registered (other REXX subcommand
  6354.                                    functions).
  6355.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6356.  40     RXSUBCOM_NOCANDROP         The subcommand handler has been
  6357.                                    registered as "not droppable."
  6358. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6359.  
  6360.  
  6361. ΓòÉΓòÉΓòÉ 10.4.2.3.4. RexxDeregisterSubcom - Remarks ΓòÉΓòÉΓòÉ
  6362.  
  6363. The handler is removed from the active subcommand handler list. 
  6364.  
  6365.  
  6366. ΓòÉΓòÉΓòÉ 10.4.2.4. RexxQuerySubcom ΓòÉΓòÉΓòÉ
  6367.  
  6368. RexxQuerySubcom queries a subcommand handler and retrieves saved user 
  6369. information. 
  6370.  
  6371. Topics: 
  6372.  
  6373.      Syntax 
  6374.  
  6375.      Parameters 
  6376.  
  6377.      Returns 
  6378.  
  6379.      Example 
  6380.  
  6381.  
  6382. ΓòÉΓòÉΓòÉ 10.4.2.4.1. RexxQuerySubcom - Syntax ΓòÉΓòÉΓòÉ
  6383.  
  6384. RexxQuerySubcom(EnvName, ModuleName, Flag, UserWord)
  6385.  
  6386.  
  6387. ΓòÉΓòÉΓòÉ 10.4.2.4.2. RexxQuerySubcom - Parameters ΓòÉΓòÉΓòÉ
  6388.  
  6389.  EnvName (PSZ) - input 
  6390.            Address of an ASCIIZ subcommand handler name. 
  6391.  
  6392.  ModuleName (PSZ) - input 
  6393.            Address of an ASCIIZ dynamic link library name. ModuleName restricts 
  6394.            the query to a subcommand handler within the ModuleName dynamic link 
  6395.            library. When ModuleName is NULL, RexxQuerySubcom searches the 
  6396.            RexxRegisterSubcomExe subcommand handler list for a handler within 
  6397.            the current process. If RexxQuerySubcom does not find a 
  6398.            RexxRegisterSubcomExe handler, it searches the RexxRegisterSubcomDll 
  6399.            subcommand handler list. 
  6400.  
  6401.  Flag (PUSHORT) - output 
  6402.            Subcommand handler registration flag. Flag is the EnvName subcommand 
  6403.            handler registration status. When RexxQuerySubcom returns 
  6404.            RXSUBCOM_OK, the EnvName subcommand handler is currently registered. 
  6405.            When RexxQuerySubcom returns RXSUBCOM_NOTREG, the EnvName subcommand 
  6406.            handler is not registered. 
  6407.  
  6408.  UserWord (PUCHAR) - output 
  6409.            Address of an 8-byte area to receive the user information saved with 
  6410.            RexxRegisterSubcomExe or RexxRegisterSubcomDll. UserWord can be NULL 
  6411.            if the saved user information is not required. 
  6412.  
  6413.  
  6414. ΓòÉΓòÉΓòÉ 10.4.2.4.3. RexxQuerySubcom - Returns ΓòÉΓòÉΓòÉ
  6415.  
  6416. The RexxQuerySubcom return values are: 
  6417.  
  6418. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6419.  0      RXSUBCOM_OK                A subcommand has executed
  6420.                                    successfully.
  6421.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6422.  30     RXSUBCOM_NOTREG            Registration was unsuccessful due to
  6423.                                    duplicate handler and dynalink names
  6424.                                    (RexxRegisterSubcomExe or
  6425.                                    RexxRegisterSubcomDll); the
  6426.                                    subroutine environment is not
  6427.                                    registered (other REXX subcommand
  6428.                                    functions).
  6429. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6430.  
  6431.  
  6432. ΓòÉΓòÉΓòÉ 10.4.2.4.4. RexxQuerySubcom - Example ΓòÉΓòÉΓòÉ
  6433.  
  6434. The following is a sample subcommand handler query: 
  6435.  
  6436.  
  6437. Sample subcommand handler query
  6438.  
  6439. ULONG Edit_Commands(
  6440.   PRXSTRING Command,    /* Command string passed from the caller    */
  6441.   PUSHORT   Flags,      /* pointer to short for return of flags     */
  6442.   PRXSTRING Retstr)     /* pointer to RXSTRING for RC return        */
  6443. {
  6444.   WORKAREARECORD  *user_info[2];       /* saved user information     */
  6445.   WORKAREARECORD   global_workarea;    /* application data anchor    */
  6446.   USHORT           query_flag;         /* flag for handler query     */
  6447.   rc = RexxQuerySubcom("Editor",       /* retrieve application work  */
  6448.       NULL,                            /* area anchor from REXX.     */
  6449.       &query_flag,
  6450.       user_info);
  6451.   global_workarea = user_info[0];      /* set the global anchor      */
  6452.  
  6453.  
  6454. ΓòÉΓòÉΓòÉ 10.4.3. Subcommand Interface Returns ΓòÉΓòÉΓòÉ
  6455.  
  6456. Return codes for the Subcommand Interface are as follows: 
  6457.  
  6458. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6459.  0x01   RXSUBCOM_ERROR             An error in subcommand processing
  6460.                                    has occurred; the interpreter raises
  6461.                                    an ERROR condition.
  6462.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6463.  0x02   RXSUBCOM_FAILURE           A failure in subcommand processing
  6464.                                    has occurred; the interpreter raises
  6465.                                    a FAILURE condition.
  6466.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6467.  0      RXSUBCOM_OK                A subcommand has executed
  6468.                                    successfully.
  6469.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6470.  10     REXSUBCOM_DUP              A duplicate handler name has been
  6471.                                    successfully registered.  There is
  6472.                                    either an EXE handler with the same
  6473.                                    name registered in another process,
  6474.                                    or a DLL handler with the same name
  6475.                                    registered in another DLL.  (To
  6476.                                    address this subcommand you must
  6477.                                    specify its library name.)
  6478.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6479.  30     RXSUBCOM_NOTREG            Registration was unsuccessful due to
  6480.                                    duplicate handler and dynalink names
  6481.                                    (RexxRegisterSubcomExe or
  6482.                                    RexxRegisterSubcomDll); the
  6483.                                    subroutine environment is not
  6484.                                    registered (other REXX subcommand
  6485.                                    functions).
  6486.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6487.  40     RXSUBCOM_NOCANDROP         The subcommand handler has been
  6488.                                    registered as "not droppable."
  6489.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6490.  50     RXSUBCOM_LOADERR           An error has occurred while loading
  6491.                                    a dynalink library; most commonly, a
  6492.                                    missing dynalink library file causes
  6493.                                    the error.
  6494.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6495.  1002   RXSUBCOM_NOEMEM            There is insufficient memory to
  6496.                                    complete this request.
  6497. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6498.  
  6499.  
  6500. ΓòÉΓòÉΓòÉ 10.5. External Function Interface ΓòÉΓòÉΓòÉ
  6501.  
  6502. There are two types of REXX external functions: 
  6503.  
  6504.    1. Routines written in REXX 
  6505.    2. Routines written in other OS/2-supported languages. 
  6506.  
  6507.  External functions written in REXX do not need to be registered. These 
  6508.  functions are found by a disk search for a REXX procedure file that matches 
  6509.  the function name. 
  6510.  
  6511.  
  6512. ΓòÉΓòÉΓòÉ 10.5.1. Registering External Functions ΓòÉΓòÉΓòÉ
  6513.  
  6514. An external function can reside in the same module (EXE or DLL) as an 
  6515. application, or in a separate dynamic link library. RexxRegisterFunctionExe 
  6516. registers external functions within an application module. External functions 
  6517. registered with RexxRegisterFunctionExe are available only to REXX programs 
  6518. called from the registering application. 
  6519.  
  6520. The RexxRegisterFunctionDll interface registers external functions that reside 
  6521. in a dynamic link library. Any REXX program can access a dynamic link library 
  6522. external function after it is registered. A dynamic link library external 
  6523. function can also be registered directly from a REXX program using the REXX 
  6524. RXFUNCADD built-in function. 
  6525.  
  6526.  
  6527. ΓòÉΓòÉΓòÉ 10.5.1.1. Creating External Functions ΓòÉΓòÉΓòÉ
  6528.  
  6529. The following is a sample external function definition: 
  6530.  
  6531.  
  6532. Sample external function definition
  6533.  
  6534. ULONG SysLoadFuncs(
  6535.      PSZ       Name,                   /* name of the function       */
  6536.      LONG      Argc,                   /* number of arguments        */
  6537.      RXSTRING  Argv[],                 /* list of argument strings   */
  6538.      PSZ       Queuename,              /* current queue name         */
  6539.      PRXSTRING Retstr)                 /* returned result string     */
  6540.  
  6541.  Name        Address of ASCIIZ function name used to call the external 
  6542.              function. 
  6543.  
  6544.  Argc        The number of elements in the Argv array. Argv will contain Argc 
  6545.              RXSTRINGs. 
  6546.  
  6547.  Argv        An array of null-terminated RXSTRINGs for the function arguments. 
  6548.  
  6549.  Queuename   The name of the currently defined REXX external data queue. 
  6550.  
  6551.  Retstr      Address of an RXSTRING for the returned value. Retstr is a 
  6552.              character string function or subroutine return value. When a REXX 
  6553.              program calls an external function with the REXX CALL instruction, 
  6554.              Retstr is assigned to the REXX special variable RESULT. When the 
  6555.              REXX program calls an external function with a function call, 
  6556.              Retstr is used directly within the REXX expression. 
  6557.  
  6558.              The REXX interpreter provides a default 256-byte RXSTRING in 
  6559.              Retstr. A longer RXSTRING can be allocated with DosAllocMem if the 
  6560.              returned string is longer than 256 bytes. The REXX interpreter 
  6561.              releases Retstr with DosFreeMem when the external function 
  6562.              completes. 
  6563.  
  6564.  Returns     An integer return code from the function. When the external 
  6565.              function returns 0, the function completed successfully. Retstr 
  6566.              contains the function return value. When the external function 
  6567.              returns a non-zero return code, the REXX interpreter raises REXX 
  6568.              error 40 ("Incorrect call to routine"). The Retstr value is 
  6569.              ignored. 
  6570.  
  6571.              If the external function does not have a return value, the 
  6572.              function should set Retstr to an empty RXSTRING (NULL strptr). 
  6573.              When an external function called as a function does not return a 
  6574.              value, the interpreter raises error 44, "Function or message did 
  6575.              not return data". When an external function called with the REXX 
  6576.              CALL instruction does not return a value, the REXX interpreter 
  6577.              drops (unassigns) the special variable RESULT. 
  6578.  
  6579.  
  6580. ΓòÉΓòÉΓòÉ 10.5.2. Calling External Functions ΓòÉΓòÉΓòÉ
  6581.  
  6582. RexxRegisterFunctionExe external functions are local to the registering 
  6583. process. Only REXX procedures running in the same process can call the 
  6584. registered external function. It is possible to register functions with the 
  6585. same external function name if they are registered from different processes. 
  6586. However, RexxRegisterFunctionDll functions are available from all processes. 
  6587. The function names cannot be duplicated. 
  6588.  
  6589.  
  6590. ΓòÉΓòÉΓòÉ 10.5.2.1. Example ΓòÉΓòÉΓòÉ
  6591.  
  6592. The following is a sample external function routine: 
  6593.  
  6594.  
  6595. Sample external function routine
  6596.  
  6597. ULONG SysMkDir(
  6598.      PSZ       Name,                   /* name of the function       */
  6599.      LONG      Argc,                   /* number of arguments        */
  6600.      RXSTRING  Argv[],                 /* list of argument strings   */
  6601.      PSZ       Queuename,              /* current queue name         */
  6602.      PRXSTRING Retstr)                 /* returned result string     */
  6603. {
  6604.   ULONG  rc;                           /* Return code of function    */
  6605.   if (Argc != 1)                       /* must be 1 argument         */
  6606.     return 40;                         /* incorrect call if not      */
  6607.                                        /* make the directory using   */
  6608.                                        /* the null-terminated        */
  6609.   rc = DosMkDir(Argv[0].strptr, 0L);   /* directly                   */
  6610.   sprintf(Retstr->strptr, "%d", rc);   /* result is return code      */
  6611.                                        /* set proper string length   */
  6612.   Retstr->strlength = strlen(Retstr->strptr);
  6613.   return 0;                            /* successful completion      */
  6614. }
  6615.  
  6616.  
  6617. ΓòÉΓòÉΓòÉ 10.5.3. External Functions Interface Functions ΓòÉΓòÉΓòÉ
  6618.  
  6619. The functions for registering and using external functions are: 
  6620.  
  6621.       RexxRegisterFunctionDll 
  6622.       RexxRegisterFunctionExe 
  6623.       RexxDeregisterFunction 
  6624.       RexxQueryFunction 
  6625.  
  6626.  
  6627. ΓòÉΓòÉΓòÉ 10.5.3.1. RexxRegisterFunctionDll ΓòÉΓòÉΓòÉ
  6628.  
  6629. RexxRegisterFunctionDll registers an external function that resides in a 
  6630. dynamic link library routine. 
  6631.  
  6632. Topics: 
  6633.  
  6634.      Syntax 
  6635.  
  6636.      Parameters 
  6637.  
  6638.      Returns 
  6639.  
  6640.      Remarks 
  6641.  
  6642.      Example 
  6643.  
  6644.  
  6645. ΓòÉΓòÉΓòÉ 10.5.3.1.1. RexxRegisterFunctionDll - Syntax ΓòÉΓòÉΓòÉ
  6646.  
  6647. RexxRegisterFunctionDll(FuncName, ModuleName, EntryPoint)
  6648.  
  6649.  
  6650. ΓòÉΓòÉΓòÉ 10.5.3.1.2. RexxRegisterFunctionDll - Parameters ΓòÉΓòÉΓòÉ
  6651.  
  6652.  FuncName (PSZ) - input 
  6653.            Address of an ASCIIZ external function name. 
  6654.  
  6655.  ModuleName (PSZ) - input 
  6656.            Address of an ASCIIZ dynamic link library name. ModuleName is the 
  6657.            DLL file containing the external function routine. 
  6658.  
  6659.  EntryPoint (PSZ) - input 
  6660.            Address of an ASCIIZ dynamic link procedure name. EntryPoint is the 
  6661.            name of the exported external function routine within ModuleName. 
  6662.  
  6663.  
  6664. ΓòÉΓòÉΓòÉ 10.5.3.1.3. RexxRegisterFunctionDll - Returns ΓòÉΓòÉΓòÉ
  6665.  
  6666. The RexxRegisterFunctionDll return values are: 
  6667.  
  6668. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6669.  0      RXFUNC_OK                  The call to the function completed
  6670.                                    successfully.
  6671.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6672.  10     RXFUNC_DEFINED             The requested function is already
  6673.                                    registered.
  6674.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6675.  20     RXFUNC_NOMEM               There is not enough memory to
  6676.                                    register a new function.
  6677. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6678.  
  6679.  
  6680. ΓòÉΓòÉΓòÉ 10.5.3.1.4. RexxRegisterFunctionDll - Remarks ΓòÉΓòÉΓòÉ
  6681.  
  6682. EntryPoint can be either a 16-bit or 32-bit routine. REXX calls the function in 
  6683. the correct addressing mode. 
  6684.  
  6685. A REXX procedure can register dynamic link library subcommand handlers with the 
  6686. RXFUNCADD built-in function. For example: 
  6687.  
  6688.                                  /* register function SysLoadFuncs*/
  6689.                                  /* in dynalink library REXXUTIL  */
  6690.   Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs'
  6691.   Call SysLoadFuncs              /* call to load other functions  */
  6692.  
  6693. RXFUNCADD registers the external function SysLoadFuncs as routine SysLoadFuncs 
  6694. in the REXXUTIL dynamic link library. SysLoadFuncs registers additional 
  6695. functions in REXXUTIL.DLL with RexxRegisterFunctionDll. See the SysLoadFuncs 
  6696. routine below for a function registration example. 
  6697.  
  6698.  
  6699. ΓòÉΓòÉΓòÉ 10.5.3.1.5. RexxRegisterFunctionDll - Example ΓòÉΓòÉΓòÉ
  6700.  
  6701. The following is a sample function package load routine: 
  6702.  
  6703.  
  6704. Function package load routine
  6705.  
  6706. static PSZ  RxFncTable[] =             /* function package list      */
  6707. {
  6708.       "SysCls",
  6709.       "SysCurpos",
  6710.       "SysCurState",
  6711.       "SysDriveInfo",
  6712. }
  6713. ULONG SysLoadFuncs(
  6714.      PSZ       Name,                   /* name of the function       */
  6715.      LONG      Argc,                   /* number of arguments        */
  6716.      RXSTRING  Argv[],                 /* list of argument strings   */
  6717.      PSZ       Queuename,              /* current queue name         */
  6718.      PRXSTRING Retstr)                 /* returned result string     */
  6719. {
  6720.   INT    entries;                      /* Num of entries             */
  6721.   INT    j;                            /* Counter                    */
  6722.   Retstr->strlength = 0;               /* set null string return     */
  6723.   if (Argc > 0)                        /* check arguments            */
  6724.     return 40;                         /* too many, raise an error   */
  6725.                                        /* get count of arguments     */
  6726.   entries = sizeof(RxFncTable)/sizeof(PSZ);
  6727.                                        /* register each function in  */
  6728.   for (j = 0; j < entries; j++) {      /* the table                  */
  6729.     RexxRegisterFunctionDll(RxFncTable[j],
  6730.           "REXXUTIL", RxFncTable[j]);
  6731.   }
  6732.   return 0;                            /* successful completion      */
  6733. }
  6734.  
  6735.  
  6736. ΓòÉΓòÉΓòÉ 10.5.3.2. RexxRegisterFunctionExe ΓòÉΓòÉΓòÉ
  6737.  
  6738. RexxRegisterFunctionExe registers an external function that resides within the 
  6739. application code. 
  6740.  
  6741. Topics: 
  6742.  
  6743.      Syntax 
  6744.  
  6745.      Parameters 
  6746.  
  6747.      Returns 
  6748.  
  6749.  
  6750. ΓòÉΓòÉΓòÉ 10.5.3.2.1. RexxRegisterFunctionExe - Syntax ΓòÉΓòÉΓòÉ
  6751.  
  6752. RexxRegisterFunctionExe(FuncName, EntryPoint)
  6753.  
  6754.  
  6755. ΓòÉΓòÉΓòÉ 10.5.3.2.2. RexxRegisterFunctionExe - Parameters ΓòÉΓòÉΓòÉ
  6756.  
  6757.  FuncName (PSZ) - input 
  6758.            Address of an ASCIIZ external function name. 
  6759.  
  6760.  EntryPoint (PFN) - input 
  6761.            Address of the external function entry point within the application 
  6762.            EXE file. Functions registered with RexxRegisterFunctionExe are 
  6763.            local to the current process. REXX procedures in the same process as 
  6764.            the RexxRegisterFunctionExe issuer can call local external 
  6765.            functions. 
  6766.  
  6767.  
  6768. ΓòÉΓòÉΓòÉ 10.5.3.2.3. RexxRegisterFunctionExe - Returns ΓòÉΓòÉΓòÉ
  6769.  
  6770. The RexxRegisterFunctionExe return values are: 
  6771.  
  6772. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6773.  0      RXFUNC_OK                  The call to the function completed
  6774.                                    successfully.
  6775.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6776.  10     RXFUNC_DEFINED             The requested function is already
  6777.                                    registered.
  6778.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6779.  20     RXFUNC_NOMEM               There is not enough memory to
  6780.                                    register a new function.
  6781. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6782.  
  6783.  
  6784. ΓòÉΓòÉΓòÉ 10.5.3.3. RexxDeregisterFunction ΓòÉΓòÉΓòÉ
  6785.  
  6786. RexxDeregisterFunction deregisters an external function. 
  6787.  
  6788. Topics: 
  6789.  
  6790.      Syntax 
  6791.  
  6792.      Parameters 
  6793.  
  6794.      Returns 
  6795.  
  6796.  
  6797. ΓòÉΓòÉΓòÉ 10.5.3.3.1. RexxDeregisterFunction - Syntax ΓòÉΓòÉΓòÉ
  6798.  
  6799. RexxDeregisterFunction(FuncName)
  6800.  
  6801.  
  6802. ΓòÉΓòÉΓòÉ 10.5.3.3.2. RexxDeregisterFunction - Parameters ΓòÉΓòÉΓòÉ
  6803.  
  6804.  FuncName (PSZ) - input 
  6805.            Address of an ASCIIZ external function name to deregister. 
  6806.  
  6807.  
  6808. ΓòÉΓòÉΓòÉ 10.5.3.3.3. RexxDeregisterFunction - Returns ΓòÉΓòÉΓòÉ
  6809.  
  6810. The RexxDeregisterFunction return values are: 
  6811.  
  6812. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6813.  0      RXFUNC_OK                  The call to the function completed
  6814.                                    successfully.
  6815.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6816.  30     RXFUNC_NOTREG              The requested function is not
  6817.                                    registered.
  6818. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6819.  
  6820.  
  6821. ΓòÉΓòÉΓòÉ 10.5.3.4. RexxQueryFunction ΓòÉΓòÉΓòÉ
  6822.  
  6823. RexxQueryFunction queries the existence of a registered external function. 
  6824.  
  6825. Topics: 
  6826.  
  6827.      Syntax 
  6828.  
  6829.      Parameters 
  6830.  
  6831.      Returns 
  6832.  
  6833.      Remarks 
  6834.  
  6835.  
  6836. ΓòÉΓòÉΓòÉ 10.5.3.4.1. RexxQueryFunction - Syntax ΓòÉΓòÉΓòÉ
  6837.  
  6838. RexxQueryFunction(FuncName)
  6839.  
  6840.  
  6841. ΓòÉΓòÉΓòÉ 10.5.3.4.2. RexxQueryFunction - Parameters ΓòÉΓòÉΓòÉ
  6842.  
  6843.  FuncName (PSZ) - input 
  6844.            Address of an ASCIIZ external function name to query. 
  6845.  
  6846.  
  6847. ΓòÉΓòÉΓòÉ 10.5.3.4.3. RexxQueryFunction - Returns ΓòÉΓòÉΓòÉ
  6848.  
  6849. The RexxQueryFunction return values are: 
  6850.  
  6851. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6852.  0      RXFUNC_OK                  The call to the function completed
  6853.                                    successfully.
  6854.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6855.  30     RXFUNC_NOTREG              The requested function is not
  6856.                                    registered.
  6857. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6858.  
  6859.  
  6860. ΓòÉΓòÉΓòÉ 10.5.3.4.4. RexxQueryFunction - Remarks ΓòÉΓòÉΓòÉ
  6861.  
  6862. RexxQueryFunction returns RXFUNC_OK only if the requested function is available 
  6863. to the current process. If a function is not available to the current process, 
  6864. RexxQueryFunction searches the RexxRegisterFunctionDll external function list. 
  6865.  
  6866.  
  6867. ΓòÉΓòÉΓòÉ 10.5.4. External Functions Interface Returns ΓòÉΓòÉΓòÉ
  6868.  
  6869. Return codes for the External Functions Interface are as follows: 
  6870.  
  6871. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6872.  0      RXFUNC_OK                  The call to the function completed
  6873.                                    successfully.
  6874.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6875.  10     RXFUNC_DEFINED             The requested function is already
  6876.                                    registered.
  6877.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6878.  20     RXFUNC_NOMEM               There is not enough memory to
  6879.                                    register a new function.
  6880.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6881.  30     RXFUNC_NOTREG              The requested function is not
  6882.                                    registered.
  6883.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6884.  40     RXFUNC_MODNOTFND           The dynamic link library module
  6885.                                    could not be found.
  6886.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6887.  50     RXFUNC_ENTNOFIND           The dynamic link library entry point
  6888.                                    could not be found.
  6889. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  6890.  
  6891.  
  6892. ΓòÉΓòÉΓòÉ 10.6. System Exit Interface ΓòÉΓòÉΓòÉ
  6893.  
  6894. The REXX System Exits let the programmer create a customized REXX operating 
  6895. environment. You can set up user-defined exit handlers to process specific REXX 
  6896. activities. 
  6897.  
  6898. Applications can create exits for: 
  6899.  
  6900.      The administration of resources at the beginning and end of 
  6901.       interpretation 
  6902.      Linkages to external functions and subcommand handlers 
  6903.      Special language features; for example, input and output to standard 
  6904.       resources 
  6905.      Polling for halt and external trace events 
  6906.  
  6907.  Exit handlers are similar to subcommand handlers and external functions: 
  6908.  
  6909.      Applications must register named exit handlers with the REXX interpreter. 
  6910.      Exit handlers can reside in dynamic link libraries or within an 
  6911.       application EXE module. 
  6912.  
  6913.  
  6914. ΓòÉΓòÉΓòÉ 10.6.1. Writing System Exit Handlers ΓòÉΓòÉΓòÉ
  6915.  
  6916. The following is a sample exit handler definition: 
  6917.  
  6918.  
  6919. Sample system exit handler definition
  6920.  
  6921. LONG Rexx_IO_exit(
  6922.      LONG  ExitNumber,    /* code defining the exit function    */
  6923.      LONG  Subfunction,   /* code defining the exit subfunction */
  6924.      PEXIT ParmBlock);    /* function dependent control block   */
  6925.  
  6926.  ExitNumber  The major function code defining the type of exit call. 
  6927.  
  6928.  Subfunction The subfunction code defining the exit event for the call. 
  6929.  
  6930.  ParmBlock   A pointer to the exit parameter list. 
  6931.  
  6932.              The exit parameter list contains exit-specific information. See 
  6933.              the exit descriptions following parameter list formats. 
  6934.  
  6935.              Note:  Some exit subfunctions do not have parameters. ParmBlock is 
  6936.                     set to null for exit subfunctions without parameters. 
  6937.  
  6938.  
  6939. ΓòÉΓòÉΓòÉ 10.6.1.1. Exit Return Codes ΓòÉΓòÉΓòÉ
  6940.  
  6941. Exit handlers return an integer value that signals one of three actions : 
  6942.  
  6943.  RXEXIT_HANDLED 
  6944.            The exit handler processed the exit subfunction and updated the 
  6945.            subfunction parameter list as required. The REXX interpreter 
  6946.            continues with processing as usual. 
  6947.  
  6948.  RXEXIT_NOT_HANDLED 
  6949.            The exit handler did not process the exit subfunction. The REXX 
  6950.            interpreter processes the subfunction as if the exit handler was not 
  6951.            called. 
  6952.  
  6953.  RXEXIT_RAISE_ERROR 
  6954.            A fatal error occurred in the exit handler. The REXX interpreter 
  6955.            raises REXX error 48 ("Failure in system service"). 
  6956.  
  6957.  For example, if an application creates an input/output exit handler: 
  6958.  
  6959.      When the exit handler returns RXEXIT_NOT_HANDLED for an RXSIOSAY 
  6960.       subfunction, the REXX interpreter writes the output line to STDOUT. 
  6961.  
  6962.      When the exit handler returns RXEXIT_HANDLED for an RXSIOSAY subfunction, 
  6963.       the REXX interpreter assumes the exit handler has handled all required 
  6964.       output. The interpreter does not write the output line to STDOUT. 
  6965.  
  6966.      When the exit handler returns RXEXIT_RAISE_ERROR for an RXSIOSAY 
  6967.       subfunction, the interpreter raises REXX error 48, "Failure in system 
  6968.       service". 
  6969.  
  6970.  
  6971. ΓòÉΓòÉΓòÉ 10.6.1.2. Exit Parameters ΓòÉΓòÉΓòÉ
  6972.  
  6973. Each exit subfunction has a different parameter list. All RXSTRING exit 
  6974. subfunction parameters are passed as null-terminated RXSTRINGs. The RXSTRING 
  6975. value may also contain null characters. 
  6976.  
  6977. For some exit subfunctions, the exit handler may return an RXSTRING character 
  6978. result in the parameter list. The interpreter provides a default 256-byte 
  6979. RXSTRING for the result string. If the result is longer than 256 bytes, a new 
  6980. RXSTRING can be allocated using DosAllocMem. The REXX interpreter returns the 
  6981. RXSTRING storage for the exit handler. 
  6982.  
  6983.  
  6984. ΓòÉΓòÉΓòÉ 10.6.1.3. Identifying Exit Handlers to REXX ΓòÉΓòÉΓòÉ
  6985.  
  6986. System exit handlers must be registered with RexxRegisterExitDll or 
  6987. RexxRegisterExitExe. The system exit handler registration is similar to 
  6988. subcommand handler registration. 
  6989.  
  6990. The REXX system exits are enabled with the RexxStart function parameter Exits. 
  6991. Exits is a pointer to an array of RXSYSEXIT structures. Each RXSYSEXIT 
  6992. structure in the array contains a REXX exit code and the address of an ASCIIZ 
  6993. exit handler name. The RXENDLST exit code marks the exit list end. 
  6994.  
  6995.  
  6996. RXSYSEXIT data structure
  6997.  
  6998. typedef struct {
  6999.    PSZ             sysexit_name;       /* name of exit handler        */
  7000.    LONG            sysexit_code;       /* system exit function code   */
  7001. } RXSYSEXIT;
  7002.  
  7003. The REXX interpreter calls the registered exit handler named in sysexit_name 
  7004. for all of the sysexit_code subfunctions. 
  7005.  
  7006.  
  7007. ΓòÉΓòÉΓòÉ 10.6.1.3.1. Example ΓòÉΓòÉΓòÉ
  7008.  
  7009. The following is a sample of system exit usage: 
  7010.  
  7011.  
  7012. Sample system exit usage
  7013.  
  7014. WORKAREARECORD  *user_info[2];         /* saved user information     */
  7015. RXSYSEXIT exit_list[2];                /* system exit list           */
  7016.   user_info[0] = global_workarea;      /* save global work area for  */
  7017.   user_info[1] = NULL;                 /* re-entrancy                */
  7018.   rc = RexxRegisterExitExe("EditInit", /* register exit handler      */
  7019.       &Init_exit,                      /* located at this address    */
  7020.       user_info);                      /* save global pointer        */
  7021.                                        /* set up for RXINI exit      */
  7022.   exit_list[0].sysexit_name = "EditInit";
  7023.   exit_list[0].sysexit_code = RXINI;
  7024.   exit_list[1].sysexit_code = RXENDLST;
  7025.   return_code = RexxStart(1,           /* one argument               */
  7026.                           argv,        /* argument array             */
  7027.                           "CHANGE.ED", /* REXX procedure name        */
  7028.                           NULL,        /* use disk version           */
  7029.                           "Editor",    /* default address name       */
  7030.                           RXCOMMAND,   /* calling as a subcommand    */
  7031.                           exit_list,   /* exit list                  */
  7032.                           &rc,         /* converted return code      */
  7033.                           &retstr);    /* returned result            */
  7034.                                        /* process return value       */
  7035. .
  7036. .
  7037. .
  7038. }
  7039. LONG Init_exit(
  7040.      LONG  ExitNumber,    /* code defining the exit function    */
  7041.      LONG  Subfunction,   /* code defining the exit subfunction */
  7042.      PEXIT ParmBlock)     /* function dependent control block   */
  7043. {
  7044.   WORKAREARECORD  *user_info[2];       /* saved user information     */
  7045.   WORKAREARECORD   global_workarea;    /* application data anchor    */
  7046.   USHORT           query_flag;         /* flag for handler query     */
  7047.   rc = RexxQueryExit("EditInit",       /* retrieve application work  */
  7048.       NULL,                            /* area anchor from REXX.     */
  7049.       &query_flag,
  7050.       user_info);
  7051.   global_workarea = user_info[0];      /* set the global anchor      */
  7052.   if (global_workarea->rexx_trace)     /* trace at start?            */
  7053.                                        /* turn on macro tracing      */
  7054.     RexxSetTrace(global_workarea->rexx_pid, global_workarea->rexx_tid);
  7055.   return RXEXIT_HANDLED;               /* successfully handled       */
  7056. }
  7057.  
  7058.  
  7059. ΓòÉΓòÉΓòÉ 10.6.2. System Exit Definitions ΓòÉΓòÉΓòÉ
  7060.  
  7061. The REXX interpreter supports the system exits listed below. Exit subfunctions 
  7062. link to more information, including: 
  7063.  
  7064.      When REXX calls the exit 
  7065.      The default action when the exit is not provided or the exit handler does 
  7066.       not process the subfunction 
  7067.      The exit action 
  7068.      Applicable continuations 
  7069.      The subfunction parameters 
  7070.  
  7071.  The system exits and their subfunctions are: 
  7072.  
  7073.  RXFNC     is the external function call exit. 
  7074.  
  7075.            The variable pool interface is fully enabled during calls to this 
  7076.            exit. 
  7077.  
  7078.            RXFNCCAL            calls an external function. 
  7079.  
  7080.  RXCMD     is the subcommand call exit. 
  7081.  
  7082.            The variable pool interface is fully enabled during calls to these 
  7083.            exits. 
  7084.  
  7085.            RXCMDHST            calls a subcommand handler. 
  7086.  
  7087.  RXMSQ     is the external data queue exit. 
  7088.  
  7089.            The variable pool interface is enabled for RXSHV_EXIT requests 
  7090.            during calls to these exits. 
  7091.  
  7092.            RXMSQPLL            pulls a line from the external data queue. 
  7093.            RXMSQPSH            places a line on the external data queue. 
  7094.            RXMSQSIZ            returns the number of lines on the external data 
  7095.                                queue. 
  7096.            RXMSQNAM            sets the active external data queue name. 
  7097.  
  7098.  RXSIO     is the standard input and output exit. 
  7099.  
  7100.            The PARSE LINEIN instruction and the LINEIN, LINEOUT, LINES, CHARIN, 
  7101.            CHAROUT, and CHARS built-in functions do not call the RXSIO exit. 
  7102.  
  7103.            RXSIOSAY            writes a line to the standard output stream for 
  7104.                                the SAY instruction. 
  7105.            RXSIOTRC            writes a line to the standard error stream for 
  7106.                                REXX trace or REXX error messages. 
  7107.            RXSIOTRD            reads a line from the standard input stream for 
  7108.                                PULL or PARSE PULL. 
  7109.            RXSIODTR            reads a line from the standard input stream for 
  7110.                                interactive debug. 
  7111.  
  7112.  RXHLT     is the halt processing exit. 
  7113.  
  7114.            Because the RXHLT exit is called after every REXX instruction, 
  7115.            enabling this exit slows REXX program execution.  The RexxSetHalt 
  7116.            function can halt a REXX program without between-instruction 
  7117.            polling. 
  7118.  
  7119.            RXHLTTST            tests for a HALT condition. 
  7120.            RXHLTCLR            clears a HALT condition. 
  7121.  
  7122.  RXTRC     is the external trace exit. 
  7123.  
  7124.            Because the RXTRC exit handler is called after every REXX 
  7125.            instruction, enabling this exit slows REXX program execution.  The 
  7126.            RexxSetTrace function can turn on REXX tracing without the 
  7127.            between-instruction polling. 
  7128.  
  7129.            RXTRCTST            tests for an external trace event. 
  7130.  
  7131.  RXINI     is the initialization exit. 
  7132.  
  7133.            This exit is called as the last step of REXX program initialization. 
  7134.            The variable pool interface is fully enabled during calls to this 
  7135.            exit. 
  7136.  
  7137.            RXINIEXT            allows additional REXX procedure initialization. 
  7138.  
  7139.  RXTER     is the termination exit. 
  7140.  
  7141.            This exit is called as the first step of REXX program termination. 
  7142.            The variable pool interface is fully enabled during calls to this 
  7143.            exit. 
  7144.  
  7145.            RXTEREXT            processes REXX procedure termination. 
  7146.  
  7147.  
  7148. ΓòÉΓòÉΓòÉ 10.6.2.1. RXFNCCAL ΓòÉΓòÉΓòÉ
  7149.  
  7150. RXFNCCAL processes calls to external functions. 
  7151.  
  7152.       When called: When REXX calls an external subroutine or function. 
  7153.  
  7154.       Default action: Call the external routine using the usual external 
  7155.       function search order. 
  7156.  
  7157.       Exit Action: Call the external routine, if possible. 
  7158.  
  7159.       Continuation: If necessary, raise REXX error 40 ("Incorrect call to 
  7160.       routine"), 43 ("Routine not found"), or 44 ("Function or message did not 
  7161.       return data"). 
  7162.  
  7163.  
  7164. ΓòÉΓòÉΓòÉ 10.6.2.1.1. RXFNCCAL Parameters ΓòÉΓòÉΓòÉ
  7165.  
  7166. typedef struct {
  7167.    struct {
  7168.       unsigned rxfferr  : 1;           /* Invalid call to routine.    */
  7169.       unsigned rxffnfnd : 1;           /* Function not found.         */
  7170.       unsigned rxffsub  : 1;           /* Called as a subroutine if   */
  7171.                                        /* TRUE.  Return values are    */
  7172.                                        /* optional for subroutines,   */
  7173.                                        /* required for functions.     */
  7174.    } rxfnc_flags ;
  7175.    PUCHAR            rxfnc_name;       /* Pointer to function name.   */
  7176.    USHORT            rxfnc_namel;      /* Length of function name.    */
  7177.    PUCHAR            rxfnc_que;        /* Current queue name.         */
  7178.    USHORT            rxfnc_quel;       /* Length of queue name.       */
  7179.    USHORT            rxfnc_argc;       /* Number of args in list.     */
  7180.    PRXSTRING         rxfnc_argv;       /* Pointer to argument list.   */
  7181.                                        /* List mimics argv list for   */
  7182.                                        /* function calls, an array of */
  7183.                                        /* RXSTRINGs.                  */
  7184.    RXSTRING          rxfnc_retc;       /* Return value.               */
  7185. } RXFNCCAL_PARM;
  7186.  
  7187. The name of the external function is defined by rxfnc_name and rxfnc_namel. The 
  7188. arguments to the function are in rxfnc_argc and rxfnc_argv. If you call the 
  7189. named external function with the REXX CALL instruction (rather than using a 
  7190. function call), the flag rxffsub is TRUE. 
  7191.  
  7192. The exit handler can set rxfnc_flags to indicate whether the external function 
  7193. call was successful. If neither rxfferr or rxffnfnd is TRUE, the exit handler 
  7194. successfully called the external function. The error flags are checked only 
  7195. when the exit handler handles the request. 
  7196.  
  7197. The exit handler sets rxffnfnd to TRUE when the exit handler cannot locate the 
  7198. external function. The interpreter raises REXX error 43, "Routine not found". 
  7199. The exit handler sets rxfferr to TRUE when the exit handler locates the 
  7200. external function, but the external function returned an error return code. The 
  7201. REXX interpreter raises error 40, "Incorrect call to routine." 
  7202.  
  7203. The exit handler returns the external function result in the rxfnc_retc 
  7204. RXSTRING. The REXX interpreter raises error 44, "Function or method did not 
  7205. return data," when the external routine is called as a function and the exit 
  7206. handler does not return a result. When the external routine is called with the 
  7207. REXX CALL instruction, a result is not required. 
  7208.  
  7209.  
  7210. ΓòÉΓòÉΓòÉ 10.6.2.2. RXCMDHST ΓòÉΓòÉΓòÉ
  7211.  
  7212. RXCMDHST calls a named subcommand handler. 
  7213.  
  7214.       When called: When REXX procedure issues a command. 
  7215.  
  7216.       Default action: Call the named subcommand handler specified by the 
  7217.       current REXX ADDRESS setting. 
  7218.  
  7219.       Exit Action: Process the call to a named subcommand handler. 
  7220.  
  7221.       Continuation: Raise the ERROR or FAILURE condition when indicated by the 
  7222.       parameter list flags. 
  7223.  
  7224.  
  7225. ΓòÉΓòÉΓòÉ 10.6.2.2.1. RXCMDHST Parameters ΓòÉΓòÉΓòÉ
  7226.  
  7227. typedef struct {
  7228.    struct {                            /* Condition flags             */
  7229.       unsigned rxfcfail : 1;           /* Command failed.  Trap with  */
  7230.                                        /* CALL or SIGNAL on FAILURE.  */
  7231.       unsigned rxfcerr  : 1;           /* Command ERROR occurred.     */
  7232.                                        /* Trap with CALL or SIGNAL on */
  7233.                                        /* ERROR.                      */
  7234.    } rxcmd_flags;
  7235.    PUCHAR            rxcmd_address;    /* Pointer to address name.    */
  7236.    USHORT            rxcmd_addressl;   /* Length of address name.     */
  7237.    PUCHAR            rxcmd_dll;        /* dll name for command.       */
  7238.    USHORT            rxcmd_dll_len;    /* Length of dll name.  0 ==>  */
  7239.                                        /*.EXE file.                  */
  7240.    RXSTRING          rxcmd_command;    /* The command string.         */
  7241.    RXSTRING          rxcmd_retc;       /* Pointer to return code      */
  7242.                                        /* buffer.  User allocated.    */
  7243. } RXCMDHST_PARM;
  7244.  
  7245. The rxcmd_command field contains the issued command. Rxcmd_address, 
  7246. rxcmd_addressl, rxcmd_dll, and rxcmd_dll_len fully define the current ADDRESS 
  7247. setting. Rxcmd_retc is an RXSTRING for the return code value assigned to REXX 
  7248. special variable RC. 
  7249.  
  7250. The exit handler can set rxfcfail or rxfcerr to TRUE to raise an ERROR or 
  7251. FAILURE condition. 
  7252.  
  7253.  
  7254. ΓòÉΓòÉΓòÉ 10.6.2.3. RXMSQPLL ΓòÉΓòÉΓòÉ
  7255.  
  7256. RXMSQPLL pulls a line from the external data queue. 
  7257.  
  7258.       When called: When a REXX PULL instruction, PARSE PULL instruction, or 
  7259.       LINEIN built-in function reads a line from the external data queue. 
  7260.  
  7261.       Default action: Remove a line from the current REXX data queue. 
  7262.  
  7263.       Exit Action: Return a line from the data queue that the exit handler 
  7264.       provided. 
  7265.  
  7266.  
  7267. ΓòÉΓòÉΓòÉ 10.6.2.3.1. RXMSQPLL Parameters ΓòÉΓòÉΓòÉ
  7268.  
  7269. typedef struct {
  7270.    RXSTRING          rxmsq_retc;       /* Pointer to dequeued entry   */
  7271.                                        /* buffer.  User allocated.    */
  7272. } RXMSQPLL_PARM;
  7273.  
  7274. The exit handler returns the queue line in the rxmsq_retc RXSTRING. 
  7275.  
  7276.  
  7277. ΓòÉΓòÉΓòÉ 10.6.2.4. RXMSQPSH ΓòÉΓòÉΓòÉ
  7278.  
  7279. RXMSQPSH places a line on the external data queue. 
  7280.  
  7281.       When called: Called by the REXX PUSH instruction, QUEUE instruction, or 
  7282.       LINEOUT built-in function to add a line to the data queue. 
  7283.  
  7284.       Default action: Add the line to the current REXX data queue. 
  7285.  
  7286.       Exit Action: Add the line to the data queue that the exit handler 
  7287.       provided. 
  7288.  
  7289.  
  7290. ΓòÉΓòÉΓòÉ 10.6.2.4.1. RXMSQPSH Parameters ΓòÉΓòÉΓòÉ
  7291.  
  7292. typedef struct {
  7293.    struct {                            /* Operation flag              */
  7294.       unsigned rxfmlifo : 1;           /* Stack entry LIFO when TRUE, */
  7295.                                        /* FIFO when FALSE.            */
  7296.    } rxmsq_flags;
  7297.    RXSTRING          rxmsq_value;      /* The entry to be pushed.     */
  7298. } RXMSQPSH_PARM;
  7299.  
  7300. The rxmsq_value RXSTRING contains the line added to the queue. It is the 
  7301. responsibility of the exit handler to truncate the string if the exit handler 
  7302. data queue has a maximum length restriction. Rxfmlifo is the stacking order 
  7303. (LIFO or FIFO). 
  7304.  
  7305.  
  7306. ΓòÉΓòÉΓòÉ 10.6.2.5. RXMSQSIZ ΓòÉΓòÉΓòÉ
  7307.  
  7308. RXMSQSIZ returns the number of lines in the external data queue. 
  7309.  
  7310.       When called: When the REXX QUEUED built-in function requests the size of 
  7311.       the external data queue. 
  7312.  
  7313.       Default action: Request the size from the current REXX data queue. 
  7314.  
  7315.       Exit Action: Return the size of the data queue that the exit handler 
  7316.       provided. 
  7317.  
  7318.  
  7319. ΓòÉΓòÉΓòÉ 10.6.2.5.1. RXMSQSIZ Parameters ΓòÉΓòÉΓòÉ
  7320.  
  7321. typedef struct {
  7322.    ULONG             rxmsq_size;       /* Number of Lines in Queue    */
  7323. } RXMSQSIZ_PARM;
  7324.  
  7325. The exit handler returns the number of queue lines in rxmsq_size. 
  7326.  
  7327.  
  7328. ΓòÉΓòÉΓòÉ 10.6.2.6. RXMSQNAM ΓòÉΓòÉΓòÉ
  7329.  
  7330. RXMSQNAM sets the name of the active external data queue. 
  7331.  
  7332.       When called: Called by the RXQUEUE("SET", newname) built-in function. 
  7333.  
  7334.       Default action: Change the current default queue to newname. 
  7335.  
  7336.       Exit Action: Change the default queue name for the data queue that the 
  7337.       exit handler provided. 
  7338.  
  7339.  
  7340. ΓòÉΓòÉΓòÉ 10.6.2.6.1. RXMSQNAM Parameters ΓòÉΓòÉΓòÉ
  7341.  
  7342. typedef struct {
  7343.    RXSTRING          rxmsq_name;       /* RXSTRING containing         */
  7344.                                        /* queue name.                 */
  7345. } RXMSQNAM_PARM;
  7346.  
  7347. Rxmsq_name contains the new queue name. 
  7348.  
  7349.  
  7350. ΓòÉΓòÉΓòÉ 10.6.2.7. RXSIOSAY ΓòÉΓòÉΓòÉ
  7351.  
  7352. RXSIOSAY writes a line to the standard output stream. 
  7353.  
  7354.       When called: By the SAY instruction to write a line to the standard 
  7355.       output stream. 
  7356.  
  7357.       Default action: Write to the standard output stream (STDOUT). 
  7358.  
  7359.       Exit Action: Write the line to the output stream that the exit handler 
  7360.       provided. 
  7361.  
  7362.  
  7363. ΓòÉΓòÉΓòÉ 10.6.2.7.1. RXSIOSAY Parameters ΓòÉΓòÉΓòÉ
  7364.  
  7365. typedef struct {
  7366.    RXSTRING          rxsio_string;     /* String to display.          */
  7367. } RXSIOSAY_PARM;
  7368.  
  7369. The output line is contained in rxsio_string. The output line can be any 
  7370. length. It is the responsibility of the exit handler to truncate or split the 
  7371. line if necessary. 
  7372.  
  7373.  
  7374. ΓòÉΓòÉΓòÉ 10.6.2.8. RXSIOTRC ΓòÉΓòÉΓòÉ
  7375.  
  7376. RXSIOTRC writes trace and error message output to the standard error stream. 
  7377.  
  7378.       When called: To output lines of trace output and REXX error messages. 
  7379.  
  7380.       Default action: Write the line to the standard error stream (.ERROR). 
  7381.  
  7382.       Exit Action: Write the line to the error output stream that the exit 
  7383.       handler provided. 
  7384.  
  7385.  
  7386. ΓòÉΓòÉΓòÉ 10.6.2.8.1. RXSIOTRC Parameters ΓòÉΓòÉΓòÉ
  7387.  
  7388. typedef struct {
  7389.   RXSTRING           rxsio_string;     /* Trace line to display.      */
  7390. } RXSIOTRC_PARM;
  7391.  
  7392. The output line is contained in rxsio_string. The output line may be of any 
  7393. length. It is the responsibility of the exit handler to truncate or split the 
  7394. line if necessary. 
  7395.  
  7396.  
  7397. ΓòÉΓòÉΓòÉ 10.6.2.9. RXSIOTRD ΓòÉΓòÉΓòÉ
  7398.  
  7399. RXSIOTRD reads from a standard input stream. 
  7400.  
  7401.       When called: To read from the standard input stream for the REXX PULL and 
  7402.       PARSE PULL instructions. 
  7403.  
  7404.       Default action: Read a line from the standard input stream (STDIN). 
  7405.  
  7406.       Exit Action: Return a line from the standard input stream that the exit 
  7407.       handler provided. 
  7408.  
  7409.  
  7410. ΓòÉΓòÉΓòÉ 10.6.2.9.1. RXSIOTRD Parameters ΓòÉΓòÉΓòÉ
  7411.  
  7412. typedef struct {
  7413.    RXSTRING          rxsiotrd_retc;    /* RXSTRING for output.        */
  7414. } RXSIOTRD_PARM;
  7415.  
  7416. The input stream line is returned in the rxsiotrd_retc RXSTRING. 
  7417.  
  7418.  
  7419. ΓòÉΓòÉΓòÉ 10.6.2.10. RXSIODTR ΓòÉΓòÉΓòÉ
  7420.  
  7421. RXSIODTR reads the interactive debug input. 
  7422.  
  7423.       When called: To read from the debug input stream for interactive debug 
  7424.       prompts. 
  7425.  
  7426.       Default action: Read a line from the standard input stream (STDIN). 
  7427.  
  7428.       Exit Action: Return a line from the standard debug stream that the exit 
  7429.       handler provided. 
  7430.  
  7431.  
  7432. ΓòÉΓòÉΓòÉ 10.6.2.10.1. RXSIODTR Parameters ΓòÉΓòÉΓòÉ
  7433.  
  7434. typedef struct {
  7435.    RXSTRING          rxsiodtr_retc;    /* RXSTRING for output.        */
  7436. } RXSIODTR_PARM;
  7437.  
  7438. The input stream line is returned in the rxsiodtr_retc RXSTRING. 
  7439.  
  7440.  
  7441. ΓòÉΓòÉΓòÉ 10.6.2.11. RXHLTTST ΓòÉΓòÉΓòÉ
  7442.  
  7443. RXHLTTST tests the HALT indicator. 
  7444.  
  7445.       When called: When the interpreter polls externally raised HALT 
  7446.       conditions. The exit will be called after completion of every REXX 
  7447.       instruction. 
  7448.  
  7449.       Default action: The interpreter uses the system facilities for trapping 
  7450.       Cntrl-Break signals. 
  7451.  
  7452.       Exit Action: Return the current state of the HALT condition (either TRUE 
  7453.       or FALSE). 
  7454.  
  7455.       Continuation: Raise the REXX HALT condition if the exit handler returns 
  7456.       TRUE. 
  7457.  
  7458.  
  7459. ΓòÉΓòÉΓòÉ 10.6.2.11.1. RXHLTTST Parameters ΓòÉΓòÉΓòÉ
  7460.  
  7461. typedef struct {
  7462.    struct {                            /* Halt flag                   */
  7463.       unsigned rxfhhalt : 1;           /* Set if HALT occurred.       */
  7464.    } rxhlt_flags;
  7465. } RXHLTTST_PARM;
  7466.  
  7467. If the exit handler sets rxfhhalt to TRUE, the HALT condition is raised in the 
  7468. REXX program. 
  7469.  
  7470. When the exit handler has set rxfhhalt to TRUE, it can also use the RXSHV_EXIT 
  7471. operation of RexxVariablePool to return a string describing the HALT condition 
  7472. reason. The REXX program can retrieve the reason string using the 
  7473. CONDITION("D") built-in function. 
  7474.  
  7475.  
  7476. ΓòÉΓòÉΓòÉ 10.6.2.12. RXHLTCLR ΓòÉΓòÉΓòÉ
  7477.  
  7478. RXHLTCLR clears a HALT condition. 
  7479.  
  7480.       When called: To acknowledge processing of the HALT condition when the 
  7481.       interpreter has recognized and raised a HALT condition 
  7482.  
  7483.       Default action: The interpreter resets the Cntrl-Break signal handlers. 
  7484.  
  7485.       Exit Action: Reset exit handler HALT state to FALSE. 
  7486.  
  7487.  
  7488. ΓòÉΓòÉΓòÉ 10.6.2.12.1. RXHLTCLR Parameters ΓòÉΓòÉΓòÉ
  7489.  
  7490. None. 
  7491.  
  7492.  
  7493. ΓòÉΓòÉΓòÉ 10.6.2.13. RXTRCTST ΓòÉΓòÉΓòÉ
  7494.  
  7495. RXTRCTST tests for an external trace indicator. 
  7496.  
  7497.       When called: When the interpreter polls for an external trace event. The 
  7498.       exit is called after completion of every REXX instruction. 
  7499.  
  7500.       Default action: None. 
  7501.  
  7502.       Exit Action: Return the current state of external tracing (either TRUE or 
  7503.       FALSE). 
  7504.  
  7505.       Continuation: When the exit handler switches from FALSE to TRUE, the REXX 
  7506.       interpreter enters REXX interactive debug mode using TRACE ?R level of 
  7507.       tracing. When the exit handler switches from TRUE to FALSE, the REXX 
  7508.       interpreter exits interactive debug mode. 
  7509.  
  7510.  
  7511. ΓòÉΓòÉΓòÉ 10.6.2.13.1. RXTRCTST Parameters ΓòÉΓòÉΓòÉ
  7512.  
  7513. typedef struct {
  7514.   struct {
  7515.     unsigned rxftrace : 1;        /* External trace setting        */
  7516.   } rxtrc_flags;
  7517. } RXTRCTST_PARM;
  7518.  
  7519. If the exit handler switches rxftrace to TRUE, REXX switches on interactive 
  7520. debug mode. It the exit handler switches rxftrace to FALSE, REXX switches off 
  7521. interactive debug mode. 
  7522.  
  7523.  
  7524. ΓòÉΓòÉΓòÉ 10.6.2.14. RXINIEXT ΓòÉΓòÉΓòÉ
  7525.  
  7526. RXINIEXT allows for additional initialization processing. 
  7527.  
  7528.       When called: Before the first instruction of the REXX procedure is 
  7529.       interpreted. 
  7530.  
  7531.       Default action: None. 
  7532.  
  7533.       Exit Action: The exit handler may perform additional initialization. For 
  7534.       example: 
  7535.  
  7536.           Use RexxVariablePool to initialize application specific variables 
  7537.  
  7538.           Use RexxSetTrace to switch on REXX interactive debug mode. 
  7539.  
  7540.  
  7541. ΓòÉΓòÉΓòÉ 10.6.2.14.1. RXINIEXT Parameters ΓòÉΓòÉΓòÉ
  7542.  
  7543. None. 
  7544.  
  7545.  
  7546. ΓòÉΓòÉΓòÉ 10.6.2.15. RXTEREXT ΓòÉΓòÉΓòÉ
  7547.  
  7548. RXTEREXT performs termination processing. 
  7549.  
  7550.       When called: After the last instruction of the REXX procedure has been 
  7551.       interpreted. 
  7552.  
  7553.       Default action: None. 
  7554.  
  7555.       Exit Action: The exit handler may perform additional termination 
  7556.       activities. For example, the exit handler can use RexxVariablePool to 
  7557.       retrieve REXX variable values. 
  7558.  
  7559.  
  7560. ΓòÉΓòÉΓòÉ 10.6.2.15.1. RXTEREXT Parameters ΓòÉΓòÉΓòÉ
  7561.  
  7562. None. 
  7563.  
  7564.  
  7565. ΓòÉΓòÉΓòÉ 10.6.3. System Exit Functions ΓòÉΓòÉΓòÉ
  7566.  
  7567. The system exit functions are similar to the subcommand handler functions. The 
  7568. system exit functions are: 
  7569.  
  7570.       RexxRegisterExitDll 
  7571.       RexxRegisterExitExe 
  7572.       RexxDeregisterExit 
  7573.       RexxQueryExit 
  7574.  
  7575.  
  7576. ΓòÉΓòÉΓòÉ 10.6.3.1. RexxRegisterExitDll ΓòÉΓòÉΓòÉ
  7577.  
  7578. RexxRegisterExitDll registers an exit handler that resides in a dynalink 
  7579. library routine. 
  7580.  
  7581. Topics: 
  7582.  
  7583.      Syntax 
  7584.  
  7585.      Parameters 
  7586.  
  7587.      Returns 
  7588.  
  7589.      Remarks 
  7590.  
  7591.  
  7592. ΓòÉΓòÉΓòÉ 10.6.3.1.1. RexxRegisterExitDll - Syntax ΓòÉΓòÉΓòÉ
  7593.  
  7594. RexxRegisterExitDll(ExitName, ModuleName, EntryPoint, UserArea,
  7595. DropAuth)
  7596.  
  7597.  
  7598. ΓòÉΓòÉΓòÉ 10.6.3.1.2. RexxRegisterExitDll - Parameters ΓòÉΓòÉΓòÉ
  7599.  
  7600.  ExitName (PSZ) - input 
  7601.            Address of an ASCIIZ exit handler name. 
  7602.  
  7603.  ModuleName (PSZ) - input 
  7604.            Address of an ASCIIZ dynamic link library name. ModuleName is the 
  7605.            DLL file containing the exit handler routine. 
  7606.  
  7607.  EntryPoint (PSZ) - input 
  7608.            Address of an ASCIIZ dynalink procedure name. EntryPoint is the 
  7609.            routine within ModuleName that REXX calls as an exit handler. 
  7610.  
  7611.  UserArea (PUCHAR) - input 
  7612.            Address of an 8-byte area of user-defined information. The 8 bytes 
  7613.            UserArea addresses are saved with the exit handler registration. 
  7614.            UserArea can be NULL if there is no user information to save. The 
  7615.            RexxQueryExit function can retrieve the saved user information. 
  7616.  
  7617.  DropAuth (ULONG) - input 
  7618.            The drop authority. DropAuth identifies the processes that can 
  7619.            deregister the exit handler. The possible DropAuth values are: 
  7620.  
  7621.            RXEXIT_DROPPABLE 
  7622.                           Any process can deregister the exit handler with 
  7623.                           RexxDeregisterExit. 
  7624.  
  7625.            RXEXIT_NONDROP 
  7626.                           Only a thread within the same process as the thread 
  7627.                           that registered the handler can deregister the 
  7628.                           handler with RexxDeregisterExit. 
  7629.  
  7630.  
  7631. ΓòÉΓòÉΓòÉ 10.6.3.1.3. RexxRegisterExitDll - Returns ΓòÉΓòÉΓòÉ
  7632.  
  7633. The RexxRegisterExitDll return values are: 
  7634.  
  7635. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7636.  0      RXEXIT_OK                  Function completed successfully.
  7637.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7638.  10     RXEXIT_DUP                 A duplicate handler name has been
  7639.                                    successfully registered.  There is
  7640.                                    either an EXE handler with the same
  7641.                                    name registered in another process,
  7642.                                    or a DLL handler with the same name
  7643.                                    registered in another DLL.  (To
  7644.                                    address this exit handler you must
  7645.                                    specify its library name.)
  7646.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7647.  1002   RXEXIT_NOEMEM              There is insufficient memory to
  7648.                                    complete this request.
  7649. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7650.  
  7651.  
  7652. ΓòÉΓòÉΓòÉ 10.6.3.1.4. RexxRegisterExitDll - Remarks ΓòÉΓòÉΓòÉ
  7653.  
  7654. EntryPoint can be either a 16-bit or a 32-bit routine. REXX calls the exit 
  7655. handler in the correct addressing mode. 
  7656.  
  7657.  
  7658. ΓòÉΓòÉΓòÉ 10.6.3.2. RexxRegisterExitExe ΓòÉΓòÉΓòÉ
  7659.  
  7660. RexxRegisterExitExe registers an exit handler that resides within application 
  7661. code. 
  7662.  
  7663. Topics: 
  7664.  
  7665.      Syntax 
  7666.  
  7667.      Parameters 
  7668.  
  7669.      Returns 
  7670.  
  7671.      Remarks 
  7672.  
  7673.      Example 
  7674.  
  7675.  
  7676. ΓòÉΓòÉΓòÉ 10.6.3.2.1. RexxRegisterExitExe - Syntax ΓòÉΓòÉΓòÉ
  7677.  
  7678. RexxRegisterExitExe(ExitName, EntryPoint, UserArea)
  7679.  
  7680.  
  7681. ΓòÉΓòÉΓòÉ 10.6.3.2.2. RexxRegisterExitExe - Parameters ΓòÉΓòÉΓòÉ
  7682.  
  7683.  ExitName (PSZ) - input 
  7684.            Address of an ASCIIZ exit handler name. 
  7685.  
  7686.  EntryPoint (PFN) - input 
  7687.            Address of the exit handler entry point within the application EXE 
  7688.            file. 
  7689.  
  7690.  UserArea (PUCHAR) - input 
  7691.            Address of an 8-byte area of user-defined information. The 8 bytes 
  7692.            UserArea addresses are saved with the exit handler registration. 
  7693.            UserArea can be NULL if there is no user information to save. The 
  7694.            RexxQueryExit function can retrieve the user information. 
  7695.  
  7696.  
  7697. ΓòÉΓòÉΓòÉ 10.6.3.2.3. RexxRegisterExitExe - Returns ΓòÉΓòÉΓòÉ
  7698.  
  7699. The RexxRegisterExitExe return values are: 
  7700.  
  7701. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7702.  0      RXEXIT_OK                  Function completed successfully.
  7703.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7704.  10     RXEXIT_DUP                 A duplicate handler name has been
  7705.                                    successfully registered.  There is
  7706.                                    either an EXE handler with the same
  7707.                                    name registered in another process,
  7708.                                    or a DLL handler with the same name
  7709.                                    registered in another DLL.  (To
  7710.                                    address this exit handler you must
  7711.                                    specify its library name.)
  7712.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7713.  30     RXEXIT_NOTREG              Registration was unsuccessful due to
  7714.                                    duplicate handler and dynalink names
  7715.                                    (RexxRegisterExitExe or
  7716.                                    RexxRegisterExitDll); the exit
  7717.                                    handler is not registered (other
  7718.                                    REXX exit handler functions).
  7719.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7720.  1002   RXEXIT_NOEMEM              There is insufficient memory to
  7721.                                    complete this request.
  7722. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7723.  
  7724.  
  7725. ΓòÉΓòÉΓòÉ 10.6.3.2.4. RexxRegisterExitExe - Remarks ΓòÉΓòÉΓòÉ
  7726.  
  7727. If ExitName has the same name as a handler registered with RexxRegisterExitDll, 
  7728. RexxRegisterExitExe returns RXEXIT_DUP. This is not an error and the new exit 
  7729. handler has been properly registered. 
  7730.  
  7731.  
  7732. ΓòÉΓòÉΓòÉ 10.6.3.2.5. RexxRegisterExitExe - Example ΓòÉΓòÉΓòÉ
  7733.  
  7734. The following is a sample exit handler registration: 
  7735.  
  7736.  
  7737. Sample exit handler registration
  7738.  
  7739.   WORKAREARECORD  *user_info[2];       /* saved user information     */
  7740.   user_info[0] = global_workarea;      /* save global work area for  */
  7741.   user_info[1] = NULL;                 /* re-entrancy                */
  7742.   rc = RexxRegisterExitExe("IO_Exit",  /* register editor handler    */
  7743.       &Edit_IO_Exit,                   /* located at this address    */
  7744.       user_info);                      /* save global pointer        */
  7745.  
  7746.  
  7747. ΓòÉΓòÉΓòÉ 10.6.3.3. RexxDeregisterExit ΓòÉΓòÉΓòÉ
  7748.  
  7749. RexxDeregisterExit deregisters an exit handler. 
  7750.  
  7751. Topics: 
  7752.  
  7753.      Syntax 
  7754.  
  7755.      Parameters 
  7756.  
  7757.      Returns 
  7758.  
  7759.      Remarks 
  7760.  
  7761.  
  7762. ΓòÉΓòÉΓòÉ 10.6.3.3.1. RexxDeregisterExit - Syntax ΓòÉΓòÉΓòÉ
  7763.  
  7764. RexxDeregisterExit(ExitName, ModuleName)
  7765.  
  7766.  
  7767. ΓòÉΓòÉΓòÉ 10.6.3.3.2. RexxDeregisterExit - Parameters ΓòÉΓòÉΓòÉ
  7768.  
  7769.  ExitName (PSZ) - input 
  7770.            Address of an ASCIIZ exit handler name. 
  7771.  
  7772.  ModuleName (PSZ) - input 
  7773.            Address of an ASCIIZ dynamic link library name. ModuleName restricts 
  7774.            the query to an exit handler within the ModuleName dynamic link 
  7775.            library. When ModuleName is NULL, RexxDeregisterExit searches the 
  7776.            RexxRegisterExitExe exit handler list for a handler within the 
  7777.            current process. If RexxDeregisterExit does not find a 
  7778.            RexxRegisterExitExe handler, it searches the RexxRegisterExitDll 
  7779.            exit handler list. 
  7780.  
  7781.  
  7782. ΓòÉΓòÉΓòÉ 10.6.3.3.3. RexxDeregisterExit - Returns ΓòÉΓòÉΓòÉ
  7783.  
  7784. The RexxDeregisterExit return values are: 
  7785.  
  7786. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7787.  0      RXEXIT_OK                  Function completed successfully.
  7788.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7789.  30     RXEXIT_NOTREG              Registration was unsuccessful due to
  7790.                                    duplicate handler and dynalink names
  7791.                                    (RexxRegisterExitExe or
  7792.                                    RexxRegisterExitDll); the exit
  7793.                                    handler is not registered (other
  7794.                                    REXX exit handler functions).
  7795.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7796.  40     RXEXIT_NOCANDROP           The exit handler has been registered
  7797.                                    as "not droppable."
  7798. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7799.  
  7800.  
  7801. ΓòÉΓòÉΓòÉ 10.6.3.3.4. RexxDeregisterExit - Remarks ΓòÉΓòÉΓòÉ
  7802.  
  7803. The handler is removed from the exit handler list. 
  7804.  
  7805.  
  7806. ΓòÉΓòÉΓòÉ 10.6.3.4. RexxQueryExit ΓòÉΓòÉΓòÉ
  7807.  
  7808. RexxQueryExit queries an exit handler and retrieves saved user information. 
  7809.  
  7810. Topics 
  7811.  
  7812.      Syntax 
  7813.  
  7814.      Parameters 
  7815.  
  7816.      Returns 
  7817.  
  7818.      Example 
  7819.  
  7820.  
  7821. ΓòÉΓòÉΓòÉ 10.6.3.4.1. RexxQueryExit - Syntax ΓòÉΓòÉΓòÉ
  7822.  
  7823. RexxQueryExit(ExitName, ModuleName, Flag, UserWord)
  7824.  
  7825.  
  7826. ΓòÉΓòÉΓòÉ 10.6.3.4.2. RexxQueryExit - Parameters ΓòÉΓòÉΓòÉ
  7827.  
  7828.  ExitName (PSZ) - input 
  7829.            Address of an ASCIIZ exit handler name. 
  7830.  
  7831.  ModuleName (PSZ) - input 
  7832.            ModuleName restricts the query to an exit handler within the 
  7833.            ModuleName dynamic link library. When ModuleName is NULL, 
  7834.            RexxQueryExit searches the RexxRegisterExitExe exit handler list for 
  7835.            a handler within the current process. If RexxQueryExit does not find 
  7836.            a RexxRegisterExitExe handler, it searches the RexxRegisterExitDll 
  7837.            exit handler list. 
  7838.  
  7839.  Flag (PUSHORT) - output 
  7840.            Exit handler registration flag. Flag is the ExitName exit handler 
  7841.            registration status. When RexxQueryExit returns RXEXIT_OK, the 
  7842.            ExitName exit handler is currently registered. When RexxQueryExit 
  7843.            returns RXEXIT_NOTREG, the ExitName exit handler is not registered. 
  7844.  
  7845.  UserWord (PUCHAR) - output 
  7846.            Address of an 8-byte area to receive the user information saved with 
  7847.            RexxRegisterExitExe or RexxRegisterExitDll. UserWord can be NULL if 
  7848.            the saved user information is not required. 
  7849.  
  7850.  
  7851. ΓòÉΓòÉΓòÉ 10.6.3.4.3. RexxQueryExit - Returns ΓòÉΓòÉΓòÉ
  7852.  
  7853. The RexxQueryExit return values are: 
  7854.  
  7855. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7856.  0      RXEXIT_OK                  Function completed successfully.
  7857.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7858.  30     RXEXIT_NOTREG              Registration was unsuccessful due to
  7859.                                    duplicate handler and dynalink names
  7860.                                    ( RexxRegisterExitExe or
  7861.                                    RexxRegisterExitDll); the exit
  7862.                                    handler is not registered (other
  7863.                                    REXX exit handler functions).
  7864. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7865.  
  7866.  
  7867. ΓòÉΓòÉΓòÉ 10.6.3.4.4. RexxQueryExit - Example ΓòÉΓòÉΓòÉ
  7868.  
  7869. The following is a sample exit handler query: 
  7870.  
  7871.  
  7872. Sample exit handler query
  7873.  
  7874. ULONG Edit_IO_Exit(
  7875.   PRXSTRING Command,    /* Command string passed from the caller    */
  7876.   PUSHORT   Flags,      /* pointer to short for return of flags     */
  7877.   PRXSTRING Retstr)     /* pointer to RXSTRING for RC return        */
  7878. {
  7879.   WORKAREARECORD  *user_info[2];       /* saved user information     */
  7880.   WORKAREARECORD   global_workarea;    /* application data anchor    */
  7881.   USHORT           query_flag;         /* flag for handler query     */
  7882.   rc = RexxQueryExit("IO_Exit",        /* retrieve application work  */
  7883.       NULL,                            /* area anchor from REXX.     */
  7884.       &query_flag,
  7885.       user_info);
  7886.   global_workarea = user_info[0];      /* set the global anchor      */
  7887.  
  7888.  
  7889. ΓòÉΓòÉΓòÉ 10.6.4. System Exit Interface Returns ΓòÉΓòÉΓòÉ
  7890.  
  7891. The return codes for the System Exit Interface are as follows: 
  7892.  
  7893. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7894.  0      RXEXIT_OK                  Function completed successfully.
  7895.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7896.  10     RXEXIT_DUP                 A duplicate handler name has been
  7897.                                    successfully registered.  There is
  7898.                                    either an EXE handler with the same
  7899.                                    name registered in another process,
  7900.                                    or a DLL handler with the same name
  7901.                                    registered in another DLL.  (To
  7902.                                    address this exit handler you must
  7903.                                    specify its library name.)
  7904.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7905.  30     RXEXIT_NOTREG              Registration was unsuccessful due to
  7906.                                    duplicate handler and dynalink names
  7907.                                    (RexxRegisterExitExe or
  7908.                                    RexxRegisterExitDll); the exit
  7909.                                    handler is not registered (other
  7910.                                    REXX exit handler functions).
  7911.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7912.  40     RXEXIT_NOCANDROP           The exit handler has been registered
  7913.                                    as "not droppable."
  7914.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7915.  1002   RXEXIT_NOEMEM              There is insufficient memory to
  7916.                                    complete this request.
  7917. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  7918.  
  7919.  
  7920. ΓòÉΓòÉΓòÉ 10.7. Variable Pool Interface ΓòÉΓòÉΓòÉ
  7921.  
  7922. Application programs can use the REXX Variable Pool Interface to manipulate the 
  7923. variables of a currently active REXX procedure. 
  7924.  
  7925.  
  7926. ΓòÉΓòÉΓòÉ 10.7.1. Interface Types ΓòÉΓòÉΓòÉ
  7927.  
  7928. Three of the Variable Pool Interface functions (set, fetch, and drop) have dual 
  7929. interfaces. 
  7930.  
  7931.  
  7932. ΓòÉΓòÉΓòÉ 10.7.1.1. Symbolic Interface ΓòÉΓòÉΓòÉ
  7933.  
  7934. The symbolic interface uses normal REXX variable rules when interpreting 
  7935. variables. Variable names are valid REXX symbols (in mixed case if desired) 
  7936. including compound symbols. Compound symbols are referenced with tail 
  7937. substitution. The functions that use the symbolic interface are RXSHV_SYSET, 
  7938. RXSHV_SYFET, and RXSHV_SYDRO. 
  7939.  
  7940.  
  7941. ΓòÉΓòÉΓòÉ 10.7.1.2. Direct Interface ΓòÉΓòÉΓòÉ
  7942.  
  7943. The direct interface uses no substitution or case translation. Simple symbols 
  7944. must be valid REXX variable names. A valid REXX variable name: 
  7945.  
  7946.      Does not begin with a digit or period 
  7947.  
  7948.      Contains only uppercase A to Z, the digits 0 - 9, or the characters _, ! 
  7949.       or ? before the first period of the name. 
  7950.  
  7951.      Can contain any characters after the first period of the name. 
  7952.  
  7953.  Compound variables are specified using the derived name of the variable.  Any 
  7954.  characters (including blanks) may appear after the first period of the name. 
  7955.  No additional variable substitution is used. RXSHV_SET, RXSHV_FETCH, and 
  7956.  RXSHV_DROP use the direct interface. 
  7957.  
  7958.  
  7959. ΓòÉΓòÉΓòÉ 10.7.2. RexxVariablePool Restrictions ΓòÉΓòÉΓòÉ
  7960.  
  7961. Only the main thread of an application can access the REXX variable pool. 
  7962. Applications may create and use new threads, but only the original thread that 
  7963. called RexxStart can use RexxVariablePool. 
  7964.  
  7965. OS/2 EXE modules called from a REXX procedure execute in a new process. Because 
  7966. the modules are not using the same process and thread as the REXX procedure, 
  7967. the modules cannot use RexxVariablePool to access REXX variables. You can use 
  7968. RexxVariablePool from subcommand handlers, external functions and exit 
  7969. handlers. 
  7970.  
  7971.  
  7972. ΓòÉΓòÉΓòÉ 10.7.3. RexxVariablePool Interface Function ΓòÉΓòÉΓòÉ
  7973.  
  7974. REXX procedure variables are accessed using the RexxVariablePool function. 
  7975.  
  7976.  
  7977. ΓòÉΓòÉΓòÉ 10.7.3.1. RexxVariablePool ΓòÉΓòÉΓòÉ
  7978.  
  7979. RexxVariablePool accesses variables of a currently active REXX procedure. 
  7980.  
  7981. Topics: 
  7982.  
  7983.      Syntax 
  7984.  
  7985.      Parameters 
  7986.  
  7987.      Returns 
  7988.  
  7989.      Example 
  7990.  
  7991.  
  7992. ΓòÉΓòÉΓòÉ 10.7.3.1.1. RexxVariablePool - Syntax ΓòÉΓòÉΓòÉ
  7993.  
  7994. RexxVariablePool(RequestBlockList)
  7995.  
  7996.  
  7997. ΓòÉΓòÉΓòÉ 10.7.3.1.2. RexxVariablePool - Parameters ΓòÉΓòÉΓòÉ
  7998.  
  7999.  RequestBlockList (PSHVBLOCK) - input 
  8000.            A linked list of shared variable request blocks (SHVBLOCK). Each 
  8001.            shared variable request block in the linked list is a separate 
  8002.            variable access request. 
  8003.  
  8004.  The SHVBLOCK has the following form: 
  8005.  
  8006.  
  8007.   SHVBLOCK data structure
  8008.  
  8009.   typedef struct shvnode {
  8010.       struct shvnode    *shvnext;
  8011.       RXSTRING           shvname;
  8012.       RXSTRING           shvvalue;
  8013.       ULONG              shvnamelen;
  8014.       ULONG              shvvaluelen;
  8015.       UCHAR              shvcode;
  8016.       UCHAR              shvret;
  8017.   }   SHVBLOCK;
  8018.  
  8019.  shvnext   The address of the next SHVBLOCK in the request list. shvnext is 
  8020.            NULL for the last request block. 
  8021.  
  8022.  shvname   An RXSTRING containing a REXX variable name. shvname usage varies 
  8023.            for the different SHVBLOCK request codes: 
  8024.  
  8025.            RXSHV_SET 
  8026.  
  8027.            RXSHV_SYSET 
  8028.  
  8029.            RXSHV_FETCH 
  8030.  
  8031.            RXSHV_SYFET 
  8032.  
  8033.            RXSHV_DROPV 
  8034.  
  8035.            RXSHV_SYDRO 
  8036.  
  8037.            RXSHV_PRIV     shvname is an RXSTRING pointing to the name of the 
  8038.                           REXX variable the shared variable request block 
  8039.                           accesses. 
  8040.  
  8041.            RXSHV_NEXTV    shvname is an RXSTRING defining an area of storage to 
  8042.                           receive the name of the next variable. shvnamelen is 
  8043.                           the length of the RXSTRING area. If the variable name 
  8044.                           is longer than shvnamelen characters, the name is 
  8045.                           truncated and the RXSHV_TRUNC bit of shvret is set. 
  8046.                           On return, shvname.strlength contains the length of 
  8047.                           the variable name; shvnamelen is unchanged. 
  8048.  
  8049.                           If shvname is an empty RXSTRING (strptr is NULL), the 
  8050.                           REXX interpreter allocates and returns an RXSTRING to 
  8051.                           hold the variable name. If the REXX interpreter 
  8052.                           allocates the RXSTRING, an RXSHV_TRUNC condition 
  8053.                           cannot occur. However, RXSHV_MEMFL errors are 
  8054.                           possible for these operations. If an RXSHV_MEMFL 
  8055.                           condition occurs, memory is not allocated for that 
  8056.                           request block. The RexxVariablePool caller must 
  8057.                           release the storage with DosFreeMem. 
  8058.  
  8059.                           Note:  The RexxVariablePool does not add a 
  8060.                                  terminating null character to the variable 
  8061.                                  name. 
  8062.  
  8063.            RXSHV_EXIT     shvname is unused for the RXSHV_EXIT function. 
  8064.  
  8065.  shvvalue  An RXSTRING containing a REXX variable value. The meaning of 
  8066.            shvvalue varies for the different SHVBLOCK request codes: 
  8067.  
  8068.            RXSHV_SET 
  8069.  
  8070.            RXSHV_SYSET    shvvalue is the value assigned to the REXX variable 
  8071.                           in shvname. shvvaluelen contains the length of the 
  8072.                           variable value. 
  8073.  
  8074.            RXSHV_EXIT     shvvalue is the value assigned to the exit handler 
  8075.                           return value. shvvaluelen contains the length of the 
  8076.                           variable value. 
  8077.  
  8078.            RXSHV_FETCH 
  8079.  
  8080.            RXSHV_SYFET 
  8081.  
  8082.            RXSHV_PRIV 
  8083.  
  8084.            RXSHV_NEXT     shvvalue is a buffer the REXX interpreter uses to 
  8085.                           return a copy of REXX variable shvname. shvvaluelen 
  8086.                           contains the length of the value buffer. On return, 
  8087.                           shvvalue.strlength is set to the length of the 
  8088.                           returned value and shvvaluelen is unchanged. If the 
  8089.                           variable value is longer than shvvaluelen characters, 
  8090.                           the value is truncated and the RXSHV_TRUNC bit of 
  8091.                           shvret is set. On return, shvvalue.strlength is set 
  8092.                           to the length of the returned value; shvvaluelen is 
  8093.                           unchanged. 
  8094.  
  8095.                           If shvvalue is an empty RXSTRING (strptr is NULL), 
  8096.                           the REXX interpreter allocates and returns an 
  8097.                           RXSTRING to hold the variable value. If the REXX 
  8098.                           interpreter allocates the RXSTRING, an RXSHV_TRUNC 
  8099.                           condition cannot occur. However, RXSHV_MEMFL errors 
  8100.                           are possible for these operations. If an RXSHV_MEMFL 
  8101.                           condition occurs, memory is not allocated for that 
  8102.                           request block. The RexxVariablePool caller must 
  8103.                           release the storage with DosFreeMem. 
  8104.  
  8105.                           Note:  The RexxVariablePool does not add a 
  8106.                                  terminating null character to the variable 
  8107.                                  value. 
  8108.  
  8109.            RXSHV_DROPV 
  8110.  
  8111.            RXSHV_SYDRO    shvvalue is not used. 
  8112.  
  8113.  shvcode   The shared variable block request code. The request codes are: 
  8114.  
  8115.            RXSHV_SET 
  8116.  
  8117.            RXSHV_SYSET    Assign a new value to a REXX procedure variable. 
  8118.  
  8119.            RXSHV_FETCH 
  8120.  
  8121.            RXSHV_SYFET    Retrieve the value of a REXX procedure variable. 
  8122.  
  8123.            RXSHV_DROPV 
  8124.  
  8125.            RXSHV_SYDRO    Drop (unassign) a REXX procedure variable. 
  8126.  
  8127.            RXSHV_PRIV     Fetch REXX procedure private information. The 
  8128.                           following information items can be retrieved by name: 
  8129.  
  8130.                           EXITNAME 
  8131.                                          The name of the current system exit 
  8132.                                          handler for this thread. If not called 
  8133.                                          from within an exit handler, a null 
  8134.                                          string will be returned. 
  8135.  
  8136.                           PARM 
  8137.                                          The number of arguments supplied to 
  8138.                                          the REXX procedure. The number is 
  8139.                                          formatted as a character string. 
  8140.  
  8141.                           PARM.n 
  8142.                                          The Nth argument string to the REXX 
  8143.                                          procedure. If the Nth argument was not 
  8144.                                          supplied to the procedure (either 
  8145.                                          omitted or fewer than N parameters 
  8146.                                          were specified), a null string is 
  8147.                                          returned. 
  8148.  
  8149.                           QUENAME 
  8150.                                          The current REXX data queue name. 
  8151.  
  8152.                           SOURCE 
  8153.                                          The REXX procedure source string used 
  8154.                                          for the PARSE SOURCE instruction. 
  8155.  
  8156.                           VERSION 
  8157.                                          The REXX interpreter version string 
  8158.                                          used for the PARSE SOURCE instruction. 
  8159.  
  8160.            RXSHV_NEXTV    Fetch next variable. RXSHV_NEXTV traverses the 
  8161.                           variables in the current generation of REXX 
  8162.                           variables, excluding variables hidden by PROCEDURE 
  8163.                           instructions. The variables are not returned in any 
  8164.                           specified order. 
  8165.  
  8166.                           The REXX interpreter maintains an internal pointer to 
  8167.                           its list of variables. The variable pointer is reset 
  8168.                           to the first REXX variable whenever: 
  8169.  
  8170.                             1. An external program returns control to the 
  8171.                                interpreter 
  8172.                             2. A set, fetch or drop RexxVariablePool function 
  8173.                                is used. 
  8174.  
  8175.                           RXSHV_NEXTV returns both the name and the value of 
  8176.                           REXX variables until the end of the variable list is 
  8177.                           reached. If no REXX variables are left to return, 
  8178.                           RexxVariablePool sets the RXSHV_LVAR bit in shvret. 
  8179.  
  8180.            RXSHV_EXIT     Set a return value for an external function or system 
  8181.                           exit call. RXSHV_EXIT is valid only from external 
  8182.                           functions or system exit events that return a string 
  8183.                           value. An external function or exit handler can use 
  8184.                           RXSHV_EXIT only once. 
  8185.  
  8186.  shvret    Individual shared variable request return code. shvret is a 1-byte 
  8187.            field of status flags for the individual shared variable request. 
  8188.            The shvret fields for all request blocks in the list are ORed 
  8189.            together to form the RexxVariablePool return code. The individual 
  8190.            status conditions are: 
  8191.  
  8192.            RXSHV_OK 
  8193.                           The request was processed without error (all flag 
  8194.                           bits are FALSE). 
  8195.  
  8196.            RXSHV_NEWV 
  8197.                           The named variable was uninitialized at the time of 
  8198.                           the call. 
  8199.  
  8200.            RXSHV_LVAR 
  8201.                           No more variables are available for an RXSHV_NEXTV 
  8202.                           operation. 
  8203.  
  8204.            RXSHV_TRUNC 
  8205.                           A variable value or variable name was truncated 
  8206.                           because the supplied RXSTRING was too small for the 
  8207.                           copied value. 
  8208.  
  8209.            RXSHV_BADN 
  8210.                           The variable name specified in shvname was invalid 
  8211.                           for the requested operation. 
  8212.  
  8213.            RXSHV_MEMFL 
  8214.                           The REXX interpreter was unable to obtain the storage 
  8215.                           required to complete the request. 
  8216.  
  8217.            RXSHV_BADF 
  8218.                           The shared variable request block contains an invalid 
  8219.                           function code. 
  8220.  
  8221.  The REXX interpreter processes each request block in the order provided; 
  8222.  RexxVariablePool returns to the caller after the last block is processed or 
  8223.  after a severe error (such as an out-of-memory condition). 
  8224.  
  8225.  The RexxVariablePool function return code is a composite return code for the 
  8226.  entire set of shared variable requests. The return codes for all of the 
  8227.  individual requests are ORed together to form the composite return code. 
  8228.  Individual shared variable request return codes are returned in the request 
  8229.  shared variable blocks. 
  8230.  
  8231.  
  8232. ΓòÉΓòÉΓòÉ 10.7.3.1.3. RexxVariablePool - Returns ΓòÉΓòÉΓòÉ
  8233.  
  8234. The RexxVariablePool return values are: 
  8235.  
  8236.  0 to 127 
  8237.            RexxVariablePool has processed the entire shared variable request 
  8238.            block list. 
  8239.  
  8240.            The RexxVariablePool function return code is a composite return code 
  8241.            for the entire set of shared variable requests. The low-order 6 bits 
  8242.            of the shvret fields for all request blocks are ORed together to 
  8243.            form the composite return code. Individual shared variable request 
  8244.            status flags are returned in the shared variable request block 
  8245.            shvret field. 
  8246.  
  8247.  RXSHV_NOAVL 
  8248.            The variable pool interface was not enabled when call was issued. 
  8249.  
  8250.  
  8251. ΓòÉΓòÉΓòÉ 10.7.3.1.4. RexxVariablePool - Example ΓòÉΓòÉΓòÉ
  8252.  
  8253. The following is a sample call to RexxVariablePool: 
  8254.  
  8255.  
  8256. Sample call to RexxVariablePool
  8257.  
  8258. /*********************************************************************/
  8259. /*                                                                   */
  8260. /* SetRexxVariable - Set the value of a REXX variable                */
  8261. /*                                                                   */
  8262. /*********************************************************************/
  8263. INT SetRexxVariable(
  8264.   PSZ        name,                     /* REXX variable to set       */
  8265.   PSZ        value)                    /* value to assign            */
  8266. {
  8267.   SHVBLOCK   block;                    /* variable pool control block*/
  8268.   block.shvcode = RXSHV_SYSET;         /* do a symbolic set operation*/
  8269.   block.shvret=(UCHAR)0;               /* clear return code field    */
  8270.   block.shvnext=(PSHVBLOCK)0;          /* no next block              */
  8271.                                        /* set variable name string   */
  8272.   MAKERXSTRING(block.shvname, name, strlen(name));
  8273.                                        /* set value string           */
  8274.   MAKERXSTRING(block.shvvalue, value, strlen(value));
  8275.   block.shvvaluelen=strlen(value);     /* set value length           */
  8276.   return RexxVariablePool(&block);     /* set the variable           */
  8277. }
  8278.  
  8279.  
  8280. ΓòÉΓòÉΓòÉ 10.8. Queue Interface ΓòÉΓòÉΓòÉ
  8281.  
  8282. Application programs can use the REXX Queue Interface to establish and 
  8283. manipulate named queues. Named queues prevent different REXX programs that are 
  8284. running in a single session from interfering with each other. Named queues also 
  8285. allow REXX programs running in different sessions to synchronize execution and 
  8286. pass data. These queuing services are entirely separate from the OS/2 
  8287. Inter-Process Communications queues. 
  8288.  
  8289. Note:  See the Object REXX Reference for more information about named and 
  8290.        unnamed queues. 
  8291.  
  8292.  
  8293. ΓòÉΓòÉΓòÉ 10.8.1. Queue Interface Functions ΓòÉΓòÉΓòÉ
  8294.  
  8295. The functions for creating and using named queues are: 
  8296.  
  8297.       RexxCreateQueue 
  8298.       RexxDeleteQueue 
  8299.       RexxQueryQueue 
  8300.       RexxAddQueue 
  8301.       RexxPullQueue 
  8302.  
  8303.  
  8304. ΓòÉΓòÉΓòÉ 10.8.1.1. RexxCreateQueue ΓòÉΓòÉΓòÉ
  8305.  
  8306. RexxCreateQueue creates a new (empty) queue. 
  8307.  
  8308. Topics: 
  8309.  
  8310.      Syntax 
  8311.  
  8312.      Parameters 
  8313.  
  8314.      Returns 
  8315.  
  8316.      Remarks 
  8317.  
  8318.  
  8319. ΓòÉΓòÉΓòÉ 10.8.1.1.1. RexxCreateQueue - Syntax ΓòÉΓòÉΓòÉ
  8320.  
  8321. RexxCreateQueue(Buffer, BuffLen, RequestedName, DupFlag)
  8322.  
  8323.  
  8324. ΓòÉΓòÉΓòÉ 10.8.1.1.2. RexxCreateQueue - Parameters ΓòÉΓòÉΓòÉ
  8325.  
  8326.  Buffer (PSZ) - input 
  8327.            Address of the buffer where the ASCIIZ name of the created queue is 
  8328.            returned. 
  8329.  
  8330.  BuffLen  (ULONG) - input 
  8331.            Size of the buffer. 
  8332.  
  8333.  RequestedName  (PSZ) - input 
  8334.            Address of an ASCIIZ queue name. If no queue of that name already 
  8335.            exists, a queue is created with the requested name. If the name 
  8336.            already exists, a queue is still created; however, REXX chooses an 
  8337.            arbitrary name for the queue. In addition, the DupFlag is set. 
  8338.  
  8339.            When RequestedName is NULL, REXX provides a name for the created 
  8340.            queue. 
  8341.  
  8342.            In all cases, the actual queue name is passed back to the caller. 
  8343.  
  8344.  DupFlag  (PULONG) - output 
  8345.            Duplicate name indicator. This flag is set when the requested name 
  8346.            already exists. 
  8347.  
  8348.  
  8349. ΓòÉΓòÉΓòÉ 10.8.1.1.3. RexxCreateQueue - Returns ΓòÉΓòÉΓòÉ
  8350.  
  8351. The RexxCreateQueue return values are: 
  8352.  
  8353. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8354.  0      RXQUEUE_OK                    The queue function has completed
  8355.                                       successfully.
  8356.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8357.  1      RXQUEUE_STORAGE               The name buffer is not large
  8358.                                       enough for the queue name.
  8359.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8360.  5      RXQUEUE_BADQNAME              The queue name is not valid, or
  8361.                                       you tried to create or delete a
  8362.                                       queue named "SESSION."
  8363. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8364.  
  8365.  
  8366. ΓòÉΓòÉΓòÉ 10.8.1.1.4. RexxCreateQueue - Remarks ΓòÉΓòÉΓòÉ
  8367.  
  8368. Queue names must conform to the same syntax rules as for REXX variable names. 
  8369. Lower case characters in queue names are translated to upper case. 
  8370.  
  8371. The queue name must be a valid REXX symbol. However, there is no connection 
  8372. between queue names and variable names. A program can have a variable and a 
  8373. queue with a common name. 
  8374.  
  8375.  
  8376. ΓòÉΓòÉΓòÉ 10.8.1.2. RexxDeleteQueue ΓòÉΓòÉΓòÉ
  8377.  
  8378. RexxDeleteQueue deletes a queue. 
  8379.  
  8380. Topics: 
  8381.  
  8382.      Syntax 
  8383.  
  8384.      Parameters 
  8385.  
  8386.      Returns 
  8387.  
  8388.      Remarks 
  8389.  
  8390.  
  8391. ΓòÉΓòÉΓòÉ 10.8.1.2.1. RexxDeleteQueue - Syntax ΓòÉΓòÉΓòÉ
  8392.  
  8393. RexxDeleteQueue(QueueName)
  8394.  
  8395.  
  8396. ΓòÉΓòÉΓòÉ 10.8.1.2.2. RexxDeleteQueue - Parameters ΓòÉΓòÉΓòÉ
  8397.  
  8398.  QueueName (PSZ) - input 
  8399.            Address of the ASCIIZ name of the queue to be deleted. 
  8400.  
  8401.  
  8402. ΓòÉΓòÉΓòÉ 10.8.1.2.3. RexxDeleteQueue - Returns ΓòÉΓòÉΓòÉ
  8403.  
  8404. The RexxDeleteQueue return values are: 
  8405.  
  8406. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8407.  0      RXQUEUE_OK                    The queue function has completed
  8408.                                       successfully.
  8409.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8410.  5      RXQUEUE_BADQNAME              The queue name is not valid, or
  8411.                                       you tried to create or delete a
  8412.                                       queue named "SESSION."
  8413.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8414.  9      RXQUEUE_NOTREG                The queue does not exist.
  8415.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8416.  10     RXQUEUE_ACCESS                The queue cannot be deleted
  8417.                                       because it is busy.
  8418. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8419.  
  8420.  
  8421. ΓòÉΓòÉΓòÉ 10.8.1.2.4. RexxDeleteQueue - Remarks ΓòÉΓòÉΓòÉ
  8422.  
  8423. If a queue is busy (for example, wait is active), it is not deleted. 
  8424.  
  8425.  
  8426. ΓòÉΓòÉΓòÉ 10.8.1.3. RexxQueryQueue ΓòÉΓòÉΓòÉ
  8427.  
  8428. RexxQueryQueue returns the number of entries remaining in the named queue. 
  8429.  
  8430. Topics: 
  8431.  
  8432.      Syntax 
  8433.  
  8434.      Parameters 
  8435.  
  8436.      Returns 
  8437.  
  8438.  
  8439. ΓòÉΓòÉΓòÉ 10.8.1.3.1. RexxQueryQueue - Syntax ΓòÉΓòÉΓòÉ
  8440.  
  8441. RexxQueryQueue(QueueName, Count)
  8442.  
  8443.  
  8444. ΓòÉΓòÉΓòÉ 10.8.1.3.2. RexxQueryQueue - Parameters ΓòÉΓòÉΓòÉ
  8445.  
  8446.  QueueName (PSZ) - input 
  8447.            Address of the ASCIIZ name of the queue to query. 
  8448.  
  8449.  Count (PULONG) - output 
  8450.            Number of entries in the queue. 
  8451.  
  8452.  
  8453. ΓòÉΓòÉΓòÉ 10.8.1.3.3. RexxQueryQueue - Returns ΓòÉΓòÉΓòÉ
  8454.  
  8455. The RexxQueryQueue return values are: 
  8456.  
  8457. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8458.  0      RXQUEUE_OK                    The queue function has completed
  8459.                                       successfully.
  8460.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8461.  5      RXQUEUE_BADQNAME              The queue name is not valid, or
  8462.                                       you tried to create or delete a
  8463.                                       queue named "SESSION."
  8464.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8465.  9      RXQUEUE_NOTREG                The queue does not exist.
  8466. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8467.  
  8468.  
  8469. ΓòÉΓòÉΓòÉ 10.8.1.4. RexxAddQueue ΓòÉΓòÉΓòÉ
  8470.  
  8471. RexxAddQueue adds an entry into a queue. 
  8472.  
  8473. Topics: 
  8474.  
  8475.      Syntax 
  8476.  
  8477.      Parameters 
  8478.  
  8479.      Returns 
  8480.  
  8481.  
  8482. ΓòÉΓòÉΓòÉ 10.8.1.4.1. RexxAddQueue - Syntax ΓòÉΓòÉΓòÉ
  8483.  
  8484. RexxAddQueue(QueueName, EntryData, AddFlag)
  8485.  
  8486.  
  8487. ΓòÉΓòÉΓòÉ 10.8.1.4.2. RexxAddQueue - Parameters ΓòÉΓòÉΓòÉ
  8488.  
  8489.  QueueName (PSZ) - input 
  8490.            Address of the ASCIIZ name of the queue to which data is to be 
  8491.            added. 
  8492.  
  8493.  EntryData  (PRXSTRING) - input 
  8494.            Address of an RXSTRING containing the data to be added to the queue. 
  8495.  
  8496.  AddFlag  (ULONG) - input 
  8497.            LIFO/FIFO flag. When AddFlag is RXQUEUE_LIFO, data is added LIFO 
  8498.            (Last In, First Out) to the queue. When AddFlag is RXQUEUE_FIFO, 
  8499.            data is added FIFO (First In, First Out). 
  8500.  
  8501.  
  8502. ΓòÉΓòÉΓòÉ 10.8.1.4.3. RexxAddQueue - Returns ΓòÉΓòÉΓòÉ
  8503.  
  8504. The RexxAddQueue return values are: 
  8505.  
  8506. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8507.  0      RXQUEUE_OK                    The queue function has completed
  8508.                                       successfully.
  8509.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8510.  5      RXQUEUE_BADQNAME              The queue name is not valid, or
  8511.                                       you tried to create or delete a
  8512.                                       queue named "SESSION."
  8513.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8514.  6      RXQUEUE_PRIORITY              The order flag is not equal to
  8515.                                       RXQUEUE_LIFO or RXQUEUE_FIFO.
  8516.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8517.  9      RXQUEUE_NOTREG                The queue does not exist.
  8518.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8519.  12     RXQUEUE_MEMFAIL               There is insufficient memory
  8520.                                       available to complete the
  8521.                                       request.
  8522. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8523.  
  8524.  
  8525. ΓòÉΓòÉΓòÉ 10.8.1.5. RexxPullQueue ΓòÉΓòÉΓòÉ
  8526.  
  8527. RexxPullQueue removes the top entry from the queue and returns it to the 
  8528. caller. 
  8529.  
  8530. Topics: 
  8531.  
  8532.      Syntax 
  8533.  
  8534.      Parameters 
  8535.  
  8536.      Returns 
  8537.  
  8538.      Remarks 
  8539.  
  8540.  
  8541. ΓòÉΓòÉΓòÉ 10.8.1.5.1. RexxPullQueue - Syntax ΓòÉΓòÉΓòÉ
  8542.  
  8543. RexxPullQueue(QueueName, DataBuf, DateTime, WaitFlag)
  8544.  
  8545.  
  8546. ΓòÉΓòÉΓòÉ 10.8.1.5.2. RexxPullQueue - Parameters ΓòÉΓòÉΓòÉ
  8547.  
  8548.  QueueName (PSZ) - input 
  8549.            Address of the ASCIIZ name of the queue from which data is to be 
  8550.            pulled. 
  8551.  
  8552.  DataBuf  (PRXSTRING) - output 
  8553.            Address of an RXSTRING for the returned value. 
  8554.  
  8555.  DateTime  (PDATETIME) - output 
  8556.            Address of the entry's date/time stamp. 
  8557.  
  8558.  WaitFlag  (ULONG) - input 
  8559.            Wait flag. When WaitFlag is RXQUEUE_NOWAIT and the queue is empty, 
  8560.            RXQUEUE_EMPTY is returned. Otherwise, that is, WaitFlag is 
  8561.            RXQUEUE_WAIT, REXX waits until a queue entry is available and 
  8562.            returns that entry to the caller. 
  8563.  
  8564.  
  8565. ΓòÉΓòÉΓòÉ 10.8.1.5.3. RexxPullQueue - Returns ΓòÉΓòÉΓòÉ
  8566.  
  8567. The RexxPullQueue return values are: 
  8568.  
  8569. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8570.  0      RXQUEUE_OK                    The queue function has completed
  8571.                                       successfully.
  8572.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8573.  5      RXQUEUE_BADQNAME              The queue name is not valid, or
  8574.                                       you tried to create or delete a
  8575.                                       queue named "SESSION."
  8576.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8577.  7      RXQUEUE_BADWAITFLAG           The wait flag is not equal to
  8578.                                       RXQUEUE_WAIT or RXQUEUE_NOWAIT.
  8579.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8580.  8      RXQUEUE_EMPTY                 Attempted to pull the item off
  8581.                                       the queue but it was empty.
  8582.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8583.  9      RXQUEUE_NOTREG                The queue does not exist.
  8584.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8585.  12     RXQUEUE_MEMFAIL               There is insufficient memory
  8586.                                       available to complete the
  8587.                                       request.
  8588. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8589.  
  8590.  
  8591. ΓòÉΓòÉΓòÉ 10.8.1.5.4. RexxPullQueue - Remarks ΓòÉΓòÉΓòÉ
  8592.  
  8593. The caller is responsible for freeing the returned memory pointed to by DataBuf 
  8594.  
  8595.  
  8596. ΓòÉΓòÉΓòÉ 10.8.2. Queue Interface Returns ΓòÉΓòÉΓòÉ
  8597.  
  8598. The return codes for the Queue Interface are as follows: 
  8599.  
  8600. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8601.  0      RXQUEUE_OK                    The queue function has completed
  8602.                                       successfully.
  8603.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8604.  1      RXQUEUE_STORAGE               The name buffer is not large
  8605.                                       enough for the queue name.
  8606.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8607.  5      RXQUEUE_BADQNAME              The queue name is not valid, or
  8608.                                       you tried to create or delete a
  8609.                                       queue named "SESSION."
  8610.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8611.  6      RXQUEUE_PRIORITY              The order flag is not equal to
  8612.                                       RXQUEUE_LIFO or RXQUEUE_FIFO.
  8613.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8614.  7      RXQUEUE_BADWAITFLAG           The wait flag is not equal to
  8615.                                       RXQUEUE_WAIT or RXQUEUE_NOWAIT.
  8616.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8617.  8      RXQUEUE_EMPTY                 Attempted to pull the item off
  8618.                                       the queue but it was empty.
  8619.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8620.  9      RXQUEUE_NOTREG                The queue does not exist.
  8621.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8622.  10     RXQUEUE_ACCESS                The queue cannot be deleted
  8623.                                       because it is busy.
  8624.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8625.  12     RXQUEUE_MEMFAIL               There is insufficient memory
  8626.                                       available to complete the
  8627.                                       request.
  8628. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8629.  
  8630.  
  8631. ΓòÉΓòÉΓòÉ 10.9. Halt and Trace Interface ΓòÉΓòÉΓòÉ
  8632.  
  8633. The halt and trace functions raise a REXX HALT condition or change the REXX 
  8634. interactive debug mode while a REXX procedure is running. These interfaces may 
  8635. be preferred over the RXHLT and RXTRC system exits. The system exits require an 
  8636. additional call to an exit routine after each REXX instruction completes. This 
  8637. might cause a noticeable performance degradation. The halt and trace functions 
  8638. are a single request to change the halt or trace state and do not degrade the 
  8639. REXX procedure performance. 
  8640.  
  8641.  
  8642. ΓòÉΓòÉΓòÉ 10.9.1. Halt and Trace Interface Functions ΓòÉΓòÉΓòÉ
  8643.  
  8644. The Halt and Trace functions include: 
  8645.  
  8646.       RexxSetHalt 
  8647.       RexxSetTrace 
  8648.       RexxResetTrace 
  8649.  
  8650.  
  8651. ΓòÉΓòÉΓòÉ 10.9.1.1. RexxSetHalt ΓòÉΓòÉΓòÉ
  8652.  
  8653. RexxSetHalt raises a HALT condition in a running REXX program. 
  8654.  
  8655. Topics: 
  8656.  
  8657.      Syntax 
  8658.  
  8659.      Parameters 
  8660.  
  8661.      Returns 
  8662.  
  8663.      Remarks 
  8664.  
  8665.  
  8666. ΓòÉΓòÉΓòÉ 10.9.1.1.1. RexxSetHalt - Syntax ΓòÉΓòÉΓòÉ
  8667.  
  8668. RexxSetHalt(ProcessId, ThreadId)
  8669.  
  8670.  
  8671. ΓòÉΓòÉΓòÉ 10.9.1.1.2. RexxSetHalt - Parameters ΓòÉΓòÉΓòÉ
  8672.  
  8673.  ProcessId (PID) - input 
  8674.            The process ID of the target REXX procedure. ProcessId is the 
  8675.            application process that called the RexxStart function. 
  8676.  
  8677.  ThreadId (TID) - input 
  8678.            The thread ID of the target REXX procedure. ThreadId is the 
  8679.            application thread that called the RexxStart function. 
  8680.  
  8681.  
  8682. ΓòÉΓòÉΓòÉ 10.9.1.1.3. RexxSetHalt - Returns ΓòÉΓòÉΓòÉ
  8683.  
  8684. The RexxSetHalt return values are: 
  8685.  
  8686. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8687.  0      RXARI_OK                        The  function completed
  8688.                                         successfully.
  8689.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8690.  1      RXARI_NOT_FOUND                 The target REXX procedure was
  8691.                                         not found.
  8692.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8693.  2      RXARI_PROCESSING_ERROR          A failure in REXX processing
  8694.                                         occurred.
  8695. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8696.  
  8697.  
  8698. ΓòÉΓòÉΓòÉ 10.9.1.1.4. RexxSetHalt - Remarks ΓòÉΓòÉΓòÉ
  8699.  
  8700. This call is not processed if the target REXX program is running with the RXHLT 
  8701. exit enabled. 
  8702.  
  8703.  
  8704. ΓòÉΓòÉΓòÉ 10.9.1.2. RexxSetTrace ΓòÉΓòÉΓòÉ
  8705.  
  8706. RexxSetTrace turns on interactive debug mode for a REXX procedure. 
  8707.  
  8708. Topics: 
  8709.  
  8710.      Syntax 
  8711.  
  8712.      Parameters 
  8713.  
  8714.      Returns 
  8715.  
  8716.      Remarks 
  8717.  
  8718.  
  8719. ΓòÉΓòÉΓòÉ 10.9.1.2.1. RexxSetTrace - Syntax ΓòÉΓòÉΓòÉ
  8720.  
  8721. RexxSetTrace(ProcessId, ThreadId)
  8722.  
  8723.  
  8724. ΓòÉΓòÉΓòÉ 10.9.1.2.2. RexxSetTrace - Parameters ΓòÉΓòÉΓòÉ
  8725.  
  8726.  ProcessId (PID) - input 
  8727.            The process ID of the target REXX procedure. ProcessId is the 
  8728.            application process that called the RexxStart function. 
  8729.  
  8730.  ThreadId (TID) - input 
  8731.            The thread ID of the target REXX procedure. ThreadId is the 
  8732.            application thread that called the RexxStart function. 
  8733.  
  8734.  
  8735. ΓòÉΓòÉΓòÉ 10.9.1.2.3. RexxSetTrace - Returns ΓòÉΓòÉΓòÉ
  8736.  
  8737. The RexxSetTrace return values are: 
  8738.  
  8739. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8740.  0      RXARI_OK                        The  function completed
  8741.                                         successfully.
  8742.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8743.  1      RXARI_NOT_FOUND                 The target REXX procedure was
  8744.                                         not found.
  8745.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8746.  2      RXARI_PROCESSING_ERROR          A failure in REXX processing
  8747.                                         occurred.
  8748. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8749.  
  8750.  
  8751. ΓòÉΓòÉΓòÉ 10.9.1.2.4. RexxSetTrace - Remarks ΓòÉΓòÉΓòÉ
  8752.  
  8753. A RexxSetTrace call is not processed if the REXX procedure is using the RXTRC 
  8754. exit. 
  8755.  
  8756.  
  8757. ΓòÉΓòÉΓòÉ 10.9.1.3. RexxResetTrace ΓòÉΓòÉΓòÉ
  8758.  
  8759. RexxResetTrace turns off interactive debug mode for a REXX procedure. 
  8760.  
  8761. Topics: 
  8762.  
  8763.      Syntax 
  8764.  
  8765.      Parameters 
  8766.  
  8767.      Returns 
  8768.  
  8769.      Remarks 
  8770.  
  8771.  
  8772. ΓòÉΓòÉΓòÉ 10.9.1.3.1. RexxResetTrace - Syntax ΓòÉΓòÉΓòÉ
  8773.  
  8774. RexxResetTrace(ProcessId,ThreadId)
  8775.  
  8776.  
  8777. ΓòÉΓòÉΓòÉ 10.9.1.3.2. RexxResetTrace - Parameters ΓòÉΓòÉΓòÉ
  8778.  
  8779.  ProcessId (PID) - input 
  8780.            The process ID of the target REXX procedure. ProcessId is the 
  8781.            application process that called the RexxStart function. 
  8782.  
  8783.  ThreadId (TID) - input 
  8784.            The thread ID of the target REXX procedure. ThreadId is the 
  8785.            application thread that called the RexxStart function. 
  8786.  
  8787.  
  8788. ΓòÉΓòÉΓòÉ 10.9.1.3.3. RexxResetTrace - Returns ΓòÉΓòÉΓòÉ
  8789.  
  8790. The RexxResetTrace return values are: 
  8791.  
  8792. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8793.  0      RXARI_OK                        The  function completed
  8794.                                         successfully.
  8795.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8796.  1      RXARI_NOT_FOUND                 The target REXX procedure was
  8797.                                         not found.
  8798.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8799.  2      RXARI_PROCESSING_ERROR          A failure in REXX processing
  8800.                                         occurred.
  8801. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8802.  
  8803.  
  8804. ΓòÉΓòÉΓòÉ 10.9.1.3.4. RexxResetTrace - Remarks ΓòÉΓòÉΓòÉ
  8805.  
  8806. A RexxResetTrace call is not processed if the REXX procedure is using the RXTRC 
  8807. exit. 
  8808.  
  8809. Interactive debug is not turned off unless interactive debug mode was 
  8810. originally started with RexxSetTrace. 
  8811.  
  8812.  
  8813. ΓòÉΓòÉΓòÉ 10.9.2. Halt and Trace Returns ΓòÉΓòÉΓòÉ
  8814.  
  8815. The return codes for the halt and trace functions are as follows: 
  8816.  
  8817. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8818.  0      RXARI_OK                        The  function completed
  8819.                                         successfully.
  8820.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8821.  1      RXARI_NOT_FOUND                 The target REXX procedure was
  8822.                                         not found.
  8823.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8824.  2      RXARI_PROCESSING_ERROR          A failure in REXX processing
  8825.                                         occurred.
  8826. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8827.  
  8828.  
  8829. ΓòÉΓòÉΓòÉ 10.10. Macrospace Interface ΓòÉΓòÉΓòÉ
  8830.  
  8831. The macrospace can improve the performance of REXX procedures by maintaining 
  8832. REXX procedure images in memory for immediate load and execution. This is 
  8833. useful for frequently-used procedures and functions such as editor macros. 
  8834.  
  8835. Programs registered in the REXX macrospace are available to all processes. You 
  8836. can run them by using the RexxStart function or calling them as functions or 
  8837. subroutines from other REXX procedures. 
  8838.  
  8839. Procedures in the macrospace are called the same way other REXX external 
  8840. functions are called. However, the macrospace REXX procedures can be placed at 
  8841. the front or at the very end of the external function search order. 
  8842.  
  8843. REXX procedures in the macrospace can be saved to a disk file. A saved 
  8844. macrospace file can be reloaded with a single call to RexxLoadMacroSpace. An 
  8845. application, such as an editor, can create its own library of frequently-used 
  8846. functions and load the entire library into memory for fast access. Multiple 
  8847. macrospace libraries may be created and loaded. 
  8848.  
  8849.  
  8850. ΓòÉΓòÉΓòÉ 10.10.1. Search Order ΓòÉΓòÉΓòÉ
  8851.  
  8852. When RexxAddMacro loads a REXX procedure into the macrospace, the position in 
  8853. the external function search order is specified. The REXX procedure may be 
  8854. placed before all other forms of external function or after all other external 
  8855. functions. 
  8856.  
  8857.  RXMACRO_SEARCH_BEFORE The REXX interpreter locates a function registered with 
  8858.            RXMACRO_SEARCH_BEFORE before any registered functions or external 
  8859.            REXX files. 
  8860.  
  8861.  RXMACRO_SEARCH_AFTER The REXX interpreter locates a function registered with 
  8862.            RXMACRO_SEARCH_AFTER after any registered functions or external REXX 
  8863.            files. 
  8864.  
  8865.  
  8866. ΓòÉΓòÉΓòÉ 10.10.2. Storage of Macrospace Libraries ΓòÉΓòÉΓòÉ
  8867.  
  8868. The REXX macrospace is placed in shared memory. Only the amount of memory and 
  8869. swap space available to the system limits the size of the macrospace. However, 
  8870. as the macrospace grows, it limits the memory available to other processes in 
  8871. the system. Allowing the macrospace to grow too large may degrade overall 
  8872. system performance due to increased system swap file access. Try to place only 
  8873. the most frequently-used functions in the macrospace. 
  8874.  
  8875.  
  8876. ΓòÉΓòÉΓòÉ 10.10.3. Macrospace Interface Functions ΓòÉΓòÉΓòÉ
  8877.  
  8878. The functions to manipulate macrospaces are: 
  8879.  
  8880.       RexxAddMacro 
  8881.       RexxDropMacro 
  8882.       RexxClearMacroSpace 
  8883.       RexxSaveMacroSpace 
  8884.       RexxLoadMacroSpace 
  8885.       RexxQueryMacro 
  8886.       RexxReorderMacro 
  8887.  
  8888.  
  8889. ΓòÉΓòÉΓòÉ 10.10.3.1. RexxAddMacro ΓòÉΓòÉΓòÉ
  8890.  
  8891. RexxAddMacro loads a REXX procedure into the macrospace. 
  8892.  
  8893. Topics: 
  8894.  
  8895.      Syntax 
  8896.  
  8897.      Parameters 
  8898.  
  8899.      Returns 
  8900.  
  8901.  
  8902. ΓòÉΓòÉΓòÉ 10.10.3.1.1. RexxAddMacro - Syntax ΓòÉΓòÉΓòÉ
  8903.  
  8904. RexxAddMacro(FuncName, SourceFile, Position)
  8905.  
  8906.  
  8907. ΓòÉΓòÉΓòÉ 10.10.3.1.2. RexxAddMacro - Parameters ΓòÉΓòÉΓòÉ
  8908.  
  8909.  FuncName (PSZ) - input 
  8910.            Address of the ASCIIZ function name. REXX procedures in the 
  8911.            macrospace are called using the assigned function name. 
  8912.  
  8913.  SourceFile (PSZ) - input 
  8914.            Address of the ASCIIZ file specification for the REXX procedure 
  8915.            source file. When a file extension is not supplied,.CMD is used. 
  8916.            When the full path is not specified, the current directory and path 
  8917.            is searched. 
  8918.  
  8919.  Position (ULONG) - input 
  8920.            Position in the REXX external function search order. Possible values 
  8921.            are: 
  8922.  
  8923.            RXMACRO_SEARCH_BEFORE 
  8924.                           The REXX interpreter locates the function before any 
  8925.                           registered functions or external REXX files. 
  8926.  
  8927.            RXMACRO_SEARCH_AFTER 
  8928.                           The REXX interpreter locates the function after any 
  8929.                           registered functions or external REXX files. 
  8930.  
  8931.  
  8932. ΓòÉΓòÉΓòÉ 10.10.3.1.3. RexxAddMacro - Returns ΓòÉΓòÉΓòÉ
  8933.  
  8934. The RexxAddMacro return values are: 
  8935.  
  8936. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8937.  0      RXMACRO_OK                           The call to the function
  8938.                                              completed successfully.
  8939.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8940.  1      RXMACRO_NO_STORAGE                   There was not enough
  8941.                                              memory to complete the
  8942.                                              requested function.
  8943.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8944.  7      RXMACRO_SOURCE_NOT_FOUND             The requested file was not
  8945.                                              found.
  8946.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8947.  8      RXMACRO_INVALID_POSITION             An invalid search-order
  8948.                                              position request flag was
  8949.                                              used.
  8950. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8951.  
  8952.  
  8953. ΓòÉΓòÉΓòÉ 10.10.3.2. RexxDropMacro ΓòÉΓòÉΓòÉ
  8954.  
  8955. RexxDropMacro removes a REXX procedure from the macrospace. 
  8956.  
  8957. Topics: 
  8958.  
  8959.      Syntax 
  8960.  
  8961.      Parameters 
  8962.  
  8963.      Returns 
  8964.  
  8965.  
  8966. ΓòÉΓòÉΓòÉ 10.10.3.2.1. RexxDropMacro - Syntax ΓòÉΓòÉΓòÉ
  8967.  
  8968. RexxDropMacro(FuncName)
  8969.  
  8970.  
  8971. ΓòÉΓòÉΓòÉ 10.10.3.2.2. RexxDropMacro - Parameters ΓòÉΓòÉΓòÉ
  8972.  
  8973.  FuncName (PSZ) - input 
  8974.            Address of the ASCIIZ function name. 
  8975.  
  8976.  
  8977. ΓòÉΓòÉΓòÉ 10.10.3.2.3. RexxDropMacro - Returns ΓòÉΓòÉΓòÉ
  8978.  
  8979. The RexxDropMacro return values are: 
  8980.  
  8981. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8982.  0      RXMACRO_OK                           The call to the function
  8983.                                              completed successfully.
  8984.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8985.  2      RXMACRO_NOT_FOUND                    The requested function was
  8986.                                              not found in the
  8987.                                              macrospace.
  8988. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  8989.  
  8990.  
  8991. ΓòÉΓòÉΓòÉ 10.10.3.3. RexxClearMacroSpace ΓòÉΓòÉΓòÉ
  8992.  
  8993. RexxClearMacroSpace removes all loaded REXX procedures from the macrospace. 
  8994.  
  8995. Topics: 
  8996.  
  8997.      Syntax 
  8998.  
  8999.      Returns 
  9000.  
  9001.      Remarks 
  9002.  
  9003.  
  9004. ΓòÉΓòÉΓòÉ 10.10.3.3.1. RexxClearMacroSpace - Syntax ΓòÉΓòÉΓòÉ
  9005.  
  9006. RexxClearMacroSpace()
  9007.  
  9008.  
  9009. ΓòÉΓòÉΓòÉ 10.10.3.3.2. RexxClearMacroSpace - Returns ΓòÉΓòÉΓòÉ
  9010.  
  9011. The RexxClearMacroSpace return values are: 
  9012.  
  9013. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9014.  0      RXMACRO_OK                           The call to the function
  9015.                                              completed successfully.
  9016.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9017.  2      RXMACRO_NOT_FOUND                    The requested function was
  9018.                                              not found in the
  9019.                                              macrospace.
  9020. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9021.  
  9022.  
  9023. ΓòÉΓòÉΓòÉ 10.10.3.3.3. RexxClearMacroSpace - Remarks ΓòÉΓòÉΓòÉ
  9024.  
  9025. RexxClearMacroSpace must be used with care. This function removes all functions 
  9026. from the macrospace, including functions loaded by other processes. 
  9027.  
  9028.  
  9029. ΓòÉΓòÉΓòÉ 10.10.3.4. RexxSaveMacroSpace ΓòÉΓòÉΓòÉ
  9030.  
  9031. RexxSaveMacroSpace saves all or part of the macrospace REXX procedures to a 
  9032. disk file. 
  9033.  
  9034. Topics: 
  9035.  
  9036.      Syntax 
  9037.  
  9038.      Parameters 
  9039.  
  9040.      Returns 
  9041.  
  9042.      Remarks 
  9043.  
  9044.  
  9045. ΓòÉΓòÉΓòÉ 10.10.3.4.1. RexxSaveMacroSpace - Syntax ΓòÉΓòÉΓòÉ
  9046.  
  9047. RexxSaveMacroSpace(FuncCount, FuncNames, MacroLibFile)
  9048.  
  9049.  
  9050. ΓòÉΓòÉΓòÉ 10.10.3.4.2. RexxSaveMacroSpace - Parameters ΓòÉΓòÉΓòÉ
  9051.  
  9052.  FuncCount (ULONG) - input 
  9053.            Number of REXX procedures to save. 
  9054.  
  9055.  FuncNames (PSZ *) - input 
  9056.            Address of a list of ASCIIZ function names. FuncCount gives the size 
  9057.            of the function list. 
  9058.  
  9059.  MacroLibFile (PSZ) - input 
  9060.            Address of the ASCIIZ macrospace file name. If MacroLibFile already 
  9061.            exists, it is replaced with the new file. 
  9062.  
  9063.  
  9064. ΓòÉΓòÉΓòÉ 10.10.3.4.3. RexxSaveMacroSpace - Returns ΓòÉΓòÉΓòÉ
  9065.  
  9066. The RexxSaveMacroSpace return values are: 
  9067.  
  9068. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9069.  0      RXMACRO_OK                           The call to the function
  9070.                                              completed successfully.
  9071.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9072.  2      RXMACRO_NOT_FOUND                    The requested function was
  9073.                                              not found in the
  9074.                                              macrospace.
  9075.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9076.  3      RXMACRO_EXTENSION_REQUIRED           An extension is required
  9077.                                              for the macrospace file
  9078.                                              name.
  9079.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9080.  5      RXMACRO_FILE_ERROR                   An error occurred
  9081.                                              accessing a macrospace
  9082.                                              file.
  9083. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9084.  
  9085.  
  9086. ΓòÉΓòÉΓòÉ 10.10.3.4.4. RexxSaveMacroSpace - Remarks ΓòÉΓòÉΓòÉ
  9087.  
  9088. When FuncCount is zero or FuncNames is NULL, RexxSaveMacroSpace saves all 
  9089. functions in the macrospace. 
  9090.  
  9091. Saved macrospace files can be used only with the same interpreter version that 
  9092. created the images. If RexxLoadMacroSpace is called to load a saved macrospace 
  9093. and the release level or service level is incorrect, RexxLoadMacroSpace fails. 
  9094. If RexxLoadMacroSpace fails, the REXX procedures must be reloaded individually 
  9095. from the original source programs. 
  9096.  
  9097.  
  9098. ΓòÉΓòÉΓòÉ 10.10.3.5. RexxLoadMacroSpace ΓòÉΓòÉΓòÉ
  9099.  
  9100. RexxLoadMacroSpace loads all or part of the REXX procedures from a saved 
  9101. macrospace file. 
  9102.  
  9103. Topics: 
  9104.  
  9105.      Syntax 
  9106.  
  9107.      Parameters 
  9108.  
  9109.      Returns 
  9110.  
  9111.      Remarks 
  9112.  
  9113.  
  9114. ΓòÉΓòÉΓòÉ 10.10.3.5.1. RexxLoadMacroSpace - Syntax ΓòÉΓòÉΓòÉ
  9115.  
  9116. RexxLoadMacroSpace(FuncCount, FuncNames, MacroLibFile)
  9117.  
  9118.  
  9119. ΓòÉΓòÉΓòÉ 10.10.3.5.2. RexxLoadMacroSpace - Parameters ΓòÉΓòÉΓòÉ
  9120.  
  9121.  FuncCount (ULONG) - input 
  9122.            Number of REXX procedures to load from the saved macrospace. 
  9123.  
  9124.  FuncNames (PSZ *) - input 
  9125.            Address of a list of ASCIIZ REXX function names. FuncCount gives the 
  9126.            size of the function list. 
  9127.  
  9128.  MacroLibFile (PSZ) - input 
  9129.            Address of the ASCIIZ saved macrospace file name. 
  9130.  
  9131.  
  9132. ΓòÉΓòÉΓòÉ 10.10.3.5.3. RexxLoadMacroSpace - Returns ΓòÉΓòÉΓòÉ
  9133.  
  9134. The RexxLoadMacroSpace return values are: 
  9135.  
  9136. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9137.  0      RXMACRO_OK                           The call to the function
  9138.                                              completed successfully.
  9139.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9140.  1      RXMACRO_NO_STORAGE                   There was not enough
  9141.                                              memory to complete the
  9142.                                              requested function.
  9143.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9144.  2      RXMACRO_NOT_FOUND                    The requested function was
  9145.                                              not found in the
  9146.                                              macrospace.
  9147.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9148.  4      RXMACRO_ALREADY_EXISTS               Duplicate functions cannot
  9149.                                              be loaded from a
  9150.                                              macrospace file.
  9151.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9152.  5      RXMACRO_FILE_ERROR                   An error occurred
  9153.                                              accessing a macrospace
  9154.                                              file.
  9155.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9156.  6      RXMACRO_SIGNATURE_ERROR              A macrospace save file
  9157.                                              does not contain valid
  9158.                                              function images.
  9159. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9160.  
  9161.  
  9162. ΓòÉΓòÉΓòÉ 10.10.3.5.4. RexxLoadMacroSpace - Remarks ΓòÉΓòÉΓòÉ
  9163.  
  9164. When FuncCount is zero or FuncNames is NULL, RexxLoadMacroSpace loads all REXX 
  9165. procedures from the saved file. 
  9166.  
  9167. If a RexxLoadMacroSpace call would replace an existing macrospace REXX 
  9168. procedure, the entire load request is discarded and the macrospace remains 
  9169. unchanged. 
  9170.  
  9171.  
  9172. ΓòÉΓòÉΓòÉ 10.10.3.6. RexxQueryMacro ΓòÉΓòÉΓòÉ
  9173.  
  9174. RexxQueryMacro searches the macrospace for a specified function. 
  9175.  
  9176. Topics: 
  9177.  
  9178.      Syntax 
  9179.  
  9180.      Parameters 
  9181.  
  9182.      Returns 
  9183.  
  9184.  
  9185. ΓòÉΓòÉΓòÉ 10.10.3.6.1. RexxQueryMacro - Syntax ΓòÉΓòÉΓòÉ
  9186.  
  9187. RexxQueryMacro(FuncName, Position)
  9188.  
  9189.  
  9190. ΓòÉΓòÉΓòÉ 10.10.3.6.2. RexxQueryMacro - Parameters ΓòÉΓòÉΓòÉ
  9191.  
  9192.  FuncName (PSZ) - input 
  9193.            Address of an ASCIIZ function name. 
  9194.  
  9195.  Position (PUSHORT) - output 
  9196.            Address of an unsigned short integer flag. If the function is loaded 
  9197.            in the macrospace, Position is set to the current function 
  9198.            search-order position. 
  9199.  
  9200.  
  9201. ΓòÉΓòÉΓòÉ 10.10.3.6.3. RexxQueryMacro - Returns ΓòÉΓòÉΓòÉ
  9202.  
  9203. The RexxQueryMacroSpace return values are: 
  9204.  
  9205. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9206.  0      RXMACRO_OK                           The call to the function
  9207.                                              completed successfully.
  9208.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9209.  2      RXMACRO_NOT_FOUND                    The requested function was
  9210.                                              not found in the
  9211.                                              macrospace.
  9212. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9213.  
  9214.  
  9215. ΓòÉΓòÉΓòÉ 10.10.3.7. RexxReorderMacro ΓòÉΓòÉΓòÉ
  9216.  
  9217. RexxReorderMacro changes the search order position of a loaded macrospace 
  9218. function. 
  9219.  
  9220. Topics: 
  9221.  
  9222.      Syntax 
  9223.  
  9224.      Parameters 
  9225.  
  9226.      Returns 
  9227.  
  9228.  
  9229. ΓòÉΓòÉΓòÉ 10.10.3.7.1. RexxReorderMacro - Syntax ΓòÉΓòÉΓòÉ
  9230.  
  9231. RexxReorderMacro(FuncName, Position)
  9232.  
  9233.  
  9234. ΓòÉΓòÉΓòÉ 10.10.3.7.2. RexxReorderMacro - Parameters ΓòÉΓòÉΓòÉ
  9235.  
  9236.  FuncName (PSZ) - input 
  9237.            Address of an ASCIIZ macrospace function name. 
  9238.  
  9239.  Position (ULONG) - input 
  9240.            New search-order position of the macrospace function. Possible 
  9241.            values are: 
  9242.  
  9243.            RXMACRO_SEARCH_BEFORE 
  9244.                           The REXX interpreter locates the function before any 
  9245.                           registered functions or external REXX files. 
  9246.  
  9247.            RXMACRO_SEARCH_AFTER 
  9248.                           The REXX interpreter locates the function after any 
  9249.                           registered functions or external REXX files. 
  9250.  
  9251.  
  9252. ΓòÉΓòÉΓòÉ 10.10.3.7.3. RexxReorderMacro - Returns ΓòÉΓòÉΓòÉ
  9253.  
  9254. The RexxReorderMacro return values are: 
  9255.  
  9256. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9257.  0      RXMACRO_OK                           The call to the function
  9258.                                              completed successfully.
  9259.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9260.  2      RXMACRO_NOT_FOUND                    The requested function was
  9261.                                              not found in the
  9262.                                              macrospace.
  9263.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9264.  8      RXMACRO_INVALID_POSITION             An invalid search-order
  9265.                                              position request flag was
  9266.                                              used.
  9267. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9268.  
  9269.  
  9270. ΓòÉΓòÉΓòÉ 10.10.4. Macrospace Interface Returns ΓòÉΓòÉΓòÉ
  9271.  
  9272. Return codes for the External Functions Interface are as follows.  Each code 
  9273. indicates the cause of a failure in its respective function: 
  9274.  
  9275. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9276.  0      RXMACRO_OK                           The call to the function
  9277.                                              completed successfully.
  9278.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9279.  1      RXMACRO_NO_STORAGE                   There was not enough
  9280.                                              memory to complete the
  9281.                                              requested function.
  9282.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9283.  2      RXMACRO_NOT_FOUND                    The requested function was
  9284.                                              not found in the
  9285.                                              macrospace.
  9286.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9287.  3      RXMACRO_EXTENSION_REQUIRED           An extension is required
  9288.                                              for the macrospace file
  9289.                                              name.
  9290.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9291.  4      RXMACRO_ALREADY_EXISTS               Duplicate functions cannot
  9292.                                              be loaded from a
  9293.                                              macrospace file.
  9294.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9295.  5      RXMACRO_FILE_ERROR                   An error occurred
  9296.                                              accessing a macrospace
  9297.                                              file.
  9298.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9299.  6      RXMACRO_SIGNATURE_ERROR              A macrospace save file
  9300.                                              does not contain valid
  9301.                                              function images.
  9302.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9303.  7      RXMACRO_SOURCE_NOT_FOUND             The requested file was not
  9304.                                              found.
  9305.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9306.  8      RXMACRO_INVALID_POSITION             An invalid search-order
  9307.                                              position request flag was
  9308.                                              used.
  9309. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  9310.  
  9311.  
  9312. ΓòÉΓòÉΓòÉ 10.10.4.1. Example ΓòÉΓòÉΓòÉ
  9313.  
  9314. The following is a sample of macrospace usage: 
  9315.  
  9316.  
  9317. Sample macrospace usage
  9318.  
  9319.                                        /* first load entire package  */
  9320.   RexxLoadMacroSpace(0, NULL, "EDITOR.MAC");
  9321.   for (i = 0; i < MACRO_COUNT; i++) {  /* verify each macro          */
  9322.                                        /* if not there               */
  9323.     if (RexxQueryMacro(macro╤ìiΓêÖ, &position))
  9324.                                        /* add to list                */
  9325.       RexxAddMacro(macro╤ìiΓêÖ, macro_files╤ìiΓêÖ,
  9326.           RXMACRO_SEARCH_BEFORE);
  9327.   }
  9328.                                        /* rebuild the macrospace     */
  9329.   RexxSaveMacroSpace(0, NULL, "EDITOR.MAC");
  9330. .
  9331. .
  9332. .
  9333.  
  9334.                                        /* build the argument string  */
  9335.   MAKERXSTRING(argv[0], macro_argument,
  9336.       strlen(macro_argument));
  9337.                                        /* set up default return      */
  9338.   MAKERXSTRING(retstr, return_buffer, sizeof(return_buffer));
  9339.                                        /* set up for macrospace call */
  9340.   MAKERXSTRING(macrospace[0],NULL, 0);
  9341.   MAKERXSTRING(macrospace[1],NULL, 0);
  9342.   return_code = RexxStart(1,           /* one argument               */
  9343.                           argv,        /* argument array             */
  9344.                           macro[pos],  /* REXX procedure name        */
  9345.                           macrospace,  /* use macrospace version     */
  9346.                           "Editor",    /* default address name       */
  9347.                           RXCOMMAND,   /* calling as a subcommand    */
  9348.                           NULL,        /* no exits used              */
  9349.                           &rc,         /* converted return code      */
  9350.                           &retstr);    /* returned result            */
  9351.  
  9352.  
  9353. ΓòÉΓòÉΓòÉ 11. Sample REXX Programs ΓòÉΓòÉΓòÉ
  9354.  
  9355. The following sample programs are included with REXX as .CMD files. Using the 
  9356. online version of this guide, you can view these samples from the OS/2 Toolkit 
  9357. REXX Samples directory. To view a sample REXX program, click on a highlighted 
  9358. program name. The command file will be displayed using the OS/2 system editor. 
  9359.  
  9360.  CCREPLY.CMD A concurrent programming example. 
  9361.  
  9362.      This program demonstrates how to use reply to run two methods at the same 
  9363.      time. 
  9364.  
  9365.  COMPLEX.CMD A complex number class. 
  9366.  
  9367.      This program demonstrates how to create a complex number class using the 
  9368.      ::CLASS and ::METHOD directives. An example of subclassing the complex 
  9369.      number class (the Vector subclass) is also shown. Finally, the Stringlike 
  9370.      class demonstrates the use of a mixin to provide some string behavior to 
  9371.      the complex number class. 
  9372.  
  9373.  FACTOR.CMD A factorial program. 
  9374.  
  9375.      This program demonstrates a way to define a factorial class using the 
  9376.      subclass method and the .methods environment symbol. 
  9377.  
  9378.  GREPLY.CMD An example contrasting the GUARDED and UNGUARDED methods. 
  9379.  
  9380.      This program demonstrates the difference between GUARDED and UNGUARDED 
  9381.      methods with respect to their use of the object variable pool. 
  9382.  
  9383.  GUESS.CMD An animal guessing game. 
  9384.  
  9385.      This sample creates a simple node class and uses it to create a logic 
  9386.      tree. The logic tree is filled in by playing a simple guessing game. 
  9387.  
  9388.  KTGUARD.CMD A GUARD instruction example. 
  9389.  
  9390.      This program demonstrates the use of the START method and the GUARD 
  9391.      instruction to control the running of several programs. In this sample, 
  9392.      the programs are controlled by one 'guarded' variable. 
  9393.  
  9394.  MONTH.CMD An example that displays the days of the month for January 1994. 
  9395.  
  9396.      This program is similar to the MONTH1.CMD exec found in the OS/2 2.0 REXX 
  9397.      User's Guide. This version demonstrates the use of arrays to replace 
  9398.      stems. 
  9399.  
  9400.  PIPE.CMD A pipeline implementation. 
  9401.  
  9402.      This program demonstrates the use of ::CLASS and ::METHOD directives to 
  9403.      create a simple implementation of a CMS-like pipeline function. 
  9404.  
  9405.  QDATE.CMD An example that types/pushes today's date and moon phase, in 
  9406.      English. 
  9407.  
  9408.  QTIME.CMD An example that lays or stacks time in real English, and also 
  9409.      chimes. 
  9410.  
  9411.  SEMCLS.CMD An Object REXX semaphore class. 
  9412.  
  9413.      This file implements a semaphore class in Object REXX. 
  9414.  
  9415.  STACK.CMD A stack class. 
  9416.  
  9417.      This program demonstrates how to implement a stack class using ::CLASS and 
  9418.      ::METHOD directives. Also included is a short example of the use of a 
  9419.      stack. 
  9420.  
  9421.  USECOMP.CMD A simple demonstration of the complex number class. 
  9422.  
  9423.      This program demonstrates use of the ::REQUIRES directive, using the 
  9424.      complex number class included in the samples. 
  9425.  
  9426.  USEPIPE.CMD Sample uses of the pipe implementation in PIPE.CMD. 
  9427.  
  9428.      This program demonstrates how you could use the pipes implemented in the 
  9429.      pipe sample. 
  9430.  
  9431.  
  9432. ΓòÉΓòÉΓòÉ 12. Notices ΓòÉΓòÉΓòÉ
  9433.  
  9434. August 1996 
  9435.  
  9436. The following paragraph does not apply to the United Kingdom or any country 
  9437. where such provisions are inconsistent with local law:  INTERNATIONAL BUSINESS 
  9438. MACHINES CORPORATION PROVIDES THIS PUBLICATION, INCLUDING ANY SAMPLE 
  9439. APPLICATION PROGRAMS, "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR 
  9440. IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  9441. MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow 
  9442. disclaimer of express or implied warranties in certain transactions, therefore, 
  9443. this statement may not apply to you. 
  9444.  
  9445. This publication could include technical inaccuracies or typographical errors. 
  9446. Changes are periodically made to the information herein; these changes will be 
  9447. incorporated in new editions of the publication. IBM may make improvements 
  9448. and/or changes in the product(s) and/or the program(s) described in this 
  9449. publication at any time. 
  9450.  
  9451. It is possible that this publication may contain reference to, or information 
  9452. about, IBM products (machines and programs), programming, or services that are 
  9453. not announced in your country.  Such references or information must not be 
  9454. construed to mean that IBM intends to announce such IBM products, programming, 
  9455. or services in your country. 
  9456.  
  9457. Requests for technical information about IBM products should be made to your 
  9458. IBM authorized reseller or IBM marketing representative. 
  9459.  
  9460.  
  9461. ΓòÉΓòÉΓòÉ 12.1. Copyright Notices ΓòÉΓòÉΓòÉ
  9462.  
  9463. COPYRIGHT LICENSE: This publication contains printed sample application 
  9464. programs in source language, which illustrate OS/2 programming techniques. You 
  9465. may copy, modify, and distribute these sample programs in any form without 
  9466. payment to IBM, for the purposes of developing, using, marketing or 
  9467. distributing application programs conforming to the OS/2 application 
  9468. programming interface. 
  9469.  
  9470. (C) Copyright International Business Machines Corporation Corp. 1994. All 
  9471. Rights Reserved. 
  9472.  
  9473. Note to U.S. Government Users--Documentation related to restricted rights--Use, 
  9474. duplication or disclosure is subject to restrictions set forth in GSA ADP 
  9475. Schedule Contract with IBM Corp. 
  9476.  
  9477.  
  9478. ΓòÉΓòÉΓòÉ 12.2. Disclaimers ΓòÉΓòÉΓòÉ
  9479.  
  9480. References in this publication to IBM products, programs, or services do not 
  9481. imply that IBM intends to make these available in all countries in which IBM 
  9482. operates. Any reference to an IBM product, program, or service is not intended 
  9483. to state or imply that only IBM's product, program, or service may be used. 
  9484. Subject to IBM's valid intellectual property or other legally protectable 
  9485. rights, any functionally equivalent product, program, or service may be used 
  9486. instead of the IBM product, program, or service. The evaluation and 
  9487. verification of operation in conjunction with other products, except those 
  9488. expressly designated by IBM, are the responsibility of the user. 
  9489.  
  9490. IBM may have patents or pending patent applications covering subject matter in 
  9491. this document. The furnishing of this document does not give you any license to 
  9492. these patents. You can send license inquiries, in writing, to: 
  9493.  
  9494.       IBM Director of Licensing 
  9495.       IBM Corporation 
  9496.       500 Columbus Avenue 
  9497.       Thornwood, NY  10594 
  9498.       U.S.A. 
  9499.  
  9500.  Asia-Pacific users can inquire, in writing, to the IBM Director of 
  9501.  Intellectual Property and Licensing, IBM World Trade Asia Corporation, 2-31 
  9502.  Roppongi 3-chome, Minato-ku, Tokyo 106, Japan. 
  9503.  
  9504.  Licensees of this program who wish to have information about it for the 
  9505.  purpose of enabling: (i) the exchange of information between independently 
  9506.  created programs and other programs (including this one) and (ii) the mutual 
  9507.  use of the information which has been exchanged, should contact IBM 
  9508.  Corporation, Department LZKS, 11400 Burnet Road, Austin, TX 78758 U.S.A.  Such 
  9509.  information may be available, subject to appropriate terms and conditions, 
  9510.  including in some cases, payment of a fee. 
  9511.  
  9512.  
  9513. ΓòÉΓòÉΓòÉ 12.3. Trademarks ΓòÉΓòÉΓòÉ
  9514.  
  9515. The following terms are trademarks of the IBM Corporation in the United States, 
  9516. other countries, or both: 
  9517.  
  9518. IBM
  9519. Object REXX
  9520. Operating System/2
  9521. OS/2
  9522. Presentation Manager
  9523. SOMobjects
  9524. Workplace Shell
  9525.  
  9526. Other company, product, and service names, which may be denoted by a double 
  9527. asterisk (**), may be trademarks or service marks of others. 
  9528.  
  9529.  
  9530. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  9531.  
  9532. RESULT is also set by an EXIT or REPLY instruction. 
  9533.  
  9534.  
  9535. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  9536.  
  9537. Float values with maximum precision require NUMERIC DIGITS 15. 
  9538.  
  9539.  
  9540. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  9541.  
  9542. Programs must provide the hexadecimal value because no conversion is done.