═══ 1. Introduction ═══ SAA Procedures Language REXX Reference Version 1.00 (c) Copyright W. David Ashley and Pedagogic Software 1991. All rights reserved. Licensed to AMR, Inc. and all subsidiaries (no fee required). Documentation by W. David Ashley No warranties, guarantees, etc. are implied, and no liability is assumed for the code, examples, DLLs or documentation. Any mis-statements of fact or mis-representations in this reference are my own. I hereby apologize ahead of time should mistakes in this reference mislead you. If you will contact me I will make every effort to correct any errors in this reference. This documentation is user-supported and may be freely copied and used by anyone who wishes to do so as long as the following conditions are met: 1. The files and documentation may not be used by any program for which a fee is charged unless the owner of the program has paid the registration fee. 2. If you transmit a copy of this software to another party you must give them the complete unaltered contents of the SAAREXX.ZIP file. If you feel that this program/documentation has benefited you, please register it by sending $25.00 (no fee required by AMR, Inc. and all subsidiaries) to: Pedagogic Software W. David Ashley 5 Timberline Dr. Trophy Club, Tx 76262 The source code for SAAREXX.INF can be obtained by sending $75.00 ($25.00 registration + $50.00 source code) to the same address (no fee required by AMR, Inc. and all subsidiaries). If you have questions, comments or suggestions please contact me through the OS/2 Shareware BBS or at the address above (AMR employees may contact me through PROFS, my user ID is Z2277). This online reference is a complete update of Brian Buck's REXREF.INF. It has been reorganized, expanded, cleaned up and otherwise modified to support only IBM SAA environments (all DOS REXX product references have been eliminated). Many thanks to Brian for an outstanding job in getting this off the ground. Brian, if you're out there somewhere, contact me. This is a reference for quick online lookups of REXX syntax; it is NOT a substitute for the real REXX reference manuals. Neither is it a tutorial; unless you have some programming experience, you probably could not learn REXX from this reference alone. It is assumed that you may know some REXX, but are still learning and need to look things up frequently, or are an experienced user who nonetheless hasn't yet memorized every function in the entire language, or the variants for every environment and implementation. You can lookup REXX topics for the SAA, OS/2, TSO, and VM environments. Why an Online REXX Reference? Why? - Like Brian Buck, I needed one; so did the people in my company. Unfortunately, IBM did not see fit to provide either a written or online one with OS/2 1.x (the beta version of the OS/2 2.0 REXX online reference from IBM is only slightly better than nothing). I also got tired of needing a different REXX manual for every environment and implementation, plus the SAA one --- important, but useless by itself. That's why this reference covers all the SAA environments that have REXX implementations. (Yes, I know, there is now REXX for AS/400, but I don't have those manuals; volunteers, anyone? Send me the details and I'll update this reference). Warning: Author mounting soapbox! Also, I wanted to encourage the widespread use of REXX as a macro language for editors, communications packages, spreadsheets, etc. A universal macro and procedures language is needed; it is crazy to have to learn a new language for every new package you buy. Maybe REXX isn't the best possible choice, but it's here now and available in most environments, and is a pretty good language for this specialized purpose. Demand REXX interfaces from your vendors -- vote with your dollars; include them in your products if you author software yourself. It is encouraging to see companies like Lotus coming out in favor of REXX (as reported in PC Week from the SLAC REXX symposium). Trademarks The following trademarks apply to all online information: o IBM is a registered trademark of International Business Machines Corporation. o Microsoft is a trademark of the Microsoft Corporation. o Operating System/2 and OS/2 are trademarks of International Business Machines Corporation. o Personal System/2 and PS/2 are registered trademarks of International Business Machines Corporation. o Presentation Manager is a trademark of International Business Machines Corporation. o Systems Application Architecture and SAA are trademarks of International Business Machines Corporation. o TSO is a trademark of International Business Machines Corporation. o VM is a trademark of International Business Machines Corporation. o MVS is a trademark of International Business Machines Corporation. ═══ 1.1. Other References ═══ The following references were consulted during the preparation of this reference: Order# / ISBN Manual, Book, or Article S01F-0284 OS/2 Procedures Language 2/REXX Reference (OS/2), IBM SC24-5239-03 VM/SP System Product Interpreter Reference (VM/SP Release 6), IBM SC28-1883-2 TSO/E Version 2 REXX Reference (TSO/E 2.2), IBM SC26-4358-2 SAA CPI Procedures Language Reference, IBM 0-13-780651-5 The Rexx Language: a Practical Approach to Programming 2nd edition, by M. F. Cowlishaw, IBM UK Scientific Centre; 1990, Prentice-Hall, Inc., Englewood Cliffs, New Jersey 07632 Additional and introductory information can be found in: Order# / ISBN Manual, Book, or Article S01F-0283 OS/2 Procedures Language 2/REXX User's Guide, IBM SC24-5549 SAA CPI Procedures Language Level 2 Reference, IBM SC28-1882-1 TSO/E Version 2 REXX User's Guide, IBM SC24-5357 VM/IS Writing Simple Programs with REXX, IBM SC24-5238 VM/SP Product Interpreter User's Guide, IBM GH19-8118 CMS REXX Compiler General Information, IBM SH19-8120 CMS REXX Compiler User's Guide and Reference, IBM SH19-8146 CMS REXX Compiler User's Guide Reference Supplemental, IBM GG22-9361 System Product Interpreter REXX Examples and Techniques, (VM) IBM G321-5359 REXX on TSO/E, IBM Systems Journal article reprint from Vol. 28 No. 2, 1989 G321-5228 The Design of the REXX Language, IBM Systems Journal article reprint from Vol. 23 No. 4, 1984 0-89435-354-3 REXX in the TSO Environment, by Gabriel F. Gargiulo; 1990, QED Information Sciences, Inc., P.O. Box 82-181, Wellesley, MA 02181 0-13-682790-X Practical Usage of REXX, by Anthony S. Rudd; 1990, Ellis Horwood Limited, Market Cross House, Cooper street, Chichester, West Sussex, PO19 1EB, England ═══ 2. Usage Instructions ═══ (The following instructions are taken from the OS/2 online Command Reference.) When the Contents window first appears, some topics have a plus (+) sign beside them. The plus sign indicates that additional topics are available. To expand the Contents if you are using a mouse, click on the plus sign. If you are using the keyboard, use the Up or Down Arrow key to highlight the topic, and press the plus (+) key. For example, Keyword Instructions has a plus sign beside it. To see the complete list of REXX keyword instructions, click on the plus sign or highlight that topic and press the plus (+) key. To view a topic, double-click on the topic (or press the Up or Down Arrow key to highlight the topic, and then press the Enter key). How to Obtain Additional Information After you select a topic, the information for that topic appears in a window. You will notice that certain words in the text may be specially highlighted (The default color for this special highlighting is green). These words are links to additional information. If you are using a mouse, double-click on the highlighted word. If you are using a keyboard, press the Tab key to move to the highlighted word, and then press the Enter key. Additional information will appear in a pop-up window. How to Use Action Bar Choices A number of choices are available for managing information presented in the REXX Quick Reference. If you want to see more information about these choices, click on the name of the choice (or press the Tab key to move to the choice and press Enter). Bookmark Allows you to set a placeholder so you can retrieve information of interest to you. (This choice is available from the Services pull-down). Search Allows you to find occurrences of a word or phrase in the current topic, selected topics, or all topics. (This choice is available from the Services pull-down). Print Allows you to print one or more topics. (This choice is available from the Services pull-down). Copy Allows you to copy a topic you are viewing to a file you can edit. (This choice is available from the Services pull-down). Options Allows you to change the way your Contents is displayed. ═══ 3. How to Read the Syntax Diagrams ═══ The first thing you see above a syntax diagram is a list of icons that represent the applicable environments for each item. indicates that IBM OS/2 Procedures Language/2 REXX does/doesn't have this item. indicates that the IBM mainframe VM implementation of REXX does/doesn't contain this item. indicates that the item is/isn't valid in TSO/E REXX. indicates that this item is/isn't in the SAA Procedures Language Specification. indicates that this item is/isn't in M.F.Cowlishaw's REXX book. If a particular option or parameter is not supported in every environment, then you will see "X'ed" icons for the unsupported environments. Language elements that are unique to one particular environment are also shown with a yellow background, as if you had run a highlighting pen over them. The symbols are not buttons or hypertext links; they are just visual clues to the set of environments which implements each item. Syntax Diagram The syntax diagram shows you how to specify a command so that the REXX interpreter can correctly understand what you typed. These diagrams are sometimes called railroad track diagrams. In general, you can just follow the lines and arrows, and any path you trace will be syntactically valid. The symbol ── identifies the start of a syntax diagram; ── pinpoints the end. When a diagram must be continued because it doesn't fit on a single line, the continued line ends in ── and the continuation begins with ── . The horizontal line is the main path. Required parameters are displayed on the main path; optional parameters are displayed below it. Parameters are classified as keywords or variables. Keywords are displayed in uppercase letters and must be typed exactly as shown. Variables appear in lowercase letters and represent names or values you supply. A filename is a variable. Note that a parameter can be a combination of a keyword and a variable. Include all punctuation shown in the diagram, such as colons, semicolons, commas, quotation marks, and equal signs. The words in the diagram that appear in a different color are hypertext links to footnotes or other parts of the online reference. You can tab to them and press Enter to view the related information. Alternatively, you can double click with the mouse selection button (by default, the left mouse button) to view the same information. Specify a Sequence More Than Once: An arrow that returns to a previous point means the sequence of items included by the arrow can be specified more than once. ────PROCEDURE──┬────────────────────┬──;──── │ ┌───────┐ │ │  │ │ └──EXPOSE──┴─name──┴─┘ Choose One Item from a Stack: A stack of parameters with no return arrow means that you cannot choose more than one from the stack. ──NUMERIC───┬──DIGITS─┬────────────┬──────────┬──;─ │ └─expression─┘ │ ├──FORM──┬──────────────────────┬─┤ │ ├─SCIENTIFIC───────────┤ │ │ ├─ENGINEERING──────────┤ │ │ └─┬───────┬─expression─┘ │ │ └─VALUE─┘ │ └──FUZZ──┬──────────────┬─────────┘ └──expression──┘ ═══ 4. Basic Concepts ═══ REXX is a programming language that is appropriate for writing command procedures and for developing macros for products such as editors, communications packages, and data bases. Personal computing tasks are conveniently and quickly done in REXX. REXX was developed at IBM in the early eighties for use on the VM mainframe operating system. Mike Cowlishaw of IBM UK created the REXX language as a successor for the existing VM command languages, EXEC and EXEC2. This is how REXX got its name: the Restructured Extended Executor language. You will be seeing more and more use of REXX as time goes on; it has been designated as the SAA (Systems Application Architecture) standard procedures language. IBM Implementations exist for VM, MVS, OS/2, OS/400, and I think AIX. Mansfield Software Group has implementations for OS/2 and DOS. A variant called AREXX is widespread in the AMIGA world. A company called Ix has spent the last two years developing multitasking REXX interpreters, written in C, for the VM, MVS, PCDOS, UNIX, and OS/2 environments. In the OS/2 environment, REXX can be used anywhere that the BAT batch language could be used - and more. REXX can be used as the macro language for several common editors. REXX is used as the scripting language for several shareware and commercial communications products. REXX can be used with the OS/2 EE Database Manager and Query Manager to perform various SQL operations. You can use REXX as the command and/or macro language with your own products and applications. There is an API that allows any program to interact with REXX execs (procedures); this makes it easy to enhance your application's functionality. You can extend REXX's capabilities with function packages of your own devising; these functions you provide, which can be written in any language, are invoked just like the builtin REXX functions. Unfortunately, the SAA specification for REXX does not extend to include a standard for function packages or the registration and APIs for host command environments. It would be fruitful for an SAA or possibly an ANSI standard to address these areas. The IBM version of REXX for OS/2 is now a component of every copy of OS/2 sold (from version 1.3 forward). The point is that REXX is automatically available on almost every OS/2 machine. Once vendors discover that a REXX capability makes their products more marketable (because customers need not learn yet another unique language) you'll begin to see it everywhere. REXX is fundamentally an interpreted language. Some implementations offer a partial or complete compilation process as well. There is a REXX compiler for VM from IBM. As demand for a compilation feature grows, we are likely to see ports of the IBM compiler to OS/2 and MVS. Sources have indicated that work is proceeding on an MVS REXX compiler in Vienna, Austria. ═══ 4.1. Language Syntax ═══ REXX programs are built from clauses; the structure of a clause is shown below: ┌───────┐  │ ───┬──────────┬─┴─token─┴───┬──────────┬──┬──────;──────┬── └──blanks──┘ └──blanks──┘ └─end of line─┘ It is important to note that the semicolon is optional for the last clause on the line; in some implementations there is actually a performance penalty by including the semicolon in this situation. Tokens Comments The C and PL/I style of /* and */ is used. The comments may span multiple lines, but may not be nested. CLIST writers should note that comments are not terminated by the end of line. Character string literals Either single (') or double (") quotes can be used to delimit the beginning and end of a string literal. Use the same delimiter for the end as for the beginning. If the delimiter must occur within the literal, then double it. The literal should be contained within one line, and can contain any character. On OS/2, the linefeed character ('0A'x) cannot be contained within the literal. On CMS and TSO/E, the literal can span lines; however, this is not a good practice. Examples: 'This is a string literal.' "So is this." "Delimiters of one kind won't cause problems inside the other." 'Delimiters of same kind should''ve been doubled.' Hexadecimal string literals Either single (') or double (") quotes can be used to delimit the hexadecimal string literal. Use the same delimiter for the end as for the beginning. Follow the ending delimiter with any case of the letter X. The literal can contain any sequence take from the digits 0-9, or any case of the letters A-F. Odd numbers of hex digits can be used, in which case a leading "0" is assumed. A nice feature is that blanks can be used within the literals at byte boundaries (but not at the beginning or end) to enhance readability. Examples: '0123456789abcdef'x "13 10"X "e3c8c9e2 c9e2 C5C2C3C4C9C3"x '4159434949'X CAUTION: Don't use "X" as a variable name -- it can cause you unexpected difficulties, as in: Say "X="x which gives an error "invalid hexadecimal string." Note: Be careful when using hexadecimal literals; dependencies on particular character sets (ASCII or EBCDIC) or particular codepages (850, 437, etc.) can greatly impair portability. Binary string literals (IBM OS/2, SAA Level 2, and REXX 4.00 only) Either single (') or double (") quotes can be used to delimit the binary string literal. Use the same delimiter for the end as for the beginning. Follow the ending delimiter with any case of the letter B. The literal can contain any sequence taken from the digits 0 or 1. If the number of binary digits is not a multiple of four (4), enough leading "0s" are added to make it so. A nice feature is that blanks can be used within the literals at byte or nibble (half-byte) boundaries (but not at the beginning or end) to enhance readability. Warning: The implementation first examines the "B" following the literal's ending delimiter to determine that this is a binary string literal; as a result , any ordinary character string literal followed immediately by a token consisting only of the letter "B" is treated as an invalid binary string literal. Examples: '1'B /* same as "0001"b */ "0010101111010100"b "0010 1011 1101 0100"b /* same as above */ Numbers Integers, decimals, and exponential notation are used. Here is the formal definition: ─┬─┬┬────┬┬d──┬┬─┬┬─────┬─ where b=blanks └b┘└s┬─┬┘├d.d┤└b┘└E┬─┬d┘ s=sign └b┘ ├.d─┤ └s┘ d=digits └d.─┘ E=E or e The number of digits that can be used is determined by the NUMERIC DIGITS instruction; the default is 9, but there is no limit to the number of digits that may be specified, other than total storage. Larger numbers of digits will, of course, lead to increased execution times. Note: For some implementations, using a NUMERIC DIGITS specification less than nine may slow execution. Operators The single character operators are: + - \ / % * | & = к > <. The multiple character operators are: >= к< \< <= к> \> к= \= <> >< // && || ** >> << == >>= к<< \<< <<= к>> \>> к== \==. The (\) and (к) characters are interchangeable (both mean "not"). Occurrences of one or more blanks in expressions but not adjacent to operators (e.g. between symbols and/or parenthesized sub-expressions) are also an operator (concatenate with one blank between). Since the (\) is universally available on modern terminal and personal computer keyboards and on both mainframe and personal printers, while the (к) is usually available only on IBM terminal keyboards, usage of the (\) is preferable. Blanks and comments can be embedded within the multiple character operators, but for goodness sake, don't code them that way! (Just because it's legal doesn't make it right.) Special characters The characters ( ) : , ; and the individual characters that compose the operators act as special characters: they delimit tokens, and "suck up" all blanks they are adjacent to. Symbols Symbols can be numbers, REXX keywords, or names used for variables, labels, functions, etc. Names can't begin with digits or a period. All implementations allow names to include: a-z A_Z 0-9 underscore(_) exclamation(!) and question(?). The period can also be used, but it has a special meaning concerned with compound symbols. Symbols are not case sensitive, i.e., lower-case letters in symbols are translated to upper-case. The VM, MVS , and TSO environments also support the characters @ #$Ы in symbols. Avoid them for the sake of portability. Continued clauses End a line with a comma (,) to continue a clause. Blank or comment tokens may follow this comma. Clauses cannot be continued within string literals. Example: Say "first", "second" displays first second Example: Say "ABC", ||"DEF" displays ABCDEF ═══ 4.2. Expressions ═══ REXX expressions are sequences of terms, operators, and parentheses (round brackets, for those of you in the UK). Terms are: o Literals, which include character strings, hexadecimal strings, binary strings, and numbers. o Variables,which are simple or compound symbols. o Function References, which are the invocation of builtin, internal, or external functions. They look like this: ─┬─symbol(─┬─┬────────────────────┬─)── └─string(─┘ │ ┌───────,────────┐ │ │  │ │ └─┴─┬────────────┬─┴─┘ └─expression─┘ The parameters in a function call are passed by value. Everything in REXX is a string. Strings that contain numbers can be manipulated with arithmetic operators, but fundamentally we are still dealing with strings. Operators o Concatenation || concatenate (with no blank in between) (juxtaposition)concatenate (with no blank in between) (blanks) concatenate with just one blank between Examples: myvar1 = "the" myvar2 = " time" say "Now" "is "myvar||myvar2" for all good men ..." └─┬─┘ └┤ ├┘ └┤  │  └───┐ (blanks) │ (||)   (juxtaposition) (juxtaposition) displays: "Now is the time for all good men ..." o Arithmetic + add - subtract * multiply / divide % return an integer quotient from the division // return the integer remainder from the division. This is not the modulus operation, because negative remainders are returned when the dividend is negative. ** power (only integral exponents) prefix - negation (like 0 - term ) prefix + (like 0 + term ) o Comparison REXX has two sets of comparison operators: the forgiving and the strict. The strict ones do an exact character comparison with no padding. The forgiving ones will do numeric comparisons if both operands are numeric; if not, then leading and trailing blanks are ignored, and the shorter string is padded with blanks on the right. Comparisons are case sensitive. Since REXX is a multi-environment language, you should be careful about character set dependencies, e.g., with respect to ASCII vs. EBCDIC. - Forgiving = equal > greater than < less than >= or \< or к< greater than or equal to (same as not less than) <= or \> or к> less than or equal to (same as not greater than) \= or к= or <> or >< not equal - Strict == equal (C programmers, be careful here) >> greater than << less than >>= or \<< or к<< greater than or equal to (same as not less than) <<= or \>> or к>> less than or equal to (same as not greater than) \== or к== not equal o Logical Character strings with a value of zero ("0") have a logical value of false. Character strings with a value of one ("1") have a logical value of true. Any other value for a character string can not be used where a logical value is required. C and CLIST programmers should be especially careful with the logical operators -- there can be a high astonishment factor if you let your typing habitstake over when entering the logical operators. & AND returns 1 if both operands are true, else 0 | OR returns 1 if either operand is true, else 0 (inclusive OR) && XOR returns 1 if exactly one operand is true, else 0 (exclusive OR) prefix \ NOT inverts operand; if 1 then 0, else 1 prefix к NOT inverts operand; if 1 then 0, else 1 The OR character may appear as a split vertical bar ( | ) or solid vertical bar ( | ) on the keycap of your keyboard. OS/2 uses the one that maps to ASCII 124 ("7C"x). Evaluation of Expressions Terms are evaluated when they are needed, in a left to right order. The expression is evaluated according to the usual precedence of the operators in the expression: 1. prefix operators (minus, plus, not) 2. exponentiation (power) 3. multiplication (multiply, divide, quotient, remainder) 4. addition (add, subtract) 5. concatenation 6. comparison 7. logical AND 8. logical OR, XOR As you would expect, the use of parentheses can effectively change the order of evaluation. The only thing really different here is that the prefix operators bind more tightly than exponentiation, e.g., -2**4 yields 16, not -16. ═══ 4.3. Clauses ═══ REXX has five types of clauses: Assignment statements A single clause of the form symbol = expression Keyword instructions A series of related clauses that begin with a keyword symbol. E.g., the IF instruction consists of the IF keyword, the IF's condition, the THEN keyword and its clause(s), and the optional ELSE keyword and its clause(s). Commands A single clause consisting of just an expression. The evaluated expression is passed to an "environment" program, which could be the operating system, a communications program, a data base manager, etc. Labels A symbol followed by a colon defines a label. Labels are used to identify function or subroutine definitions. There is no GOTO in REXX. Null clauses A clause with only blanks or comments; it is ignored. This is NOT like a null instruction; you can't just add a semicolon to mean a null operation. There is a NOP instruction for that purpose (like the "CONTINUE" or "NEXT SENTENCE" in COBOL. ═══ 4.4. Variables ═══ Variables are symbols that don't begin with a digit or a period. A variable has a value that is a character string; it can hold any characters and be of unbounded length. These character strings can be numbers, and if so, you can do arithmetic on them. Variables do not have to be declared before use, or declared at all -- in fact, they cannot be declared. The name of a variable is not case sensitive, i.e., the names MyVar, myvar, and MYVAR all refer to the same variable MYVAR (C programmers take note). There are two kinds of variables in REXX: simple and compound. A simple variable is just like an ordinary variable you see in other programming languages -- it holds a single value. A compound variable is kind of like an array, kind of like a structure, kind of like a hash table, and quite unlike variables you may have seen in most other programming languages. Compound variables are symbols composed of what looks like a simple variable name, followed by a period, and then a sequence of other periods and/or valid symbol characters. OneD_Array.12 TwoD_Array.I.J SymbolTable.Symbol The first part of the compound variable name (up to and including the first period) is called the stem. Compound variables are often referred to as stem variables. The general form of a compound variable is: ┌─────────────────────┐  │ ───stempart─┴─ . ───simplesymbol──┴─────── When a compound variable is used, the stempart name is converted to all upper case, and the value of each simplesymbol is substituted into the name; the resulting derived name is then used like an ordinary variable name. You can see how it would be easy to use compound variables like multi-dimensional arrays, where the sequence of simple symbols after the stempart have numeric values. However, you can extend the idea because the simple symbols in the name can take on any value! You can use this powerful concept to create and manipulate stacks, queues, deques, heaps, trees, lists, etc. -- properly encapsulated, any type of data structure can be created using compound variables. The following code fragment, part of a word counting and cross-reference program, demonstrates a common use of compound variables -- as an array of structures, with an content-addressable index into the array: /* assume user functions exist */ /* called morewords() */ /* and nextword() */ /* no words in list, yet */ WordListNr = 0 /* This initializes ALL variables */ /* beginning with this stem: */ WordIndex. = "" do while morewords() thisword = nextword() /* Lookup index for word */ thisindex = WordIndex.thisword if thisindex = "" then do /* First occurrence of this word */ /* Save info in WordList.. array */ /* of structures */ WordListNr = WordListNr + 1 WordList.WORDVALUE.WordListNr = thisword WordList.WORDCOUNT.WordListNr = 1 WordIndex.thisword = WordListNr end else do WordList.WORDCOUNT.thisindex = WordList.WORDCOUNT.thisindex + 1 end end /* while morewords() */ Uninitialized Variables Variables that are used before they have been given values are uninitialized; the value of an uninitialized simple variable is its own name in upper case. Contrast this to other programming languages in which an uninitialized value is zero or the null string, or undefined. E.g., if variable NoInitValue has not been initialized, its value is "NOINITVALUE" (like WORDCOUNT and WORDVALUE in the example above). Similarly, the value of an uninitialized compound variable is the value of its derived name, in upper case. E.g., the uninitialized value of FileType.this when this = "exe" is "FILETYPE.EXE". ═══ 4.5. Commands ═══ The whole reason for REXX is to issue commands -- commands to the operating system, commands to an editor, commands to a communications package, etc. Depending on where your REXX exec runs, it will have access to one or more host system environments which receive and proccess the commands from your REXX exec. Any program can use a REXX API to register itself as an environment that will then be available to REXX execs. When your REXX exec begins execution, one of these environments is chosen as the default environment. When your exec contains a clause like: expression it is a command. The value of the expression is evaluated, and the resulting character string is passed to the current host environment. You can send commands to more than one environment in the same REXX exec. See the ADDRESS keyword instruction and the ADDRESS( ) builtin function for details. The default environment in OS/2 is CMD -- which processes the commands in the same way as the OS/2 command processor. Here is an OS/2 example: /* assume variable drive = 'C' */ /* assume variable directory = 'OS2' */ 'dir' drive':\'directory'\*' /* The command sent to the environment is: */ /* dir C:\OS2\* */ It is very important to enclose the parts of your command that are not to be evaluated in quotes. If you do not, REXX thinks you want variable substitution, which may not give you the desired results. For example, if the command above had been coded as: dir drive':\'directory'\*' then you would get different results depending on whether a variable called dir existed. If it did not exist, its uninitialized value would be used ("DIR"). This would be OK, but if the variable existed and had a value of "erase" then the command issued to the environment would be the ERASE command rather than the DIR command! You may see examples of REXX code that are not rigorous about quoting command strings; don't follow their style -- these are sleeping bugs that someday will wake up and bite you when a change is made elsewhere in the REXX exec, e.g., to begin using dir as a variable name. ═══ 5. Keyword Instructions ═══ Keyword instructions provide the structure on which the rest of a REXX program hangs; the commands and builtin functions flesh out this skeleton. For a description of the icons displayed and the syntax diagrams, see How to Read These Syntax Diagrams. In the sections that follow, the REXX keyword instructions are described. The respective sections can be jumped to directly by selecting one of the names from the list below: o ADDRESS - Set Subcommand Environment o ARG - Fetch Argument o CALL - Invoke Subroutine/Function o DO - Begin Block o DROP - Free Variable o EXIT - Terminate Program o IF - Condition Execution o INTERPRET - Execute Variable Statement o ITERATE - Terminate DO-Loop Cycle o LEAVE - Terminate DO-Loop o NOP - No-Operation o NUMERIC - Set Numeric Formats o OPTIONS - Set Language Processor Parameters o PARSE - Fetch and Assign Data o PROCEDURE - Define Internal Subroutine/Function o PULL - Fetch Element From the Head of the Stack o PUSH - Push Element To the Head of the Stack o QUEUE - Push Element to the Tail of the Stack o RETURN - Return From Subroutine/Function o SAY - Display Output o SELECT - Conditional Execution o SIGNAL - Enable/Disable Execption Condition o TRACE - Set Debugging Options o UPPER - Lower to Upper Case Conversion ═══ 5.1. ADDRESS - Set Subcommand Environment ═══ The ADDRESS instruction will change the destination of commands, either temporarily or permanently. ──ADDRESS──┬────────────────────────────┬──;── ├─environment─┬────────────┬─┤ │ └─expression─┘ │ └┬───────┬──expression1──────┘ └─VALUE─┘ Related Function: ADDRESS( ) Use the ADDRESS instruction to issue commands to a host or command environment, e.g., OS/2 commands, CMS or TSO commands, ISPEXEC or ISREDIT services. Many products, such as editors and communications packages, "register" their command environments for use in REXX procedures. You can write and register your own environments for use with your programs. Your REXX exec begins executing with one of the environments considered to be the default. You can change the environment temporarily to issue one command to a different environment, when more than one command environment is available, or you can change the environment permanently (until the next ADDRESS instruction). Commands that are being issued to the default environment need not be preceded by the ADDRESS keyword. Typical ADDRESS environments: o OS/2 CMD Used for OS/2 commands, just like in a windowed or full screen OS/2 command session DSQCIX Used to send commands to the OS/2 EE Query Manager. ISPCIR Used to issue OS/2 Dialog Manager services. LPEX Used in LPEX edit macros to issue commands to the editor. (LPEX, the Live Parsing Editor, is an IBM PM editor commercially available only in Europe). SQLDBS Used to send commands to the OS/2 EE Database Manager. o VM CMS Used for CMS commands, just as in the normal interactive mode. COMMAND Used in "system" EXECs to pass commands directly to CMS via SVC 202, bypassing EXEC or CP cmd search, and without parmlist translation. XEDIT Used in XEDIT sessions to issue commands to the editor. ISPEXEC Used in ISPF sessions to issue ISPF or ISPF/PDF services. ISREDIT Used in ISPF/PDF Edit macros. o TSO TSO Used for TSO/E commands, just as in the normal interactive mode. MVS Used in any MVS address space to issue a subset of TSO/E REXX commands. LINK Used in any MVS address space to link to any MVS or user module at the same task level. ATTACH Used in any MVS address space to attach any MVS or user module at a daughter task (TCB) level. ISPEXEC Used in ISPF sessions to issue ISPF or ISPF/PDF services. ISREDIT Used in ISPF/PDF Edit macros. NETVIEW Used in NetView Network Management Clists Examples: ADDRESS CMD 'TYPE C:\CONFIG.SYS' In this example, the default environment is TSO: /* command goes to environment TSO */ "listdsi" dataset_name_variable /* command goes to environment ISPEXEC */ address ispexec "LIBDEF ISPPLIB DATASET ID("dataset_name_variable") COND" /* command goes to environment TSO */ "alloc f(applwork) unit(vio) sp(1) tracks' /* commands go to environment ISREDIT */ address ISREDIT "change 'DOS' 'OS/2' all" "save" ═══ 5.2. ARG - Fetch Argument ═══ The ARG instruction parses incoming parameters. ──ARG──────┬────────────┬────────;── └──template──┘ Short form of PARSE UPPER ARG. Used to upper-case and receive parameters in an exec. Related Instructions: CALL, PARSE, PROCEDURE Related Function: ARG( ) Example: /* Suppose that the REXX exec has been * invoked with the parameter: * * "This string is in MiXeD CaSe." */ arg first second TheRest /* Contents of variables * after the ARG instruction: * * first : "THIS" * second : "STRING" * TheRest : "IS IN MIXED CASE." */ ═══ 5.3. CALL - Invoke Subroutine/Function ═══ The CALL instruction invokes an internal routine (contained in the same exec/program), or a builtin REXX function, or an external routine (located elsewhere -- details differ by operating system). CALL also is used for enabling and disabling condition traps for error recovery. ──CALL──┬──name──────┬─────────────────────────────┬──;─ │ │ ┌──────,───────────┐ │ │ │  │ │ │ └──┴─┬──────────────┬─┴───────┤ │ └──expression──┘ │ │ │ ├──OFF───────┬──ERROR────┬─────────────────┤ │ ├──FAILURE──┤ │ │ ├──HALT─────┤ │ │ └──NOTREADY─┘ │ │ │ └──ON──┬──ERROR────┬─┬──────────────────┬──┘ ├──FAILURE──┤ └──NAME──trapname──┘ ├──HALT─────┤ └──NOTREADY─┘ Related Instructions: ARG, PARSE, PROCEDURE, SIGNAL Related Functions: ARG( ), CONDITION( ) A routine can alternatively be invoked as a function reference, if it is defined as returning a result; the function reference can be used any where that an expression can: ──name(─┬─────────────────────────────┬─)── │ ┌──────,───────────┐ │ │  │ │ └──┴─┬──────────────┬─┴───────┘ └──expression──┘ Note: The name and the left parenthesis in the above MUST be adjacent (no intervening blank) or else REXX will see this not as a function reference but a blank operator between two string expressions. When a routine returns a result, but has been invoked with the CALL syntax, the returned result is still accessible to the caller in the special variable RESULT. If the called routine did NOT return a result, then the RESULT variable is dropped, i.e., becomes uninitialized (its value = "RESULT"). Recursive calls are supported; in fact, in OS/2, you cannot invoke a REXX program from a REXX program via the command environment -- you must use the CALL instruction. It is possible to invoke builtin functions in this way, but strange terminations of the REXX exec usually happen. There is some overloading on CALL in REXX: as you can see above in the syntax diagram, CALL is used both for invoking routines and for setting error recovery options. When a condition has been enabled, as in: call on error name MyError then should the ERROR condition be raised, the routine MyError will be called. It could take some action and return, or exit (terminate the entire REXX program). Parameters: name A symbol or string literal that names the routine to be called. The search order for finding the routine is: 1. internal routine 2. external routine 3. builtin function When a string literal is used, internal routines are not invoked, only external or builtin routines are called. The string literal should be in upper case because builtin routines and external routines in most environments must be in upper case. ON Enables the named condition. OFF Disables the named condition. ERROR The ERROR condition is raised if an environment command indicates an error upon its return to REXX, or if it indicates a failure and the FAILURE condition is not enabled. FAILURE The FAILURE condition is raised if an environment command indicates a failure upon its return to REXX. HALT The HALT condition is raised if an external attempt is made to halt the REXX program. In OS/2, this is not implemented for REXX programs invoked from the command session. NOTREADY The NOTREADY condition is only valid in OS/2; this condition is raised if there is an error during an I/O operation. trapname The name of a routine to be called when the associated condition is raised. Example: ... call fcn dataset, member valuefromfcn = RESULT ... fcn: procedure arg dsn, mbr ... return somevalue ═══ 5.4. DO - Begin Block ═══ The DO instruction (and it's paired END keyword) bracket a block of instructions that can be executed repetitively. ─DO─┬─────────┬─┬───────────┬─;─┬────────────────┬END─┬───────┬;─ └repetitor┘ └conditional┘ │┌──────────────┐│ └─symbol┘ │ ││ └┴─instructions─┴┘ repetitor: ──┬─name=expri─┬────────┬─┬────────┬─┬─────────┬─┬── │ └TO─exprt┘ └BY─exprb┘ └FOR─exprf┘ │ ├──FOREVER─────────────────────────────────────┤ └──exprr───────────────────────────────────────┘ conditional: ─────┬─WHILE─exprw──┬─── └─UNTIL─expru──┘ Related Instructions: ITERATE, LEAVE, NUMERIC For C programmers, this is like while (condition) { ... } and for (initial;condition;repetitor) { ... } all rolled into one instruction. Used to control the looping of instructions. Note that REXX, unlike other languages, does NOT allow the use of both the WHILE and UNTIL keywords in the same DO statement. The exprr, exprw and expru expressions must evaluate to 1 or 0 (true or false). The DO must have a matching END keyword. Example: do i = 1 to CellNr by 2 until Cell.i = 'empty' end Control Flow in a DO Loop Evaluate expi, expt, expb │  DO name=expi │  ┌─────TO exprt────END │ │ │  │ FOR exprf────END │ │ │  │ WHILE exprw───END │ │ │  │ instruction(s) │ │ │  │ UNTIL expru───END │ │ │  │ BY exprb └──────────┘ ═══ 5.5. DROP - Free Variable ═══ The DROP instruction unassigns variables; restores them to their original uninitialized state. ┌───────────────┐  │ ────DROP───┴┬────name─────┬┴───;────────── └─(name-expr)─┘ Related Instruction: PROCEDURE It's OK to specify the names of variables that are uninitialized already. If an exposed variable is named via PROCEDURE EXPOSE, the variable in the older generation is dropped. CAUTION: In some environments, excessive use of DROP can slow the execution. Example: a = "This is a" b = "variable B here" c = "a C variable" d = "a b" e.1 = "E sub 1" drop (d) c e. say "a = " a say "b = " b say "c = " c say "d = " d say "e.1 = " e.1 Output a = A /* uninitialized value */ b = B /* uninitialized value */ c = C /* uninitialized value */ d = a b e.1 = E.1 /* uninitialized value */ The variables in a list are dropped in order, left to right. Example: a = "This is a" b = "variable B here" c = "a C variable" d = "a b" e.1 = "E sub 1" drop d (d) c e. say "a = " a say "b = " b say "c = " c say "d = " d say "e.1 = " e.1 Output a = This is a b = variable B here c = C /* uninitialized value */ d = D /* uninitialized value */ e.1 = E.1 /* uninitialized value */ ═══ 5.6. EXIT - Terminate Program ═══ The EXIT instruction leaves a REXX program; an optional expression is returned in the caller's REXX variable named RESULT. ────EXIT───┬──────────────┬──;────── └──expression──┘ Related Instruction: RETURN A REXX program that is intended to be invoked as an external function must return a result. EXIT in an internal routine terminates the whole program. Note: On VM, the optional expression is returned to caller upon termination (not in RESULT). ═══ 5.7. IF - Conditional Execution ═══ Use to control execution sequencing; can be nested to accommodate complex conditional logic. ─IF─expression─┬─┬THEN─┬─┬instruction─┬────────────────────┬── └;┘ └;┘ └─ELSE─┬─┬instruction┘ └;┘ Note: If you need a "null" instruction, you must use the NOP instruction. Simply coding a blank line, or adjacent semicolons (;;) does NOT work as in PL/I. Most of the semicolons in the syntax for IF are optional; this is a syntactic sugaring that makes writing REXX programs easier for those who also work in other languages. Imagine what would happen if the semicolon after the THEN were required! A result of this convenience is that a variable named THEN cannot be used in the expression of an IF instruction. This doesn't constitute a hardship, as any programmer who names variables this way should be shot, anyway. ═══ 5.8. INTERPRET - Execute Variable Statement ═══ The INTERPRET is used to dynamically interpret sequences of REXX instructions, and to perform multiple levels of symbolic substitution. ────INTERPRET────expression───;────────── This can be tricky, but is powerful when necessary. Overuse of INTERPRET makes programs HARD to read, and thus hard to maintain. Real world examples could include usage to invoke subroutines whose names are not known until run time. Could be used in this way to crudely implement some aspects of object oriented methods. The REXX instruction or instructions in the expression of an INTERPRET instruction must be syntactically complete, i.e., no unpaired DO loops, etc. Labels can be coded in these instructions, but are ignored, so don't use them. Programmers used to other languages, especially TSO CLISTs, tend to use INTERPRET as a substitute for REXX compound variables. This is not as efficient, and stylistically is at variance with the mainstream of REXX programming. Example: things_to_do = "do 5; say 'Hi there ...'; end" INTERPRET things_to_do Output Hi there ... Hi there ... Hi there ... Hi there ... Hi there ... ═══ 5.9. ITERATE - Terminate DO-Loop Cycle ═══ The ITERATE instruction is used in DO loops; it is like transferring to the bottom of current loop, then cycling. ────ITERATE─┬──────┬──;────────────────── └─name─┘ Related Instructions: DO, LEAVE Used to control flow in DO loops; a special purpose substitute for GOTO. Example: /* copy a file, omitting blank lines */ arg infile outfile call lineout outfile,,1 /* position to start of file */ do while lines(infile) \= 0 line = linein(infile) if line = "" then iterate call lineout outfile, line end ═══ 5.10. LEAVE - Terminate DO-Loop ═══ The LEAVE instruction leaves the innermost DO loop, or the named DO loop. ────LEAVE────┬──────┬───;──────────────── └─name─┘ Related Instructions: DO, ITERATE, EXIT, RETURN Use to control flow in DO loops; a special purpose substitute for GOTO. Example: /* compute the next "perfect" number */ /* (number = sum of its divisors, */ /* excluding itself, but including 1) */ arg startnum if startnum // 1 \= 0 then do say "Starting number must be an integer." exit 1 end if startnum <= 0 then do say "Starting number must be positive." exit 1 end currnum = startnum + 1 do while 1 sum = 0 do i = 1 to currnum - 1 if currnum // i = 0 then sum = sum + i end if sum = currnum then leave say currnum sum currnum = currnum + 1 end say "The next perfect number, starting after" startnum", is" currnum"." exit 0 ═══ 5.11. NOP - No-Operation ═══ Does nothing - a placeholder, like "CONTINUE" or "NEXT SENTENCE" in COBOL. ────NOP───;────────────────────────────── Example: Say "Enter a positive integer" pull I if I > 0 then nop else do say 'Number must be positive.' exit end if I // 1 = 0 then nop else do say 'Number must be an integer.' exit end do forever /* always stops; * can you PROVE it does? */ say I if I=1 then leave if I//2 = 0 then do I = I/2 iterate end I = (3*I + 1)/2 end ═══ 5.12. NUMERIC - Set Numeric Formats ═══ The NUMERIC instruction changes the way in which arithmetic is done: precision of numbers, format of display, and accuracy of comparison. ──NUMERIC───┬──DIGITS─┬────────────┬──────────┬──;─ │ └─expression─┘ │ ├──FORM──┬──────────────────────┬─┤ │ ├─SCIENTIFIC───────────┤ │ │ ├─ENGINEERING──────────┤ │ │ └─┬───────┬─expression─┘ │ │ └─VALUE─┘ │ └──FUZZ──┬──────────────┬─────────┘ └──expression──┘ Default DIGITS is 9; max DIGITS is implementation dependent, but usually bigger than you have any reasonable excuse to use (e.g., 9999 digits!). Use to control precision of arithmetic results; to specify display format of floating point numbers; to indicate how close floating point numbers have to be before they are considered equal in comparisons (the "fuzz"). NUMERIC settings are saved across subroutine and internal function calls. Note: A high value for digits adversely affects performance; non-intuitively, a value less than nine in 32-bit environments also hurts performance (e.g., in TSO). Note: On VM, the FORM keyword is only valid with options SCIENTIFIC and ENGINEERING for releases before VM/SP Release 6. ═══ 5.13. OPTIONS - Set Language Processor Parameters ═══ The OPTIONS instruction is for notifying the REXX language processor about the user's choice for particular implementation options. ────OPTIONS─────expression─────────;──── The SAA REXX processors use this instruction in support of DBCS. (DBCS is Double Byte Character Set, for use with natural languages like Japanese or Chinese with enormous numbers of unique glyphs.) Valid expressions in TSO, VM and OS/2 are: ETMODE enables use of DBCS strings NOETMODE disables use of DBCS strings EXMODE preserves logical DBCS character integrity NOEXMODE byte basis; DBCS integrity not guaranteed (default) Other processors use this instruction for run-time support. The VM REXX compiler uses this instruction to specify compile options. ═══ 5.14. PARSE - Fetch and Assign Data ═══ The PARSE instruction extracts data into one or more variables from arguments, variables, and other sources. ──PARSE─┬───────┬─┬──ARG───────────────────────┬─┬──────────┬─;─ └─UPPER─┘ ├──EXTERNAL──────────────────┤ └─template─┘ ├──NUMERIC───────────────────┤ ├──LINEIN────────────────────┤ ├──PULL──────────────────────┤ ├──SOURCE────────────────────┤ ├──VALUE─┬────────────┬─WITH─┤ │ └─expression─┘ │ ├──VAR──name─────────────────┤ └──VERSION───────────────────┘ Note: EXTERNAL and NUMERIC are TSO and VM only; LINEIN is OS/2 only. Related Instructions: ARG, PULL Related Function: LINEIN( ) PARSE is a powerful text pattern matching/extraction instruction used to parse words/parameters/keywords in arguments, from terminal input, from variables; a variety of matching and positional templates are available. You can use PARSE SOURCE and PARSE VERSION to write multi-environment REXX procedures that execute on all systems, under all implementations. PARSE ARG The string(s) passed to the program, subroutine, or function as input arguments are parsed. To parse multiple argument strings, multiple templates must be supplied seperated by commas. For example: parse arg arg1, arg2, , arg4 assigns the first argument string to arg1, the second argument to arg2 and the fourth argument to arg4. PARSE EXTERNAL Reads from the user's terminal (the standard input stream). PARSE NUMERIC Parses the current numeric controls (as set by the NUMERIC statement. For example: parse numeric var1 might set var1 to the value "9 0 SCIENTIFIC". PARSE LINEIN The next line from the default input stream is parsed. If no line is available execution pauses until one becomes available. This is a short form of PARSE VALUE LINEIN() WITH template. PARSE PULL The next line from the default queue is parsed. If the queue is empty a line is read from the default input stream. PARSE SOURCE The SOURCE consists of a list of tokens that describe the origin of the procedure being executed. The first token is CMS or TSO or OS/2; Second is COMMAND, or SUBROUTINE or FUNCTION; the rest differ according to the environment and the implementation: OS/2 fully qualified file name of procedure CMS Compiler file name or syn file type; * if running as MODULE file mode; * if running as MODULE name invoked as or syn or ? default address env CMS Interpreter file name file type or * file mode or * name invoked as or syn or ? default address env TSO name of exec in upper case or ? name of DDNAME fo exec or ? name of data set for exec, or ? name of exec as invoked, or ? default address env name of address space 8 character user-specified token PARSE VALUE The expression is parsed with the specified template. PARSE VAR The name REXX variable is parsed with the specified template. PARSE VERSION The VERSION string consists of five tokens in three groups: 1. A word naming the implementation of the language. It must begin with the four characters "REXX," and the rest can be any characters valid in a symbol. REXXSAA OS/2 REXX370 TSO, TSO/E, VM interpreter REXXC370 VM CMS REXX compiler 2. The language level of the REXX implementation: 4.00 OS/2, the Cowlishaw book (2nd edition) 3.46 CMS Release 6 with SPE TSO/E Version 2 Release 1 with an APAR, TSO/E V2R1.1 CMS Compiler 3.45 CMS Release 6 TSO/E V2R1 3.40 CMS Releases 4, 5 and 5.5 3.20 CMS Release 3 (original) 3. The date of the implementation, in three tokens: 06 Feb 1990 OS/2 Example: (pull off one word at a time) do until bigstring = "" PARSE VARIABLE bigstring oneword bigstring say oneword end Example: (multiple parallel assignment) PARSE VALUE '1 10 100' WITH one ten hundred /* assigns '1' to variable "one" */ /* assigns '10' to variable "ten" */ /* assigns '100' to variable "hundred" */ Example: (assignment of one value to multiple variables) xyz = "same value" PARSE VAR xyz 1 copy1 1 copy2 1 copy3 /* assigns "same value" to variable "copy1" */ /* assigns "same value" to variable "copy2" */ /* assigns "same value" to variable "copy3" */ Note: If you are coding in a TSO/E environment and need to replace a CLIST that used "PROC" statement parameter parsing, you will find that there is no convenient way to do this in REXX. Until someone writes a public domain external function to do this in a general way, or until IBM decides to remedy this obvious hole in TSO/E REXX functionality, the easiest way to accomplish this is to retain a shell of the original CLIST, that contains the original CLIST PROC statement (to perform the parsing and prompting). The only other statement in the CLIST would be an invocation of the REXX exec, passing the parsed parameters in a manner convenient to the exec. ═══ 5.15. PROCEDURE - Define Internal Subroutine/Function ═══ The PROCEDURE instruction defines a scoping level for variables, i.e., variables used within the routine are local to the routine, and hiding all variables in the calling routine from query or update by this routine. ────PROCEDURE──┬────────────────────┬──;──── │ ┌───────┐ │ │  │ │ └──EXPOSE──┴─name──┴─┘ Related Instructions: CALL, RETURN PROCEDURE begins an internal procedure or function; EXPOSE gives access to selected variables in the containing procedure. You use this to control the scoping of variables in procedures and functions; internal procedures should ususally be specified with this instruction, and the EXPOSE operand should be used judiciously. Although internal routines do not have to begin with the PROCEDURE instruction, seldom is it warranted to omit it. A variety of tricks and useful techniques are based on the fact that one level of substitution can be performed in the EXPOSE clause prior to establishing the exposed variable names. Another trick is to use a stem in the EXPOSE statement. Example: GlobalVariables = "MyVariable HisVariable CompoundVariables." ... TestObjectVariables = "TestMode TestName TestConditions. TestNr" call TestProcedure ... TestProcedure: procedure expose (GlobalVariables) (TestObjectVariables) In the example above, the values of GlobalVariables and TestObjectVariables are substituted prior to determining which variables are to be exposed. Thus, all of the following variables are exposed in the procedure TestProcedure: MyVariable, HisVariable, all compund forms of CompoundVariables., TestMode, TestName, all compound forms of TestConditions., and TestNr. ═══ 5.16. PULL - Fetch Element From the Head of the Stack ═══ The PULL instructions is used to obtain line mode input from the currently active REXX queue; usually the command line or the terminal. ──PULL─────┬────────────┬────────;── └──template──┘ Related Instructions: PARSE, PUSH, QUEUE Related Functions: QUEUED( ), RXQUEUE( ) This is short for PARSE UPPER PULL. Example: say "Please enter your name:" pull input say "Howdy," input"!" ═══ 5.17. PUSH - Push Element To the Head of the Stack ═══ The PUSH instruction places an expression on top of the REXX queue. ──PUSH─────┬──────────────┬────────;── └──expression──┘ Related Instructions: PULL, QUEUE Related Functions: QUEUED( ), RXQUEUE( ) The expression goes on top of the queue in LIFO (Last in, first out) order. You can use to push a value on data stack for later use by a subroutine or I/O routines. Example: push "Simon Nash" push "Linda Green" push "Herr VandeWater" do while queued( ) \= 0 call NameRoutine end exit NameRoutine: procedure pull input say "Howdy," input"!" return Output Howdy, HERR VANDEWATER! Howdy, LINDA GREEN! Howdy, SIMON NASH! ═══ 5.18. QUEUE - Push Element To the Tail of the Stack ═══ The QUEUE instruction places an expression on the bottom of the REXX queue. ──QUEUE────┬──────────────┬────────;── └──expression──┘ Related Instructions: PARSE, PULL, PUSH, QUEUE Related Functions: QUEUED( ), RXQUEUE( ) Places expression on the bottom of the REXX queue in FIFO (First in, first out) order. You can use QUEUE to queue a value on the queue for later use; more natural than PUSH when adding several items to an empty queue. Note: REXX queues are NOT the same as OS/2 queues. Example: queue "Poughkeepsie" queue "Vienna" call ItineraryRoutine exit ItineraryRoutine: procedure pull from pull to say "Goodbye," from", hello" to"!" return Output Goodbye POUGHKEEPSIE, hello VIENNA! ═══ 5.19. RETURN - Return From Subroutine/Function ═══ Leaves an internal routine or function; expression is returned in variable RESULT. ──RETURN───┬──────────────┬────────;── └──expression──┘ Related Instructions: CALL, EXIT, PROCEDURE You can use this to return a value from a function; use of the expression is required when a routine is invoked as a function as opposed to a subroutine; it is a good (or at least, safe ...) programming practice in REXX to always return a value. Example: /* compute the "Nth" Fibonacci number */ do i=1 to 12 say i Fibonacci(i) end exit Fibonacci: procedure arg N if N <= 2 then do return 1 end return (Fibonacci(N-1) + Fibonacci(N-2)) Output 1 1 2 1 3 2 4 3 5 5 6 8 7 13 8 21 9 34 10 55 11 89 12 144 ═══ 5.20. SAY - Display Output ═══ Use SAY to display a line of output. ──SAY──────┬──────────────┬────────;── └──expression──┘ Places expression on output device (terminal for foreground TSO or CMS; DDNAME SYSTSPRT for background TSO; command session or redirection or piping for OS/2. There is no REXX analog of the CLIST WRITENR statement or 'C' printf( ) with no "\n"; one could easily be provided as an external function if desired. ═══ 5.21. SELECT - Conditional Execution ═══ Use SELECT to choose among several options. ┌───────────────────────────────────────────┐  │ ──SELECT;─┴─WHEN──expression─┬─┬─THEN─┬─┬──instruction┴── └;┘ └;┘ ───┬────────────────────────────────────┬───END;──── └─OTHERWISE─┬─┬─┬───────────────────┬┘ └;┘ │ ┌─────────────┐ │ │  │ │ └──┴─instruction─┴──┘ SELECT is more convenient and readable in most cases than extended nested-IF logic. This is like a PL/I SELECT or EASEL switch; it is NOT like a C switch -- no drop-through of cases are allowed. PL/I programmers, be careful - this is very close, but not identical to your language; don't let your habits lead you astray here. Example: Select When environment = 'TSO' & REXX_manuals = "not available" then say "For now, you'd better write a CLIST." When environment = 'CMD' & REXX_manuals = "not available" then say "For now, you'd better write a .BAT style command list." When REXX_manuals = "not available" then say "Better write a program." Otherwise say 'A REXX exec should do the trick.' End /* Select */ ═══ 5.22. SIGNAL - Enable/Disable Execption Condition ═══ SIGNAL raises certain CONDITIONs to perform various error recovery functions. ──SIGNAL───┬─labelname───────────────────────────┬─────;─ ├─┬───────┬──expression───────────────┤ │ └─VALUE─┘ │ ├───OFF─────┬──ERROR──────┬───────────┤ │ ├──FAILURE────┤ │ │ ├──HALT───────┤ │ │ ├──NOVALUE────┤ │ │ ├──SYNTAX─────┤ │ │ └──NOTREADY───┘ │ │ │ └──ON──┬─ERROR───┬─┬────────────────┬─┘ ├─FAILURE─┤ └─NAME─trapname──┘ ├─HALT────┤ ├─NOVALUE─┤ ├─SYNTAX──┤ └─NOTREADY┘ Note: NOTREADY is for OS/2 only. NAME is not available on VM. Related Instructions: CALL, PROCEDURE Related Function: CONDITION( ) A special purpose instruction for dealing with CONDITIONs and condition traps; NOT a substitue for a GOTO statement, and NOT a general purpose error handling solution. Use to perform special-case, out-of-line processing, usually of a "windup-processing" or "fatal error" nature; any other use of SIGNAL impairs readability and maintenance, and should be avoided -- it probably WON'T do what you think it does, or at least the next person to maintain your code probably won't understand it. Consider using the "CALL ON condition NAME trapname" instead. ═══ 5.23. TRACE - Set Debugging Options ═══ TRACE supports the interactive debugging of REXX command procedures. ──TRACE──┬──────────────────────────────────────────┬──;─ ├────────number────────────────────────────┤ │ ┌───────────┐ │ │  │ │ └─┴─┬───────┬─┴─┬────────────────────────┬─┘ ├───?───┤ ├───'All'────────────────┤ └───!───┘ ├───'Commands'───────────┤ ├───'Error'──────────────┤ ├───'Failure'────────────┤ ├───'Intermediates'──────┤ ├───'Labels'─────────────┤ ├───'Normal'─────────────┤ ├───'Off'────────────────┤ ├───'Results'────────────┤ └───'Scan'───────────────┘ Or, alternatively: ──TRACE──┬────────────────────────────┬──;───────── ├────────symbol──────────────┤ └───┬───────┬───expression───┘ └─VALUE─┘ Note: Scan is for TSO and VM only. Failure is not available on VM; Negative may be used in place of Normal on VM only. You can use TRACE to perform a wide variety of tracing on REXX execs. The following TRACE symbols are supported. All All expressions a displayed before being exectued. Commands Host commands are displayed before being exectued. Error Host commands which return a non-zero return code are displayed after being executed. Failure Host commands which return a negative return code are displayed after being executed. This is the same as the Normal setting. Intermediate All expressions are displayed before being executed, intermediate results are also displayed. Labels Labels are displayed as they are reached. Normal Host commands which return a negative return code are displayed after being executed. This is the default. Off Stop tracing. Results All expressions are displayed before being executed as well as the end results. Scan Check syntax without processing the statements. Note: This is no longer supported under the SAA definition. Any of the above symbol values may be prefixed with the "?" to turn off that trace setting. ═══ 5.24. UPPER - Lower to Upper Case Conversion ═══ UPPER translates text to uppercase. ┌───────────┐  │ ────UPPER───┴─variable──┴───────;────────────────── Note: TSO and VM only. Use on variables or values prior to comparisons to implement case-insensitive checking. For greater portability, use the PARSE UPPER keyword instruction or the TRANSLATE( ) builtin function. ═══ 6. Rexx Builtin Functions ═══ This section details the syntax of the REXX builtin functions, and certain external functions that are supplied in particular environments. This part will talk about the general syntax of functions, and about function argument resolution, search order, error recovery, and will distinguish builtin vs external vs internal functions. The sections respective to each builtin function may be jumped to directly by selecting one of the names from the following list: o ABBREV( ) - Test String Abbreviation o ABS( ) - Return Absolute Value o ADDRESS( ) - Return Name of Current Environment o ARG( ) - Return Argument o BEEP( ) - Sound Alarm o BITAND( ) - Logical AND o BITOR( ) - Logical OR o BITXOR( ) - Logical XOR o B2X( ) - Bit to Hex Conversion o CENTER( ) - Center Data o CHARIN( ) - Read Character String o CHAROUT( ) - Write Character String o CHARS( ) - Return Status of Input Stream o CMSFLAG( ) - Return Status of CMSFLAG o COMPARE( ) - Compare Strings o CONDITION( ) - Return Condition o COPIES( ) - Duplicate String Data o CSL( ) - Call a routine in a Callable Services Library o C2D( ) - Character String to Decimal Conversion o C2X( ) - Character String to Hex Conversion o DATATYPE( ) - Determine Data Type o DATE( ) - Return System Date o DBCS( ) - Set DBCS Option o DELSTR( ) - Delete Substring o DELWORD( ) - Delete Words o DIAG( ) - Communicate with CP o DIAGRC( ) - Communicate with CP o DIGITS( ) - Return NUMERIC DIGITE Settings o DIRECTORY( ) - Change OS/2 Directory o D2C( ) - Decimal to Character String Conversion o D2X( ) - Decimal to Hex Conversion o ENDLOCAL( ) - End OS/2 Local Setting o ERRORTEXT( ) - Return Error Message Text o EXTERNALS( ) o FILESPEC( ) o FIND( ) - Search for Word o FORM( ) - Return NUMERIC FORM Setting o FORMAT( ) - Format Numeric Strings o FUZZ( ) - Return NUMERIC FUZZ Settings o GETMSG( ) o INDEX( ) - Search for Substring o INSERT( ) - Insert Substring o JUSTIFY( ) - Justify String of Words o LASTPOS( ) - Determine Last Position of Phrase o LEFT( ) - Left-Align String o LENGTH( ) - Return Length of String o LINEIN( ) - Read a Line o LINEOUT( ) - Write a Line o LINES( ) - Return Status of Input Stream o LINESIZE( ) - Return Width of Terminal o LISTDSI( ) - Determine Dataset Status o MAX( ) - Return Maximum Value From a Set o MIN( ) - Return Minimum Value From a Set o MSG( ) - Set MSG Option o OUTTRAP( ) - Trap TSO Display Output o OVERLAY( ) - Replace Phrase in a String o POS( ) - Search for Substring o PROMPT( ) - Set TSO PROMPT Option o QUEUED( ) - Return Number of Entries in Queue o RANDOM( ) - Return Random Number o REVERSE( ) - Reverse String o RIGHT( ) - Right-Align String o RXFUNCADD( ) - Add an External Function o RXFUNCDROP( ) - Drop an External Function o RXFUNCQUERY( ) - Query For an External Function o RXQUEUE( ) - Manipulate Queue o SETLANG( ) - Set International Language o SETLOCAL( ) - Set OS/2 Local Setting o SIGN( ) - Return Numeric Sign o SOURCELINE( ) - Return Program Line o SPACE( ) - Insert Fill-Character o STORAGE( ) o STREAM( ) - Stream Command o STRIP( ) - Remove Padding o SUBSTR( ) - Return Substring o SUBWORD( ) - Return Word From String o SYMBOL( ) - Return Status of Symbol o SYSDSN( ) - Return Status of Dataset o SYSVAR( ) - Return System Variable o TIME( ) - Return System Time o TRACE( ) - Return TRACE Mode o TRANSLATE( ) - Translate String o TRUNC( ) - Truncate Numeric Value o USERID( ) - Return Logon User ID o VALUE( ) - Return Content of Symbol o VERIFY( ) - Test Character String o WORD( ) - Get Word o WORDINDEX( ) - Return Word Position o WORDLENGTH( ) - Return Word Length o WORDPOS( ) - Return Word Position o WORDS( ) - Return Number of Words o XRANGE( ) - Define Range of Hex Values o X2C( ) - Hex to Character String Conversion o X2D( ) - Hex to Decimal Conversion ═══ 6.1. ABBREV( ) - Test String Abbreviation ═══ Use ABBREV for matching several variants of command names, parameter names, etc. ──ABBREV(information,info─┬──────────┬─)───────── └─,length──┘ Returns 1 if info value is a prefix of information value, and is at least length characters long, else 0. A null string (for info) is considered to match anything. Be careful about uppercase/lowercase -- the ABBREV functions is case sensitive. length defaults to the length of info. Examples: abbrev("BROWSE","BROWSER") returns 0 abbrev("BROWSE","BROWSE") returns 1 abbrev("BROWSE","BROWS") returns 1 abbrev("BROWSE","BROW") returns 1 abbrev("BROWSE","BRO") returns 1 abbrev("BROWSE","BR") returns 1 abbrev("BROWSE","B") returns 1 abbrev("BROWSE","") returns 1 abbrev("BROWSE","browse") returns 0 ═══ 6.2. ABS( ) - Return Absolute Value ═══ ABS returns the absolute value of a number formatted according to the current NUMERIC settings. ──ABS(number)──────────────────────────────────── Related Instruction: NUMERIC The parameter to ABS must be a valid number. Examples: abs(1) returns 1 abs(0) returns 0 abs(-1) returns 1 abs(.01) returns .01 abs("") gives an (OS/2) error like: 12 +++ Say 'abs("a") returns' abs('a'); REX0040: Error 40 running D:\Commands\TestREXX.cmd, line 12: Incorrect call to routine ═══ 6.3. ADDRESS( ) - Return Name of Current Environment ═══ ADDRESS returns the name of the current environment for "host" commands, e.g., CMD, CMS, TSO, ISREDIT, etc. ──ADDRESS( )───────────────────────────────────── Related Instruction: ADDRESS This function is used only to query the current environment, not to set it. ═══ 6.4. ARG( ) - Return Argument ═══ ARG returns the number of arguments, or the value of a specific argument. ──ARG(─┬───────────────────┬─)─────────────────── └─n──┬───────────┬──┘ └─,option───┘ Related Instructions: ARG PARSE ARG is used in receiving parameters passed to a main or subroutine REXX program. It is important to remember that REXX considers discrete arguments to have been separated by commas in the invocation. If n is omitted ,ARG returns the number of arguments passed . If no option is specified, ARG returns the nth argument string. If option "E" (Exists) is specified, returns 1 if nth argument exists; else 0. If option "O" (Omitted) is specified, returns 1 if nth argument was omitted, that is, does not exist; else 0. Example: ... call ArgTester "parm1",, "This is 3" ... ArgTester: procedure /* arg( ) returns 3 */ /* arg(1) returns <> */ /* arg(2) returns <<>> */ /* arg(3) returns <>*/ /* arg(4) returns <<>> */ /* arg(1,'E') returns 1 */ /* arg(2,'E') returns 0 */ /* arg(3,'E') returns 1 */ /* arg(4,'E') returns 0 */ /* arg(1,'O') returns 0 */ /* arg(2,'O') returns 1 */ /* arg(3,'O') returns 0 */ /* arg(4,'O') returns 1 */ return "" ═══ 6.5. BEEP( ) - Sound Alarm ═══ BEEP drives the speaker; this is basically just DosBeep. ──BEEP(frequency,duration)───────── Note: OS/2 only. Frequency is in Hertz in range [37..32767]. Duration is in milliseconds in range [1..60000]. On most machines, you can't really have a duration less than 32 ms. Note: Remember that in OS/2 the speaker is a serially reusable resource, for which there is no explicit synchronization provided. In other words, except for VERY brief passages, NEVER issue "beeps" from a process that doesn't have the input focus. No application "owns" the speaker. Musical Note Frequencies The western tempered scale musical notes, based on a concert pitch of A=440 Hz, and rounded to the nearest integral Hz, are shown below: C6 is middle C on the piano ; A6 is the "concert a." D3 37 D3sharp 39 E3flat 39 E3 41 F3 44 F3sharp 46 G3flat 46 G3 49 G3sharp 52 A3flat 52 A3 55 A3sharp 58 B3flat 58 B3 62 C4 65 C4sharp 69 D4flat 69 D4 73 D4sharp 78 E4flat 78 E4 82 F4 87 F4sharp 92 G4flat 92 G4 98 G4sharp 104 A4flat 104 A4 110 A4sharp 117 B4flat 117 B4 123 C5 131 C5sharp 139 D5flat 139 D5 147 D5sharp 156 E5flat 156 E5 165 F5 175 F5sharp 185 G5flat 185 G5 196 G5sharp 208 A5flat 208 A5 220 A5sharp 233 B5flat 233 B5 247 C6 262 C6sharp 277 D6flat 277 D6 294 D6sharp 311 E6flat 311 E6 330 F6 349 F6sharp 370 G6flat 370 G6 392 G6sharp 415 A6flat 415 A6 440 A6sharp 466 B6flat 466 B6 494 C7 523 C7sharp 554 D7flat 554 D7 587 D7sharp 622 E7flat 622 E7 659 F7 698 F7sharp 740 G7flat 740 G7 784 G7sharp 831 A7flat 831 A7 880 A7sharp 932 B7flat 932 B7 988 C8 1047 C8sharp 1109 D8flat 1109 D8 1175 D8sharp 1245 E8flat 1245 E8 1319 F8 1397 F8sharp 1480 G8flat 1480 G8 1568 G8sharp 1661 A8flat 1661 A8 1760 A8sharp 1865 B8flat 1865 B8 1976 C9 2093 C9sharp 2217 D9flat 2217 D9 2349 D9sharp 2489 E9flat 2489 E9 2637 F9 2794 F9sharp 2960 G9flat 2960 G9 3136 G9sharp 3332 A9flat 3332 A9 3520 A9sharp 3729 B9flat 3729 B9 3951 C10 4186 C10sharp 4435 D10flat 4435 D10 4699 D10sharp 4978 E10flat 4978 E10 5274 F10 5588 F10sharp 5920 G10flat 5920 G10 6272 G10sharp 6645 A10flat 6645 A10 7040 A10sharp 7459 B10flat 7459 B10 7902 C11 8372 C11sharp 8870 D11flat 8870 D11 9397 D11sharp 9956 E11flat 9956 E11 10548 F11 11175 F11sharp 11840 G11flat 11840 G11 12544 G11sharp 13290 A11flat 13290 A11 14080 A11sharp 14917 B11flat 14917 B11 15804 C12 16744 C12sharp 17740 D12flat 17740 D12 18795 D12sharp 19912 E12flat 19912 E12 21096 F12 22351 F12sharp 23680 G12flat 23680 G12 25088 G12sharp 26580 A12flat 26580 A12 28160 A12sharp 29834 B12flat 29834 B12 31609 Typical tempo: quarternote=120, so quarter note duration = 500 milliseconds. FULL 2000 HALF 1000 QUARTER 500 EIGHTH 250 SIXTEENTH 125 THIRTYSECOND 62 SIXTYFOURTH 31 ═══ 6.6. BITAND( ) - Logical AND ═══ BITAND does a logical AND of two strings on a bit-by-bit basis. ──BITAND(string1─┬───────────────────────┬─)───── └─,─┬────────┬─┬──────┬─┘ └─string2┘ └─,pad─┘ Related Functions: BITOR( ), BITXOR( ) Returns a string that is the result of ANDing the two input strings together, bit by bit. If a pad is specified, is extends the shorter of the two strings on the right. If no pad is specified, it defaults to '1111 1111'B. There are really two different kinds of operations that are encoded in BITAND. The first is simply doing an AND between two strings. The second, which you obtain by omitting string2, and supplying a pad is one in which the pad is ANDed with each character of the string1. Logical AND bit-by-bit operation: 0 1 ┌───┬───┐ 0 │ 0 │ 0 │ ├───┼───┤ 1 │ 0 │ 1 │ └───┴───┘ Examples: BITAND('C1 C2 C3'x, '12 34 56'x) returns '00 00 42'x BITAND('F7 F8 F9'x, '20'x, '2F'x) returns '20 28 29'x BITAND('F0 F1 F2'x,, '0F'x) returns '00 01 02'x ═══ 6.7. BITOR( ) - Logical OR ═══ BITOR does a logical OR of two strings on a bit-by-bit basis. ──BITOR(string1─┬───────────────────────┬─)────── └─,─┬────────┬─┬──────┬─┘ └─string2┘ └─,pad─┘ Related Functions: BITAND( ), BITXOR( ) Returns a string that is the result of ORing the two input strings together, bit by bit. If a pad is specified, is extends the shorter of the two strings on the right. If no pad is specified, it defaults to '0000 0000'B. There are really two different kinds of operations that are encoded in BITOR. The first is simply doing an OR between two strings. The second, which you obtain by omitting string2, and supplying a pad is one in which the pad is ORed with each character of the string1. Logical OR bit-by-bit operation: 0 1 ┌───┬───┐ 0 │ 0 │ 1 │ ├───┼───┤ 1 │ 1 │ 1 │ └───┴───┘ Examples: BITOR('C1 C2 C3'x, '12 34 56'x) returns 'D3 F6 D7'x BITOR('87 88 89'x, '20'x, '2F'x) returns 'A7 AF AF'x BITOR('41 42 43'x,, '20'x) returns '61 62 63'x ═══ 6.8. BITXOR( ) - Logical XOR ═══ BITXOR does a logical XOR (exclusive OR) of two strings on a bit-by-bit basis. ──BITXOR(string1─┬───────────────────────┬─)───── └─,─┬────────┬─┬──────┬─┘ └─string2┘ └─,pad─┘ Related Functions: BITAND( ), BITOR( ) Returns a string that is the result of XORing the two input strings together, bit by bit. If a pad is specified, is extends the shorter of the two strings on the right. If no pad is specified, it defaults to '1111 1111'B. There are really two different kinds of operations that are encoded in BITXOR. The first is simply doing an XOR between two strings. The second, which you obtain by omitting string2, and supplying a pad is one in which the pad is XORed with each character of the string1. Logical XOR bit-by-bit operation: 0 1 ┌───┬───┐ 0 │ 0 │ 1 │ ├───┼───┤ 1 │ 1 │ 0 │ └───┴───┘ Examples: BITXOR('C1 C2 C3'x, '12 34 56'x) returns 'D3 F6 95'x BITXOR('F7 F8 F9'x, '20'x, '2F'x) returns 'D7 D7 D6'x BITXOR('F0 F1 F2'x,, '0F'x) returns 'FF FE FD'x ═══ 6.9. B2X( ) - Bit to Hex Conversion ═══ B2X converts a character string containing ones and zeros into a character string containing hexadecimal characters. ──B2X(string)──────────────────────────────────── Note: Not in TSO or VM. Converts binary (bit) to hexadecimal. The binary string can contain zeros, ones, and blanks. The converted string only uses the upper case letters to represent the hexadecimal digits A-F. There will be no blanks in the converted string. Examples: B2X('11110001') returns 'F1' B2X('101') returns '5' B2X('1000 0010 1001 0001 1000 0010') returns '829182' ═══ 6.10. CENTER( ) - Center Data ═══ CENTER returns a string that is length characters long, and has string centered in it. ┌─CENTER(─┐ ──┤ ├──string──,length─┬───────┬─)───────── └─CENTRE(─┘ └─,pad──┘ When the string is shorter than the length, pad characters are added at both ends to center the string and bring it to the required length. CENTER operates as though the characters were added one at a time, first on the right, then on the left, another on the right, and so on. When the string is longer than the length, then characters are removed from both ends of the string until the string has been reduced to the required length. CENTER operates as though the characters were removed one at a time, first on the right, then on the left, another on the right, and so on. The default pad is the blank character. Examples: CENTER("ABC",8,'+') returns '++ABC+++' CENTER('Catastrophe',5) returns 'astro' CENTER('stints',0) returns '' CENTER('stints',1) returns 'i' CENTER('stints',2) returns 'in' CENTER('stints',3) returns 'tin' CENTER('stints',4) returns 'tint' CENTER('stints',5) returns 'stint' CENTER('stints',6) returns 'stints' CENTER('stints',7) returns 'stints ' CENTER('stints',8) returns ' stints ' Note: The British spelling (CENTRE) is due to the origins of REXX with IBMer Mike Cowlishaw from England. ═══ 6.11. CHARIN( ) - Read Character String ═══ CHARIN returns up to length characters from the character input stream name. ──CHARIN(─┬──────┬─┬───────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬─────────┬─┘ └─start──┘ └─,length─┘ Note: OS/2 has the only implementation; the new SAA REXX Level 2 specification includes this function. Related Functions: CHAROUT( ), CHARS( ) The stream name defaults to STDIN:, which is the default input stream. The default length is 1. There are two types of streams: transient and persistent. Transient streams are associated with devices, like the console, a printer, and STDIN:. Persistent streams have an existence after a close of the stream; files are persistent streams, for example. A current position is maintained for persistent streams. The default start for persistent streams is the current position, but any position that lies within the bounds of the character stream can be specified (1 to the length of the stream). A length of zero positions the stream, but returns the null string (no characters are read). Be careful using CHARIN( ) to read from the keyboard; your REXX program will not regain control until the Enter key has been pressed. It does NOT get control immediately after each press of a character. ═══ 6.12. CHAROUT( ) - Write Character String ═══ CHAROUT writes length characters to the name stream. ──CHAROUT(─┬──────┬─┬───────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬─────────┬─┘ └─start──┘ └─,length─┘ Note: OS/2 has the only implementation. It is included in the new SAA REXX Level 2 specification. Related Functions: CHARIN( ), CHARS( ) CHAROUT returns a count of any characters remaining after attempting to write to the the name stream. Any value other than 0 indicates some type of error ocurred, and the NOTREADY condition has been raised. The stream name defaults to STDOUT:, which is the default output stream. The default length is 1. There are two types of streams: transient and persistent. Transient streams are associated with devices, like the console, a printer, and STDOUT:. Persistent streams have an existence after a close of the stream; files are persistent streams, for example. A current position is maintained for persistent streams. The default start for persistent streams is the current position, but any position that lies within the bounds of the character stream can be specified (1 to the length of the stream). A length of zero positions the stream, but returns zero and no characters are written. Warning: The default initial position for output persistent streams is at the end of the stream. Repeated CHAROUT( ) operations append to the end of the stream. If you wish to overwrite a stream, you must explicitly set the position of the stream to one (e.g., call CHAROUT stream,,1). ═══ 6.13. CHARS( ) - Return Status of Input Stream ═══ CHARS either returns a 1 or a 0 depending on whether characters exist in the input stream name, or returns the actual number of characters remaining in the input stream. ──CHARS(─┬──────┬─)─── └─name─┘ Note: OS/2 has the only implementation. The new SAA REXX Level 2 specification includes it. Related Functions: CHARIN( ), CHAROUT( ) For transient streams, where it is impossible to determine the number of characters that remain, 0 means no more data, and 1 means there is more data. Example: /* Sample program to convert a file with */ /* only line ending LINEFEED characters */ /* to one with both Carriage Return and */ /* LINEFEED characters (e.g., Unix to */ /* DOS file conversion) */ LF = '0A'x /* linefeed character */ CR = '0D'x /* carriage return character */ arg instream outstream lastchar = "" /* Position outstream to beginning. */ call charout outstream,,1 do while chars(instream) \= 0 thischar = charin(instream) if thischar = LF, & lastchar \= CR then do call charout outstream, CR||LF end else do call charout outstream, thischar end lastchar = thischar end ═══ 6.14. CMSFLAG( ) - Return Status of CMSFLAG ═══ CMSFLAG returns information about the CMS environment in VM. ──CMSFLAG(flag)────────────────────────────────── Note: VM only. Returns 1 or 0 depending on flag. Use the CMS SET command to set flags ON or OFF, except as specfied: ┌──────────┬────────────────────────────────────────┐ │ Flag │ Definition │ ├──────────┼────────────────────────────────────────┤ │ ABBREV │ returns 1 if truncations will be │ │ │ accepted; else 0 │ ├──────────┼────────────────────────────────────────┤ │ AUTOREAD │ returns 1 if console read will be │ │ │ issued immediately after command │ │ │ execution; else 0 │ ├──────────┼────────────────────────────────────────┤ │ CMSTYPE │ returns 1 if console output will be │ │ │ displayed within the exec; else 0 │ ├──────────┼────────────────────────────────────────┤ │ DOS │ returns 1 if your virtual machine is │ │ │ in the DOS environment; else 0 │ ├──────────┼────────────────────────────────────────┤ │ EXECTRAC │ returns 1 if EXEC tracing is turned on;│ │ │ else 0 │ ├──────────┼────────────────────────────────────────┤ │ IMPCP │ returns 1 if commands not recognized by│ │ │ CMS will be passed to CP; else 0 │ ├──────────┼────────────────────────────────────────┤ │ IMPEX │ returns 1 if EXECs may be invoked by │ │ │ filename; else 0 │ ├──────────┼────────────────────────────────────────┤ │ PROTECT │ returns 1 if the CMS nucleus is │ │ │ storage-protected; else 0 │ ├──────────┼────────────────────────────────────────┤ │ RELPAGE │ returns 1 if pages are to be released │ │ │ following completion of certain │ │ │ commands; else 0 │ ├──────────┼────────────────────────────────────────┤ │ SUBSET │ returns 1 if you are in the CMS subset;│ │ │ else 0 - set by issuing SUBSET, reset │ │ │ using RETURN │ └──────────┴────────────────────────────────────────┘ ═══ 6.15. COMPARE( ) - Compare Strings ═══ COMPARE returns 0 if the two strings are equal, else the position of the leftmost mismatch. ──COMPARE(string1,string2─┬───────┬─)──────────── └─,pad──┘ The shorter of string1 and string2 is padded on the right with the pad character before performing the comparison. The default pad character is the blank. Examples: COMPARE('close','cigar') returns 2 COMPARE('microsoft','micro') returns 6 COMPARE('C','C ') returns 0 COMPARE('apples','oranges') returns 1 ═══ 6.16. CONDITION( ) - Return Condition ═══ CONDITION returns information about a trapped condition, or the null string if no condition is currently trapped. ──CONDITION(─┬────────┬─)──────────────────────── └─option─┘ Note: Not available on VM. Related Instructions: CALL, SIGNAL Related Functions: ERRORTEXT( ) The chart below summarizes the different options that are available: ┌────────────────┬──────────────────────────────────┐ │ Option │ Returns │ ├────────────────┼──────────────────────────────────┤ │ Condition name │ name of trapped condition │ ├────────────────┼──────────────────────────────────┤ │ Description │ descriptive string assoc'd w/trap│ ├────────────────┼──────────────────────────────────┤ │ Instruction │ CALL or SIGNAL (how raised) │ ├────────────────┼──────────────────────────────────┤ │ Status │ ON, OFF, or DELAY │ └────────────────┴──────────────────────────────────┘ Only the first, capitalized letter of option need be specified. CONDITION information is local to each subroutine level; the information is saved prior to calling a subroutine, and restored upon return. (PL/I programmers take note; conditions cannot percolate upward to different levels.) ═══ 6.17. COPIES( ) - Duplicate String Data ═══ COPIES returns n copies of the string, all strung together. ──COPIES(string,n)─────────────────────────────── The number n cannot be less than zero. Examples: COPIES("Tu",2) returns "TuTu" COPIES("nada",0) returns "" ═══ 6.18. CSL( ) - Call a routine in a Callable Services Library ═══ Refer to the IBM System Product Interpreter Reference for more information on the use of this function. ──CSL('rtname retcode─┬────────┬───────────────── │┌──────┐│ │ ││ └┴─parm─┴┘ VM only. ═══ 6.19. C2D( ) - Character String to Decimal Conversion ═══ C2D converts the binary representation of string to a decimal number. ──C2D(string─┬─────┬─)─────────────────────────── └─,n──┘ When n is not specified, an unsigned whole number is always returned. When n is specified, it represents the length of the binary number to be converted, in bytes. These numbers are assumed to represent signed two's complement numbers, and thus may return negative numbers. If the string is shorter than the length n it is extended on the left by binary zeroes; it is not sign extended. An error condition is raised when the result requires more precision than the current setting of NUMERIC DIGITS. Note: Because this function involves the binary representation of strings, it is heavily dependent on the character set and code page being used. Portable REXX programs should not make assumptions about this. Examples: C2D('A') returns 193 /* EBCDIC */ C2D('A',1) returns -63 /* EBCDIC */ C2D('A',2) returns 193 /* EBCDIC */ C2D('A') returns 65 /* ASCII */ C2D('A',1) returns 65 /* ASCII */ C2D('A',2) returns 65 /* ASCII */ C2D('2350'x) returns 9040 /* portable */ ═══ 6.20. C2X( ) - Character String to Hex Conversion ═══ C2X converts the binary representation of string to a decimal number. ──C2X(string)──────────────────────────────────── Converts character to hexadecimal, like you would see in a dump of a file. Examples: C2X('Aa.') returns 'C1814B' /* EBCDIC */ C2X('Aa.') returns '41612E' /* ASCII */ C2X('2350'x) returns '2350' ═══ 6.21. DATATYPE( ) - Determine Data Type ═══ DATATYPE classifies character strings as belonging to various lexical categories. ──DATATYPE(string─┬─────────┬─)────────────────── └──,type──┘ Related Instruction: NUMERIC If type is omitted, DATATYPE returns NUM when the string represents a valid REXX number (including decimals or floating point). It returns CHAR otherwise. When the type is specified, DATATYPE returns a 1 when the string is in the typed category, and 0 when it is not. For reasons that are beyond me, the null string is considered to be only a hexadecimal string, i.e., DATATYPE on the null string will return 0 for every type except X, in which case it will return a 1. ┌───────────────┬────────────────────────────────────────┐ │ Type │ Definition │ ├───────────────┼────────────────────────────────────────┤ │ Alphanumeric │ returns 1 if string has only chars in │ │ │ ranges a-z, A-Z, 0-9 │ ├───────────────┼────────────────────────────────────────┤ │ Bits │ returns 1 if string has only chars in │ │ │ ranges 0-1 │ ├───────────────┼────────────────────────────────────────┤ │ C │ returns 1 if string is a mixed SBCS/ │ OS/2, VM and TSO │ │ DBCS string │ ├───────────────┼────────────────────────────────────────┤ │ DBCS │ returns 1 if string is a pure DBCS │ OS/2, VM and TSO │ │ string │ ├───────────────┼────────────────────────────────────────┤ │ Lowercase │ returns 1 if string has only chars in │ │ │ range a-z │ ├───────────────┼────────────────────────────────────────┤ │ Mixed case │ returns 1 if string has only chars in │ │ │ ranges a-z and A-Z │ ├───────────────┼────────────────────────────────────────┤ │ Number │ returns 1 if string is a valid REXX │ │ │ number │ ├───────────────┼────────────────────────────────────────┤ │ Symbol │ returns 1 if string is a valid REXX │ │ │ symbol │ ├───────────────┼────────────────────────────────────────┤ │ Uppercase │ returns 1 if string has only chars in │ │ │ range A-Z │ ├───────────────┼────────────────────────────────────────┤ │ Whole number │ returns 1 if string is a REXX whole │ │ │ number │ ├───────────────┼────────────────────────────────────────┤ │ heXadecimal │ returns 1 if string has only chars in │ │ │ ranges a-f, A-F, 0-9, and blank │ │ │ │ │ │ also returns 1 for the null string │ └───────────────┴────────────────────────────────────────┘ Only the underscored, capitalized letter in the types above is required by DATATYPE. Examples: DATATYPE('654 ') returns 'NUM' DATATYPE('') returns 'CHAR' DATATYPE('12-1') returns 'CHAR' DATATYPE('abc','A') returns 1 DATATYPE('abc','N') returns 0 DATATYPE('a285839985a3 83968485','X') returns 1 DATATYPE('?X','S') returns 1 More examples, in a tabular form: ┌──────────┬────────────────────────────┐ │ │ type │ │ string ├──────┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┤ │ │(none)│A│B│C│D│L│M│N│S│U│W│X│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'123.45' │ NUM │0│0│0│0│0│0│1│1│0│0│0│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'-4e9' │ NUM │0│0│0│0│0│0│1│0│0│0│0│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'5e6' │ NUM │1│0│0│0│0│0│1│1│0│1│1│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'+1.' │ NUM │0│0│0│0│0│0│1│0│0│1│0│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'1' │ NUM │1│1│0│0│0│0│1│1│0│1│1│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'10101010'│ NUM │1│1│0│0│0│0│1│1│0│0│1│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'' │ CHAR │0│0│0│0│0│0│0│0│0│0│0│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'Ab' │ CHAR │1│0│0│0│0│1│0│1│0│0│1│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'MS' │ CHAR │1│0│0│0│0│1│0│1│1│0│0│ ├──────────┼──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'xy' │ CHAR │1│0│1│1│1│1│0│1│0│0│0│ └──────────┴──────┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ ═══ 6.22. DATE( ) - Return System Date ═══ DATE returns a variety of formats for the current date. ──DATE(─┬──────────┬─)─────────────────────────── └──option──┘ Related Functions: TIME( ) The default option is "Normal." All calls in the same statement return the same value. ┌────────┬─────────────────────────────────────────────────────┐ │ Option │ Example │ ├────────┼───────────┬─────────────────────────────────────────┤ │Basedate│726236 │days since Jan 1, 0001; date(b)//7 │no VM │ │ │gives 0-6, where 0 is Monday, 6 is Sunday│(R.4) ├────────┼───────────┼─────────────────────────────────────────┤ │Century │32642 │days since Jan 1 1900 (in next century, │TSO │ │ │will be days since Jan 1 2000) │VM ├────────┼───────────┼─────────────────────────────────────────┤ │Days │135 │days so far in year, including today │ ├────────┼───────────┼─────────────────────────────────────────┤ │European│15/05/89 │dd/mm/yy │ ├────────┼───────────┼─────────────────────────────────────────┤ │Julian │89135 │yyddd │TSO,VM ├────────┼───────────┼─────────────────────────────────────────┤ │Language│?????????? │date in an implementation & language │ │ │ │dependent format; assume NOTHING of its │OS/2 │ │ │internal structure -- use it as a whole │ ├────────┼───────────┼─────────────────────────────────────────┤ │Month │May │month of year, spelled out in English │ ├────────┼───────────┼─────────────────────────────────────────┤ │Normal │15 May 1989│preferred because there is no confusion │ │ │ │between European and USA conventions │ ├────────┼───────────┼─────────────────────────────────────────┤ │Ordered │89/05/15 │yy/mm/dd │ ├────────┼───────────┼─────────────────────────────────────────┤ │Sorted │ │ │ │ or │890515 │yyyymmdd │ │Standard│ │ │ ├────────┼───────────┼─────────────────────────────────────────┤ │Usa │05/15/89 │mm/dd/yy │ ├────────┼───────────┼─────────────────────────────────────────┤ │Weekday │Monday │day of week, English, mixed case │ └────────┴───────────┴─────────────────────────────────────────┘ Only the underscored, capitalized letter in the types above is required by DATE. Examples: DATE( ) returns 23 Sep 1990 DATE('B') returns 726732 DATE('D') returns 266 DATE('E') returns 23/09/90 /* Remember, you cannot rely on the */ /* format of the 'L' option date. */ DATE('L') returns 23 September 1990 /* OS/2 */ DATE('L') returns 90266 /* TSO,VM */ DATE('M') returns September DATE('N') returns 23 Sep 1990 DATE('O') returns 90/09/23 DATE('S') returns 19900923 DATE('U') returns 09/23/90 DATE('W') returns Sunday ═══ 6.23. DBCS( ) - Set DBCS Option ═══ There are some special DBCS functions; see the reference manuals. DBCS stands for Double Byte Character Set. DBCS is used for languages which are ideographic, like Japanese, Korean, and Chinese, et. al. DBADJUST DBBRACKET DBCENTER DBLEFT DBRIGHT DBRLEFT DBRRIGHT DBTODBCS DBTOSBCS DBUNBRACKET DBVALIDATE DBWIDTH DBJUSTIFY ═══ 6.24. DELSTR( ) - Delete Substring ═══ DELSTR removes length characters from a string starting at position n. ──DELSTR(string,n─┬───────────┬─)──────────────── └──,length──┘ The length defaults to the remainder of the string. Examples: DELSTR('carpet',4) returns 'car' DELSTR('carpet',4,1) returns 'caret' DELSTR('carpet',4,2) returns 'cart' DELSTR('carpet',1,3) returns 'pet' ═══ 6.25. DELWORD( ) - Delete Words ═══ DELWORD removes length number of blank-delimited words from a string starting with the nth word. ──DELWORD(string,n─┬───────────┬─)─────────────── └──,length──┘ The length defaults to the remainder of the string. Examples: DELWORD('response is not valid',3,1) returns 'response is valid' DELWORD('response is not valid',2) returns 'response' ═══ 6.26. DIAG( ) - Communicate with CP ═══ DIAG communicates with the CP via a dummy DIAGNOSE instruction. ──DIAG(n──┬───┬──┬───────────┬─)───────────────── └─?─┘ │┌─────────┐│ │ ││ └┴─,number─┴┘ Note: VM only. Related Functions: DIAGRC( ) See the VM manual for details. ═══ 6.27. DIAGRC( ) ═══ DIAGRC is like DIAG, except data returned is prefixed by return and condition codes. ──DIAGRC(n──┬───┬──┬───────────┬─)─────────────── └─?─┘ │┌─────────┐│ │ ││ └┴─,number─┴┘ Note: VM only. Related Functions: DIAG( ) See the VM manual for details. ═══ 6.28. DIGITS( ) - Return NUMERIC DIGITS Settings ═══ DIGITS returns the current NUMERIC DIGITS setting. ──DIGITS( )────────────────────────────────────── Related Instruction: NUMERIC DIGITS returns the maximum number of digits that can used for numbers in REXX programs, based on the current setting of NUMERIC DIGITS. The default NUMERIC DIGITS specification is 9. ═══ 6.29. DIRECTORY( ) - Change OS/2 Directory ═══ DIRECTORY returns and/or changes the current directory. ──DIRECTORY(──┬───────────────┬────────────────── └─newdirectory──┘ Note: OS/2 only. DIRECTORY returns the current directory, FIRST changing it to the newdirectory if it has been specified. It includes a drive letter; newdirectory can optionally contain a drive letter, in which case the drive is also changed, not just the directory. CAUTION: This function is somewhat unusual compared to other similarly structured REXX functions in that the value returned is the new value, not the old value. ═══ 6.30. D2C( ) - Decimal to Character String Conversion ═══ D2C converts a number to the character string whose binary representation is the number. ──D2C(wholenumber─┬─────┬─)────────────────────── └─,n──┘ If the number n (the length of the final result) is omitted, then the input wholenumber must not be negative. The result returned is the minimum number of characters whose binary representation is the number. When n is specified, it indicates what the length of the final result should be. If n is longer than it needs to be to express the number in binary, then the result is sign extended on the left (negative numbers being represented in two's complement notation). If n is shorter than it needs to be to fully express the number in binary, then the result is simply truncated from the left. Examples: D2C(193) returns 'C1'x /* 'A' in EBCDIC */ D2C(65) returns '41'x /* 'A' in ASCII */ D2C(-1) returns /* illegal */ D2C(-1,2) returns 'FFFF'x D2C(-1,4) returns 'FFFFFFFF'x D2C(10000012,4) returns '0098968C'x D2C(9040) returns '2350'x D2C(9040,1) returns '50'x D2C(9040,2) returns '2350'x D2C(9040,3) returns '002350'x D2C(9040,4) returns '00002350'x ═══ 6.31. D2X( ) - Decimal to Hex Conversion ═══ D2X converts a number to hexadecimal. ──D2X(wholenumber─┬─────┬─)────────────────────── └─,n──┘ If n (the length in characters of the result) is omitted, then the wholenumber must not be negative, and the result is as long as it needs to be without using leading zeros. When n is specified and longer than it needs to be, then the result is sign-extended on the left (two's complement notation). When n is specified and shorter than it needs to be, the result is truncated on the left. Examples: D2X(193) returns 'C1' D2X(193,1) returns '1' D2X(193,2) returns 'C1' D2X(193,3) returns '0C1' D2X(193,4) returns '00C1' D2X(-1) returns /* illegal */ D2X(-1,1) returns 'F' D2X(-1,2) returns 'FF' D2X(-1,3) returns 'FFF' D2X(-1,4) returns 'FFFF' C2X(D2C(number,n)) returns D2X(number,2*n) ═══ 6.32. ENDLOCAL( ) - End OS/2 Local Setting ═══ ENDLOCAL undoes the effect of the last SETLOCAL. ──ENDLOCAL( )────────────────────── Note: OS/2 only. Related Functions: SETLOCAL( ) ENDLOCAL returns 1 for a succesful restore of the drive, directory, and environment variables. It returns 0 if there was no previous SETLOCAL, or for any other failure. Note: SETLOCAL and ENDLOCAL can be nested in REXX programs; this is not possible in regular batch procedures. If a REXX program that issues SETLOCAL ends without calling ENDLOCAL, an implicit ENDLOCAL is performed at termination. Example: call setlocal oldpath = value('path',,'OS2ENVIRONMENT') call value 'path',, newpathpart';'oldpath,, 'OS2ENVIRONMENT' ... /* do some things with new path */ ... call endlocal ═══ 6.33. ERRORTEXT( ) - Return Error Message Text ═══ ERRORTEXT returns the error message text for REXX error message n. ──ERRORTEXT(n)─────────────────────────────────── Related Functions: CONDITION( ) Most implementations use identical text and meaning for all REXX error codes less than 50. The SAA specification only lists error messages from 1 to 50. Error Messages 1: File Table full 2: Interpret expression > 64000 characters 3: Program is unreadable 4: Program interrupted 5: Machine resources exhausted 6: Unmatched "/*" or quote 7: WHEN or OTHERWISE expected 8: Unexpected THEN or ELSE 9: Unexpected WHEN or OTHERWISE 10: Unexpected or unmatched END 11: Control stack full 12: Clause too long 13: Invalid character in program 14: Incomplete DO/SELECT/IF 15: Invalid hexadecimal or binary string 16: Label not found 17: Unexpected PROCEDURE 18: THEN expected 19: String or symbol expected 20: Symbol expected 21: Invalid data on end of clause 22: Invalid character string 23: Invalid data string 24: Invalid TRACE request 25: Invalid sub-keyword found 26: Invalid whole number 27: Invalid DO syntax 28: Invalid LEAVE or ITERATE 29: Environment name too long 30: Name or string too long 31: Name starts with number or "." 32: Invalid use of stem 33: Invalid expression result 34: Logical value not 0 or 1 35: Invalid expression 36: Unmatched "(" in expression 37: Unexpected "," or ")" 38: Invalid template or pattern 39: Evaluation stack overflow 40: Incorrect call to routine 41: Bad arithmetic conversion 42: Arithmetic overflow/underflow 43: Routine not found 44: Function did not return data 45: No data specified on function RETURN 46: Invalid variable reference 48: Failure in system service 49: Interpretation error 115: The RXSUBCOM parameters are incorrect 116: The RXSUBCOM parameter REGISTER is incorrect 117: The RXSUBCOM parameter DROP is incorrect 118: The RXSUBCOM parameter LOAD is incorrect 119: Invalid file name ═══ 6.34. EXTERNALS( ) ═══ EXTERNALS returns the number of elements in the terminal input buffer (type-ahead). ──EXTERNALS( )─────────────────────────────────── Note: In TSO always returns 0. ═══ 6.35. FILESPEC( ) ═══ FILESPEC can return the drive, the directory, or the filename of a given file specification. ──FILESPEC(option,filespec)────────────── Note: OS/2 only. This is only guaranteed to work on file specifications that are valid. The valid options are: o Drive o Path o Name Only the first character of each option need be specified. The drive is identified as anything up to and including the first colon (:) in the filespec. The path is identified as anything from the first character after the colon (or the absolute first character, if no colon is present) in the filespec up to and including the last slash (/) or backslash (\). The name is identified as anything after the last slash or backslash or colon through the end of the filespec. Since this is entirely driven by delimiters, no considerations of IFS or HPFS long names or special characters, or even of valid characters, enter into the processing. Examples: filespec("d","C:CONFIG.SYS") returns "C:" filespec("p","C:CONFIG.SYS") returns "" filespec("n","C:CONFIG.SYS") returns "CONFIG.SYS" filespec("d","C:\CONFIG.SYS") returns "C:" filespec("p","C:\CONFIG.SYS") returns "\" filespec("n","C:\CONFIG.SYS") returns "CONFIG.SYS" filespec("D","C:/os2\cmd.Exe") returns "C:" filespec("P","C:/os2\cmd.Exe") returns "/os2\" filespec("N","C:/os2\cmd.Exe") returns "cmd.exe" filespec("D","abc\def") returns "" filespec("P","abc\def") returns "abc\def" filespec("N","abc\def") returns "" filespec("D","abc\def:g:a.b/c") returns "abc\def:" filespec("P","abc\def:g:a.b/c") returns "abc\def:g:a.b/" filespec("N","abc\def:g:a.b/c") returns "c" ═══ 6.36. FIND( ) - Search for Word ═══ FIND is the same as WORDPOS(phrase, string). ──FIND(string,phrase)──────────────────────────── Related Functions: WORDPOS( ) Same as WORDPOS(phrase,string); WORDPOS is prefered but may not be implemented in older versions. ═══ 6.37. FORM( ) - Return NUMERIC FORM Settings ═══ FORM returns the current setting of NUMERIC FORM (SCIENTIFIC or ENGINEERING). ──FORM( )──────────────────────────── Related Instructions: NUMERIC ═══ 6.38. FORMAT( ) - Format Numeric Strings ═══ FORMAT prepares a number for display, rounding and formatting. ──FORMAT(number─┬───────────────────────────────────────────┬─)─ └─,─┬──────┬─┬─────────────────────────────┬┘ └before┘ └,─┬─────┬─┬─────────────────┬┘ └after┘ └─,─┬────┬─┬─────┬┘ └expp┘ └expt┘ Related Instruction: NUMERIC Note: VM (R.4) does not implement expp and expt. The before and after specify how many positions to use before and after the decimal point, respectively. These default to using as many positions as are needed. The expp specifies exponent precision, or number of places in the exponent; the default is to use as many as are necessary. The expt specifies the exponent trigger. Examples: FORMAT('3',4) returns ' 3' FORMAT('2.7128',2,0) returns ' 3' FORMAT('2.7128',2,3) returns ' 2.713' FORMAT('-2.7128',2,5) returns '-2.71280' FORMAT('3.14159262',0,4) returns '.1416' ═══ 6.39. FUZZ( ) - Return NUMERIC FUZZ Settings ═══ ──FUZZ( )──────────────────────────────────────── Related Instructions: NUMERIC Returns current setting of NUMERIC FUZZ. Examples: FUZZ() returns 0 /* by default */ ═══ 6.40. GETMSG( ) ═══ Retrieves session console messages. ──GETMSG(msgstem─┬─────────────────────────────────────────┬─)─ └,─┬────────┬─┬───────────────────────────┤ └,msgtype┘ └,─┬─────┬─┬────────────────┤ └,cart┘ └,─┬─────┬─┬─────┤ └,mask┘ └,time┘ Note: Available on TSO only. Refer to the TSO Extensions Version 2 Procedures Language MVS / REXX Reference manual for a full description of this function. ═══ 6.41. INDEX( ) - Search for Substring ═══ ──INDEX(haystack,needle──┬─────────┬─)─────────── └─,start──┘ Returns position of leftmost needle string in haystack string, starting from position start in haystack, or returns 0 if needle is not found. Note: This function has been replaced in the SAA specification by the POS( ) function. POS( ) should be used wherever possible for future compatibility. Examples: INDEX('abracadabra','dab') returns 7 INDEX('abracadabra','dba') returns 0 INDEX('abracadabra','ab') returns 1 INDEX('abracadabra','ab',2) returns 8 INDEX('abracadabra','ab',9) returns 0 ═══ 6.42. INSERT( ) - Insert Substring ═══ ──INSERT(new,target─┬─────────────────────────────┬─)─────────── └─,─┬───┬─┬──────────────────┬┘ └─n─┘ └─,─┬──────┬─┬────┬┘ └length┘ └,pad┘ Inserts length characters of new string into the target string, padding with the pad string, after position n in the target string; n defaults to 0, i.e., insert before the beginning of target. The default pad is the blank character. Examples: INSERT('abcd','efg') returns 'abcdefg' INSERT('abcd','efg',3) returns 'efgabcd' INSERT(' ','efg',2) returns 'ef g' INSERT('second','first',9,8,'*') returns 'first***second**' ═══ 6.43. JUSTIFY( ) - Justify String of Words ═══ ──JUSTIFY(string,length──┬───────┬─)───────────── └─,pad──┘ Takes the words (blank-delimited) in string, and spreads them out evenly to a length of length by inserting blanks between words. If length is less than the length of string, truncate letters on the right. Examples: JUSTIFY('This is balanced.',21) returns 'This is balanced.' ═══ 6.44. LASTPOS( ) - Determine Last Position of Phrase ═══ ──LASTPOS(needle,haystack──┬─────────┬─)───────── └─,start──┘ Related Functions: POS( ) Returns the position of the rightmost occurrence of the needle string in the haystack string, or returns 0 if not found; start is the rightmost character which the is to be scanned in the right to left direction. start defaults to the last position in haystack. Examples: LASTPOS('abra','abracadabra') returns 8 ═══ 6.45. LEFT( ) - Left-Align String ═══ ──LEFT(string,length──┬───────┬─)──────────────── └─,pad──┘ Related Functions: RIGHT( ) Returns the leftmost length characters of string, padded, if necessary, with pad. The default pad is the blank character. Examples: LEFT('abracadabra',2) returns 'ab' LEFT('a',4)LEFT('b',4)'c' returns 'a b c' ═══ 6.46. LENGTH( ) - Return Length of String ═══ ──LENGTH(string)───────────────────────────────── Returns the length of string. Examples: LENGTH('ab c') returns 4 LENGTH('ab c ') returns 6 LENGTH('') returns 0 ═══ 6.47. LINEIN( ) - Read a Line ═══ ──LINEIN(─┬──────┬─┬───────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬────────┬──┘ └─start──┘ └─,count─┘ Related Functions: LINEOUT( ), LINES( ) Note: OS/2 has the only implementation. Returns a line from the input stream name. The count defaults to 1. Count is 0 or 1. ═══ 6.48. LINEOUT( ) - Write a Line ═══ ──LINEOUT(─┬──────┬─┬──────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬───────┬──┘ └─string─┘ └─,line─┘ Related Functions: LINEIN( ), LINES( ) Note: OS/2 has the only implementation. Returns count of lines remaining after attempting to write to the the name stream. Any value other than 0 indicates some type of error ocurred. 1 is only value other than 0. If name is omitted, the default output stream (STDOUT:) is used. The default positioning for output streams is at the end of the file. E.g., use: call lineout(myfile,,1) to open file, if not already open, and position to the beginning of the file. ═══ 6.49. LINES( ) - Return Status of Input Stream ═══ ──LINES(─┬──────┬─)─── └─name─┘ Related Functions: LINEIN( ), LINEOUT( ) Note: OS/2 has the only implementation. Returns 1 if any data is remaining in the input stream between the current positions and the end. name defaults to "STDIN:". The following is a common construct to copy a file: Example: call lineout outfile,,1 /* open, position to end */ do while lines(myfile) call linein myfile, thisline call lineout myfile, thisline end ═══ 6.50. LINESIZE( ) - Return Width of Terminal ═══ ──LINESIZE( )──────────────────────────────────── Note: VM and TSO only. Returns the terminal line width - 1; in background TSO, always returns 132. When in full-screen VM, always returns 999999999. ═══ 6.51. LISTDSI( ) - Determine Dataset Status ═══ ──LISTDSI(─┬─dsn─┬──────────┬─┬─┬───────────┬─┬────────┬─── │ └─location─┘ │ └─directory─┘ └─recall─┘ └─filename────type─┘ Note: TSO only. Returns information about the data set specified by dsn. The following REXX variables are assigned values on successful execution: SYSDSNAME The data set name. SYSVOLUME The data set volume serial number. SYSUNIT The unit of the volume serial number. SYSDSORG "PS" for sequential; "PO" for partitioned; "DA" for direct; "VS" for VSAM. SYSRECFM "F" for fixed; "V" for variable; "A" for asa printer control; "B" for blocked. SYSRECL The logical record length. SYSBLKSIZE The block size ("VS" for VSAM). SYSKEYLEN The key length. SYSALLOC The space allocation. SYSUSED The space used. SYSPRIMARY The primary space allocation. SYSSECONDS The secondary space allocation. SYSUNITS The space units ("CYLINDER", "TRACK" or "BLOCK"). SYSEXTENTS The space extents used. SYSCREATE The creation date. SYSREFDATE The last reference date. SYSEXDATE The expiration date. SYSPASSWORD The type of password protection ("NONE", "READ" or "WRITE"). SYSRACFA The type of RACF protection ("NONE", "GENERIC" or "DISCRETE"). SYSUPDATED Data set updated ("YES" or "NO"). SYSTRKSCYL The tracks per cylinder on the volume. SYSBLKSTRK The number of blocks per track on the volume. SYSADIRBLK The number of directory blocks allocated. SYSUDIRBLK The number of directory blocks used. SYSMEMBERS The number of partitioned members. SYSREASON The reason code for command failure. SYSMSGLVL1 The first level error message. SYSMSGLVL2 The second level error message. Returns 0 if the function was successful, 16 if not. ═══ 6.52. MAX( ) - Return Maximum Value From a Set ═══ ──MAX(number─┬───────────┬─)───────────────────── │┌─────────┐│ │ ││ └┴─,number─┴┘ Related Instruction: NUMERIC Returns the largest number in the list; up to 20 can be specified; for more, can nest MAX( ) calls; can not be used with non-numeric arguments. (On VM, up to 10 numbers can be specified). ═══ 6.53. MIN( ) - Return Minimum Value From a Set ═══ ──MIN(number─┬───────────┬─)───────────────────── │┌─────────┐│ │ ││ └┴─,number─┴┘ Related Instruction: NUMERIC Returns the smallest number in the list; up to 20 can be specified; for more, can nest MIN( ) calls; can not be used with non-numeric arguments. (On VM, up to 10 numbers can be specified). ═══ 6.54. MSG( ) - Set TSO MSG Option ═══ ──MSG(─┬─────┬─)───────────────────────────────── ├─ON──┤ └─OFF─┘ Returns and/or sets the value of the TSO MSG setting. The MSG setting determines whether or not TSO messages are displayed. The return value will be either ON or OFF. Note: TSO only. ═══ 6.55. OUTTRAP( ) - Trap TSO Display Output ═══ ──OUTTRAP(─┬────────────────────────────────┬──────── ├─OFF────────────────────────────┤ └─varname─┬─────┬─┬──────────────┤ └─max─┘ └─,─┬────────┬─┘ └─concat─┘ Note: TSO only. Turns on the capture of display output from TSO commands. Each display line is captured in a different element of the array formed from varname (a period at the end of varname is required). varname.0 will contain the number of elements in the array on successful execution. The OFF keyword discontinues the trapping of TSO commands. ═══ 6.56. OVERLAY( ) - Replace Phrase in String ═══ ──OVERLAY(new,target─┬─────────────────────────────┬─)────────── └─,─┬───┬─┬──────────────────┬┘ └─n─┘ └─,─┬──────┬─┬────┬┘ └length┘ └,pad┘ Overlays length characters in target starting at position n with characters from string new, padded if necessary with pad; the length defaults to the length of new. The default pad is the blank character. If n is not given then 1 is the default. Example: OVERLAY(' ','invalid') returns ' valid' OVERLAY('1',OVERLAY('2','Version 1 Release 4',9),19) returns 'Version 2 Release 1' ═══ 6.57. POS( ) - Search for Substring ═══ ──POS(needle,haystack──┬─────────┬─)───────────── └─,start──┘ Related Functions: LASTPOS( ) Returns the leftmost position of the needle string in the haystack string, starting at the start position; returns 0 if the needle string is not found. If start is not given then 1 is the default. Example: POS('/','09/23/52') returns 3 POS('/','09/23/52',4) returns 5 POS('6','09/23/52',4) returns 0 ═══ 6.58. PROMPT( ) - Set TSO PROMPT Option ═══ ──PROMPT(─┬─────┬─)────────────────────────────── ├─ON──┤ └─OFF─┘ Returns and/or sets the value of the TSO PROMPT setting. The PROMPT setting determines TSO commands can prompt or not. The return value will be either ON or OFF. Note: TSO only. ═══ 6.59. QUEUED( ) - Return Number of Entries in Queue ═══ ──QUEUED( )────────────────────────────────────── Related Instructions: PARSE, PULL, PUSH, QUEUE Related Function: RXQUEUE( ) Returns the number of lines in the data stack (see the TSO/E REXX User's Guide for a complete discussion of all the things you can do with the data stack; the data stack should not be confused with the old TSO command stack). Also available on VM: returns the number of lines in the program stack. ═══ 6.60. RANDOM( ) - Return Random Number ═══ ──RANDOM(─┬──────────────────────────┬─)───────── ├─max──────────────────────┤ ├─min,─┬─┬─────┬─┬───────┬─┘ └─,────┘ └─max─┘ └─,seed─┘ Returns a pseudo-random whole number in the range MAX(0,min) to max; min defaults to 0, and max defaults to 999; the seed can be used to obtain repeatable results for testing; useful for simulation and modeling applications. The singular max option is not available on VM. ═══ 6.61. REVERSE( ) - Reverse String ═══ ──REVERSE(string)──────────────────────────────── Reverses the order of characters in a string; can be used with functions that work left to right to create versions that work right to left. Examples: REVERSE('stop') returns 'pots' REVERSE('oprah') returns 'harpo' REVERSE('radar') returns 'radar' ═══ 6.62. RIGHT( ) - Right-Align String ═══ ──RIGHT(string,length──┬───────┬─)─────────────── └─,pad──┘ Related Functions: LEFT( ) Returns the rightmost length characters of string, padded, if necessary, with pad. The default pad is the blank character. Examples: RIGHT('example',5) returns 'ample' RIGHT('a',4)RIGHT('b',4)'c' returns ' a bc' ═══ 6.63. RXFUNCADD( ) - Add an External Function ═══ RXFUNCADD adds the function name, making it available to REXX procedures. ──RXFUNCADD(name, module, procedure)───────────── Related Functions: RXFUNCDROP( ), RXFUNCQUERY( ) name is the name you wish the new REXX procedure to be known by. module is the filename of the OS/2 DLL that contains the procedure to be invoked when the new function is referenced by REXX. The DLL must reside in the OS/2 LIBPATH. The function returns 0 (zero) if name was successfully registered; 1 (one) otherwise. Examples: if rxfuncquery('RXCLS') then do if rxfuncadd('RXCLS', 'REXXUTIL', 'RXCLS_FUNC') then do say 'Unable to add RXCLS function.' exit end end ... call rxcls ... call rxfuncdrop 'RXCLS' ═══ 6.64. RXFUNCDROP( ) - Drop an External Function ═══ RXFUNCDROP drops the function name, making it unavailable to REXX procedures. ──RXFUNCDROP(name)─────────────────────────────── Related Functions: RXFUNCADD( ), RXFUNCQUERY( ) name is the name of the REXX function you wish to drop. The function name must have been previously registered to REXX via the RXFUNCADD( ) function. The function returns 0 (zero) if name was successfully dropped; 1 (one) otherwise. Examples: if rxfuncquery('RXCLS') then do if rxfuncadd('RXCLS', 'REXXUTIL', 'RXCLS_FUNC') then do say 'Unable to add RXCLS function.' exit end end ... call rxcls ... call rxfuncdrop 'RXCLS' ═══ 6.65. RXFUNCQUERY( ) - Query For an External Function ═══ RXFUNCQUERY queries whether or not the name function has been registered via RXFUNCADD( ). ──RXFUNCQUERY(name)────────────────────────────── Related Functions: RXFUNCADD( ), RXFUNCDROP( ) name is the name you used to register the function by with RXFUNCADD( ). The function returns 0 (zero) if name is available; 1 (one) otherwise. Examples: if rxfuncquery('RXCLS') then do if rxfuncadd('RXCLS', 'REXXUTIL', 'RXCLS_FUNC') then do say 'Unable to add RXCLS function.' exit end end ... call rxcls ... call rxfuncdrop 'RXCLS' ═══ 6.66. RXQUEUE( ) - Manipulate Queue ═══ RXQUEUE is used to manipulate external data queues. ──RXQUEUE(─┬─'Get'─────────────────────┬─)─────── ├─'Set'──────newqueuename───┤ ├─'Delete'───queuename──────┤ └─'Create'─┬──────────────┬─┘ └──,queuename──┘ Related Instructions: PARSE, PUSH, QUEUE Related Function: QUEUED( ) This function is used to create and delete queues and to set and query their names. The first parameter determines the function performed. Parameters: Create Creates a queue with the name, queuename (if specified); If no name is specified, then REXX will provide a name. Returns the name of the queue in either case. Delete Deletes the named queue; returns 0 (zero) if successful, a non-zero number if an error occurs; the possible return values are: 0 Queue has been deleted. 5 Not a valid queue name. 9 Queue named does not exist. 10 Queue is busy; wait is active. 12 A memory failure has occurred. 1000 Initialization error; chek file OS2.INI. Get Returns the name of the queue currently in use. Set Sets the name of the current queue to newqueuename and returns the previous name of the queue. Examples: if rxfuncquery('RXCLS') then ═══ 6.67. SETLANG( ) - Set International Language ═══ Sets/returns the three character code indicating the language in which REXX messages are currently being displayed. ──SETLANG(─┬──────────┬─)────────── └─langcode─┘ Note: TSO only. The following values are the valid for langcode. CHS Simplified Chinese CHT Traditional Chinese DAN Danish DEU German ENP US English - all upper case ENU US English - mixed case ESP Spanish FRA French JPN Japanese KOR Korean PTB Brazilian Portuguese Example: call setlocal if setlang() <> 'ENU' then do oldlang = setlang() call setlang 'ENU' end ═══ 6.68. SETLOCAL( ) - Set OS/2 Local Setting ═══ SETLOCAL creates a local environment until the next ENDLOCAL is executed. ──SETLOCAL( )────────────────────── Note: OS/2 only. Related Functions: ENDLOCAL( ) SETLOCAL returns 1 for a succesful store of the drive, directory, and environment variables. It returns 0 if unsuccessful. Note: SETLOCAL and ENDLOCAL can be nested in REXX programs; this is not possible in regular batch procedures. If a REXX program that issues SETLOCAL ends without calling ENDLOCAL, an implicit ENDLOCAL is performed at termination. Example: call setlocal oldpath = value('path',,'OS2ENVIRONMENT') call value 'path',, newpathpart';'oldpath,, 'OS2ENVIRONMENT' ... /* do some things with new path */ call endlocal ═══ 6.69. SIGN( ) - Return Numeric Sign ═══ ──SIGN(number)─────────────────────────────────── Returns -1 if negative, +1 if positive, 0 if zero. ═══ 6.70. SOURCELINE( ) - Return Program Line ═══ ──SOURCELINE(─┬─────┬─)────────────────────────── └──n──┘ Returns the nth line of the REXX exec currently executing; returns the number of source lines if n is omitted; useful in error reporting procedures in production REXX execs. ═══ 6.71. SPACE( ) - Insert Fill-Character ═══ ──SPACE(string─┬─────────────────────┬─)───────── └─,──┬───┬─┬────────┬─┘ └─n─┘ └──,pad──┘ Reformats the words in string by placing exactly n copies of pad between each word. The default pad is the blank character. n defaults to 1. Example: SPACE('a b cd',3) returns 'a b cd' SPACE('a b cd',0) returns 'abcd' SPACE('This is an example') returns 'This is an example' ═══ 6.72. STORAGE( ) ═══ ──STORAGE(─┬─────────┬─┬────────────────────────┬─)─ └─address─┘ └─,─┬────────┬─┬───────┬─┘ └─length─┘ └─,data─┘ Note: VM only. If no arguments are specified, returns the current virtual machine size. Otherwise, returns length bytes from your virtual machine's memory starting at address. If data is specified, storage starting at address is over-written for length, but not past the end of your virtual machine. Consult the VM manual before using this option. ═══ 6.73. STREAM( ) - Stream Command ═══ ──STREAM(name─┬───────────────────────────┬─)──── └─,──┬────────────────────┬─┘ ├─C,──streamcommand──┤ ├─D──────────────────┤ └─S──────────────────┘ Note: OS/2 has the only implementation. Returns a string describing the state of, or result of an operation on the character stream name. Command Issue a stream command. The following commands are available under OS/2: 'OPEN' Opens a named stream. The words 'READ' and 'WRITE' may optionally be appended to 'OPEN' to specifiy those conditions. 'CLOSE' Closes the named stream. 'SEEK offset' Sets the read or write position to a given offset within a persistent stream. The offset may be prefixed with the following: = Explicit offset. < Specifies offset from the end of the stream. + Specifies offset forward from the current position. - Specifies offset backward from the current position. 'QUERY EXISTS' Returns the full path specification of the persistent stream if it exists, else returns the null string. 'QUERY SIZE' Returns the size in bytes of the persistent stream if it exists, else returns 0. 'QUERY DATETIME' Returns the date and time stamps of the stream. Description Identical to the STATE option except that the returned string is followed by a colon and, if available, additional information about the ERROR or NOTREADY state. State Returns the following strings: 'ERROR' An error in a stream operation has taken place. 'NOTREADY' A stream is in a state in which a requested operation would raise the NOTREADY condition. 'READY' Normal operations are available for the stream. 'UNKNOWN' The stream in is an unknown state. Only the first character of each option need be specified. Examples: state = STREAM(myfile) state = STREAM(myfile, 'S') state = STREAM(myfile, 'D') state = STREAM(myfile, 'C', 'OPEN') state = STREAM(myfile, 'C', 'CLOSE') size = STREAM(myfile, 'QUERY SIZE') ═══ 6.74. STRIP( ) - Remove Padding ═══ ──STRIP(string─┬──────────────────────────┬─)──── └─,──┬────────┬─┬────────┬─┘ └─option─┘ └──,char─┘ Removes the leading and/or trailing char from the string; the options are: o Leading o Trailing o Both (default) Only the first character of each option need be specified. The default char is the blank character. Examples: STRIP('0000981.3',L,0) returns '981.3' STRIP(' how are you? ') returns 'how are you?' A useful combination is: SPACE(STRIP(' how are you? ')) returns 'how are you?' ═══ 6.75. SUBSTR( ) - Return Substring ═══ ──SUBSTR(string,n─┬────────────────────────┬─)─── └─,──┬────────┬─┬──────┬─┘ └─length─┘ └─,pad─┘ Returns length characters from string starting at position n and padding, if necessary, with pad. The length defaults to the rest of the string; the pad defaults to a blank. Examples: SUBSTR('basic',2,3) returns 'asi' SUBSTR('basic',2) returns 'asic' SUBSTR('DTSS CO',6,5,'.') returns 'CO...' ═══ 6.76. SUBWORD( ) - Return Word From String ═══ ──SUBWORD(string,n─┬──────────┬─)──────────────── └─,length──┘ Returns length number of blank-delimited words from string, starting at word n; length defaults to the rest of the string. Examples: SUBWORD('A quick brown ',2) returns 'quick brown' SUBWORD('A quick brown ',2,1) returns 'quick' SUBWORD('A quick brown ',4,1) returns '' ═══ 6.77. SYMBOL( ) - Return Status of Symbol ═══ ──SYMBOL(name)─────────────────────────────────── Returns the class of the symbol represented by name; returns "BAD" if the name is not a valid REXX symbol (variable name or constant); returns "LIT" if it is a constant, or a variable that has never been assigned a value; returns "VAR" if the symbol represents the name of a variable that has been assigned a value. ═══ 6.78. SYSDSN( ) - Return Status of Dataset ═══ ──SYSDSN(dsn)──────────────────────────────────── Returns 'OK' if the specified dsn exists, or what status it is. One of the following values will always be returned: OK MEMBER NOT FOUND MEMBER SPECIFIED, BUT DATASET IS NOT PARTITIONED DATASET NOT FOUND ERROR PROCESSING REQUESTED DATASET PROTECTED DATASET /* RACF Protected */ VOLUME NOT ON SYSTEM INVALID DATASET NAME, dsn MISSING DATASET NAME UNAVAILABLE DATASET Note: TSO only. ═══ 6.79. SYSVAR( ) - Return System Variable ═══ ──SYSVAR(info)─────────────────────────────────── Note: TSO only. Returns information about the specified system variable info. The following info system variables may be specified: SYSPREF The TSO prefix for unqualified dataset names. SYSPROC The TSO logon procedure. SYSUID The TSO user id. SYSLTERM The number of line available on the terminal screen. SYSWTERM The number of characters in width available on the terminal screen. SYSENV The current environment, either 'FORE' or 'BACK'. SYSICMD The implicit name of the current exec. SYSISPF 'ACTIVE' if executing under ISPF, else 'NOT ACTIVE'. SYSNEST 'YES' if executing under a nested condition, else 'NO'. SYSPCMD The most recently executed TSO command. SYSSCMD The most recently executed TSO subcommand. SYSCPU The number of CPU seconds used so far. SYSHSM Null if HSM not available, else the release level of HSM. SYSLRACF Null if RACF not installed, else the release level of RACF. SYSRACF 'AVAILABLE' if RACF available, 'NOT AVAILABLE' if not not available, else 'NOT INSTALLED'. SYSSRV How many SRM service units used so far. SYSTSOE The level of TSO/E installed. Other info is available. Refer to the TSO reference manual. Returns 0 if the function was successful, 16 if not. ═══ 6.80. TIME( ) - Return System Time ═══ TIME returns a variety of formats for the current time. ──TIME(─┬────────┬─)───────────────────────────── └─option─┘ Related Functions: DATE( ) The default option is "Normal." All calls in the same statement return the same value. ┌────────────┬──────────────────────────────────────────────┐ │ Option │ Example │ ├────────────┼──────────────────────────────────────────────┤ │ Civil │ '7:15pm' │ ├────────────┼──────────────────────────────────────────────┤ │ Elapsed │ 123456789.123456 │ │ │ time since elapsed-time clock started/reset │ ├────────────┼──────────────────────────────────────────────┤ │ Hours │ '19' │ ├────────────┼──────────────────────────────────────────────┤ │ Long │ '19:15:31.123456 │ ├────────────┼──────────────────────────────────────────────┤ │ Minutes │ 1155 /* 15 + 60*19 */ │ ├────────────┼──────────────────────────────────────────────┤ │ Normal │ '19:15:31' │ ├────────────┼──────────────────────────────────────────────┤ │ Reset │ 123456789.123456 │ │ │ time since elapsed-time clock started/reset │ ├────────────┼──────────────────────────────────────────────┤ │ Seconds │ 69331 /* 31 + 60*(15+60*19) */ │ └────────────┴──────────────────────────────────────────────┘ Only the underscored, capitalized letter in the option above is required by TIME. ═══ 6.81. TRACE( ) - Return TRACE Mode ═══ ──TRACE(────┬───┬─┬──┬────────┬─)────────────────  ├─?─┤ │ └─option─┘ │ └─!─┘ │ └───────┘ Note: The "!" is not available in OS/2. Related Instructions: TRACE Returns the current TRACE actions; can also set TRACE options. ┌─────────────────┬───────────────────────────────────┐ │ Option │ Example │ ├─────────────────┼───────────────────────────────────┤ │ All │ All clauses │ ├─────────────────┼───────────────────────────────────┤ │ Commands │ All host commands │ ├─────────────────┼───────────────────────────────────┤ │ Error │ Host commands generating errors │ ├─────────────────┼───────────────────────────────────┤ │ Failure │ Host commands generating failures │ ├─────────────────┼───────────────────────────────────┤ │ Intermediates │ All clauses with intermediates │ ├─────────────────┼───────────────────────────────────┤ │ Lables │ All labels │ ├─────────────────┼───────────────────────────────────┤ │ Normal │ Host commands generating failures │ ├─────────────────┼───────────────────────────────────┤ │ Off │ All tracing off │ ├─────────────────┼───────────────────────────────────┤ │ Results │ All clauses traced before exec. │ └─────────────────┴───────────────────────────────────┘ The default option is "Normal". The "?" turns on an option. Example: save_trace = trace('?R') /* saves, sets */ /* trace some code */ ... TRACE VALUE save_trace /* reset trace */ ═══ 6.82. TRANSLATE( ) - Translate String ═══ ──TRANSLATE(string─┬─────────────────────────────────┬─)─ └─,┬────────┬─┬──────────────────┬┘ └─tableo─┘ └─,─┬──────┬─┬────┬┘ └tablei┘ └,pad┘ Translates characters in string according to the correspondence between the characters in tableo and tablei; the shorter of tablei or tableo is padded to equal length with pad for purposes of character translation; default for tablei is a list of all 256 hexadecimal characters from '00'x to 'FF'x; if neither table is specified, then a translation from lower case to upper case is done. The default pad is the blank character. Example: TRANSLATE('AbCdEfGhI') returns 'ABCDEFGHI' TRANSLATE('301-41-8397',,'-') returns '301 41 8397' TRANSLATE('12 34 56 78','C4A49497','12345678') returns 'C4 A4 94 97' ═══ 6.83. TRUNC( ) - Truncate Numeric Value ═══ ──TRUNC(number─┬─────┬─)───────────────────────── └─,n──┘ Truncates the number to n decimal places; n defaults to zero. Example: TRUNC(123.456) returns 123 TRUNC(123.456,2) returns 123.45 TRUNC(123.4,2) returns 123.40 ═══ 6.84. USERID( ) - Return Logon User ID ═══ ──USERID( )────────────────────────────────────── Note: VM and TSO only. Returns to TSO/E userid in the TSO foreground or background environment; returns the system defined user identifier in VM; an environment specific replaceable routine is invoked in other environments. Example: USERID( ) returns '@64BB' ═══ 6.85. VALUE( ) - Return Content of Symbol ═══ ──VALUE(name)──────────────────────────────────── Returns the value of the symbol named by name; this is like the CLIST &SYSNSUB(2,&&NAME) function; in general, you should use compound stem variables to implement arrays rather than multiple levels of symbolic substitution. ═══ 6.86. VERIFY( ) - Test Character String ═══ ──VERIFY(string,reference─┬─────────────────────────┬─)── └─,─┬────────┬─┬────────┬─┘ └─option─┘ └─,start─┘ Verifies that the substring of string starting at start contains only the characters listed in the reference string; the option can be: o Match o Nomatch (default) "M" says to return the position of the leftmost character in string that is found in the set of characters in the reference string; "N" says to return the position of the leftmost character in string that is NOT found in the set of characters in the reference string; zero is returned when all characters match (N) or don't match (M). The default start position is 1. Example: VERIFY('123','0123456789') returns 0 VERIFY('123','0123456789','N') returns 0 VERIFY('123','0123456789','M') returns 1 VERIFY('A23','0123456789','N') returns 1 VERIFY('A23','0123456789','M') returns 2 ═══ 6.87. WORD( ) - Get Word ═══ ──WORD(string,n)───────────────────────────────────────── Returns the nth blank-delimited word from string; same as SUBWORD( ). ═══ 6.88. WORDINDEX( ) - Return Word Position ═══ ──WORDINDEX(string,n)──────────────────────────────────── Returns the character position of the first character in the nth word of the string. Example: WORDINDEX('Four score and',1) returns 1 WORDINDEX('Four score and',2) returns 6 WORDINDEX('Four score and',3) returns 12 WORDINDEX('Four score and',4) returns 0 ═══ 6.89. WORDLENGTH( ) - Return Word Length ═══ ──WORDLENGTH(string,n)─────────────────────────────────── Returns the length of the nth word in the string. Example: WORDLENGTH('Four score and',1) returns 4 WORDLENGTH('Four score and',2) returns 5 WORDLENGTH('Four score and',3) returns 3 WORDLENGTH('Four score and',4) returns 0 ═══ 6.90. WORDPOS( ) - Return Word Position ═══ ──WORDPOS(phrase,string─┬────────┬─)───────────────────── └─,start─┘ Finds the leftmost match of the phrase in the string, starting at word number start; if a match is found, returns the relative number of the first matching word in string; if not found, returns zero. The default start position is 1. Example: WORDPOS('the', 'now is the time') returns 3 WORDPOS('The', 'now is the time') returns 0 WORDPOS('is the', 'now is the time') returns 2 ═══ 6.91. WORDS( ) - Return Number of Words ═══ ──WORDS(string)────────────────────────────────────────── Returns the number of words in the string. Example: WORDS('Four score and') returns 3 WORDS('Four-score-and') returns 1 WORDS(' ') returns 0 WORDS('') returns 0 ═══ 6.92. XRANGE( ) - Define Range of Hex Values ═══ ──XRANGE(─┬───────┬─┬───────┬─)────────────────────────── └─start─┘ └─,end──┘ Returns a string of all the hexadecimal values from start through end, inclusive; start defaults to '00'x; end defaults to 'FF'x. Do not make the mistake of using XRANGE("A","Z") to check for only upper case letters; this range includes more hex values than just the letters, and several of these characters are enterable at a keyboard. Example: upper_case = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" IF verify(test_string,upper_case)=0 THEN ... Do NOT use: upper_case = XRANGE('A','Z') IF verify(test_string,upper_case)=0 THEN ... The former example is character set independent; the latter example will only work correctly with ASCII -- it includes too many characters with EBCDIC. ═══ 6.93. X2C( ) - Hex to Character String Conversion ═══ ──X2C(hexstring)───────────────────────────────────────── Converts hexadecimal hexstring to character. Example: X2C('d5a6a64089a240a38885') returns 'Now is the' X2C('F1F2F3') returns '123' ═══ 6.94. X2D( ) - Hex to Decimal Conversion ═══ ──X2D(hexstring─┬────┬─)───────────────────────────────── └─,n─┘ Related Instructions: NUMERIC Converts hexadecimal hexstring to decimal; if n is specified, it represents the number of hexadecimal digits to use in the conversion; extra ones are truncated from the LEFT; if padding is needed, hexadecimal zeroes are added on the LEFT; also, when n is specified, if the leftmost bit is on, the number is considered to be a negative number in two's complement. Example: X2D('C1') returns 193 X2D('001') returns 1 X2D('2374') returns 9076 9076 X2D('FF') returns 255 X2D('FF',0) returns 0 X2D('FF',2) returns -1 X2D('FF',4) returns 255 ═══ 7. Useful Environment Subcommands ═══ Note: The examples and descriptions in the following sections are not meant to be a complete reference to all subcommands in all available subcommand environments. Only some of the more useful and common subcommands in each environment are discussed. Remember that the result or status of host REXX commands is set into the RC special variable. The following sections discuss some useful subcommands available in the following execution environments: o OS/2 CMD Environment o MVS Environment o TSO Environment o VM Environment ═══ 7.1. OS/2 CMD Environment ═══ This OS/2 CMD subcommand environment is available to REXX programs which are executed by the CMD.EXE command processor. This an EXE registered subcommand environment and is therefore not available to programs called by CMD.EXE or to Presentation Manager programs. Any OS/2 command which can be placed in an OS/2 batch file can be sent to the CMD subcommand environment for processing. Some useful subcommands follow: o CALL Command o DEL or ERASE Command o DIR Command o PATH Command o SET Command o RXSUBCOM Command o RXQUEUE Command Other products are beginning to appear on the market which define their own subcommand environments. ═══ 7.1.1. CALL Command ═══ Do not confuse this with the REXX CALL statement. This subcommand is used to invoke OS/2 batch (.CMD) files. ┌────────────────┐  │ ──CALL ──batchfile──┴─┬────────────┬─┴──────────────────── └──argument──┘ The CALL invokes another copy of CMD.EXE and begins execution of the batchfile. The batchfile parameter can be either the name of and OS/2 .CMD file or a REXX program to be called as a subcommand. Any return information generated by the batchfile is lost. Refer to the OS/2 Command Reference for more information. Example: if x = 'OK' then 'call startcm' ═══ 7.1.2. DEL or ERASE Command ═══ Deletes OS/2 files. ┌───────────────────────────────┐ ┌──DEL ────┐  │ ──┤ ├──┴─┬───────┬─┬───────filename──┬─┴─┬────┬── └──ERASE ──┘ └─drive─┘ └─path─┬──────────┤ └─/P─┘ └─filename─┘ Refer to the OS/2 Command Reference for more information. Example: if x = 'OK' then 'del temp.dat' ═══ 7.1.3. DIR Command ═══ Displays a directory of OS/2 files. ┌─────────────────────────────────┐ ┌──────────┐  │  │ ──DIR ──┴─┬───────┬─┬──────┬─┬──────────┬─┴─┴─┬┬────┬┬─┴── └─drive─┘ └─path─┘ └─filename─┘ │├─/W─┤│ │└─/F─┘│ ├──/P──┤ └──/N──┘ Refer to the OS/2 Command Reference for more information. Example: if x = 'SHOW' then 'dir *.* /p' ═══ 7.1.4. PATH Command ═══ Displays/sets the directory paths to search cor commands or REXX programs, if not found in the current directory or specified directory. ──PATH ────┬────────────────────────┬───────────────────── │ ┌──────────;─────────┐ │ │  │ │ └─┴─┬───────┬─┬──────┬─┴─┘ └─drive─┘ └─path─┘ Refer to the OS/2 Command Reference for more information. Example: if x = 'CHG' then 'path c:\os2;d:\bin;' else 'path' ═══ 7.1.5. SET Command ═══ Displays/sets OS/2 environment variables. ──SET ────┬──────────────────────┬──────────────────────── └─string──=─┬────────┬─┘ └─string─┘ Refer to the OS/2 Command Reference for more information. Example: if x = 'CHG' then 'set init=d:\init' ═══ 7.1.6. RXSUBCOM Command ═══ Manipulates subcommand environments packaged as DLLs. ──RXSUBCOM─┬─REGISTER envname dllname procname─┬────────── ├─DROP──┬─ envname──┬─────────┬─────┘ ├─LOAD──┤ └─dllname─┘ └─QUERY─┘ REGISTER Register a subcommand environment packaged as a DLL. Performs the same service as the RxSubcomRegister( ) C function. This subcommand however cannot register subcommand environments packaged in EXEs. DROP Drops a previously registered subcommand environment. Performs the same service as the RxSubcomDrop( ) C function. This subcommand however cannot drop subcommand environments packaged in EXEs. LOAD Loads a previously registered subcommand environment. Performs the same service as the RxSubcomLoad( ) C function. This subcommand however cannot load subcommand environments packaged in EXEs. QUERY Queries for a previously registered subcommand environment. Performs the same service as the RxSubcomQuery( ) C function. Examples: 'rxsubcom register sampleenv sample sampleproc' 'rxsubcom drop sampleenv' 'rxsubcom load sampleenv sampdll' 'rxsubcom query sampleenv' ═══ 7.1.7. RXQUEUE Command ═══ Manipulates REXX queues. ──RXQUEUE──┬───────────┬──┬─/LIFO──┬────────────────────── └─queuename─┘ ├─/FIFO──┤ └─/CLEAR─┘ /LIFO stacks items from STDIN on the top of of a named (or defualt) REXX queue. /FIFO queues items from STDIN to the end of a named (or defualt) REXX queue. /CLEAR clears the named (or defualt) REXX queue. Example: 'rxsubcom query sampleenv' ═══ 7.2. MVS Environment ═══ The MVS Subcommand environment includes 15 commands: o DELSTACK Command o DROPBUF Command o EXECIO Command o EXECUTIL Command o HI Command o HT Command o MAKEBUF Command o NEWSTACK Command o QBUF Command o QELEM Command o QSTACK Command o RT Command o SUBCOM Command o TE Command o TS Command The MVS environment is available to all REXX execs running in any address spaces. ═══ 7.2.1. DELSTACK Command ═══ The DELSTACK commands deletes the most recently created stack. If no stack has been created (via the NEWSTACK command), then all elements from the original stack are deleted. ──DELSTACK──────────────────────────────────────────────── Example: 'delstack' ═══ 7.2.2. DROPBUF Command ═══ The DROPBUF command deletes the specified buffer (and its elements) from the current stack. Buffers are created via the MAKEBUF command. ──DROPBUF──┬───────────┬────────────────────────────────── └─bufnumber─┘ bufnumber The number of the buffer to be deleted. This buffer and all higher numbered buffers are deleted. The default is the most recently created buffer. Example: 'dropbuf 4' ═══ 7.2.3. EXECIO Command ═══ The EXECIO command performs input/output operations. ──EXECIO─┬─reccount─┬────────────────────────────────────── └─*────────┘ ───┬─DiskW ddname─┬────────────────────────────┬───┬──── │ └─(─┬──────────────┬─┬───────┤ │ │ └─STEM varname─┘ └─FINIS─┘ │ ├─DISKR──┬─ddname─┬────────────────┬─┬──────────┤ └─DISKRU─┘ └─startrecnumber─┘ └─( option─┘ where option is: ───(─┬─┬───────┬────┬──────┬──┬───────────────────────── │ └─FINIS─┘ ├─FIFO─┤ │ │ ├─LIFO─┤ │ │ └─SKIP─┘ │ └─STEM varname─┬───────┬─┘ └─FINIS─┘ reccount The number of records to be processed. "*" causes the complete dataset to be processed. DISKW Performs write operations. DISKR Performs read operations. DISKRU Performs read for update operations. ddname Specifies the dataset on which to perform the specified operation. STEM varname Specifies the REXX stem variable from/to which the specified operation is to take place. FINIS Close the file on completion of the operation. startrecnumber Specifies the first record on which to perform the operation. FIFO Specifies the records are to be stored at the head of the stack. LIFO Specifies the records are to be stored at the end (tail) of the stack. SKIP Specifies the number of record to be skipped. Example: 'execio * DISKR INFILE (STEM line.' ═══ 7.2.4. EXECUTIL Command ═══ The EXECUTIL command specifies the execution (TSO) environment for the REXX exec. ──EXECUTIL┬─EXECDD(─┬─CLOSE───┬─)─┬──────────────────────── │ └─NOCLOSE─┘ │ ├─HI────────────────────┤ ├─HT────────────────────┤ ├─renameoption──────────┤ ├─RT────────────────────┤ ├─SEARCHDD(─┬─NO──┬─)───┤ │ └─YES─┘ │ ├─TE────────────────────┤ └─TS────────────────────┘ where renameoption is: ──RENAME NAME(funcname)───────────────────────────────── ───┬──────────────────┬─┬───────────┬───────────────── └─SYSNAME(sysname)─┘ └─DD(sysdd)─┘ EXECDD Specifies the system exec library to be used and the close option after the library has been loaded. The default option is NOCLOSE. HI Halt interpretation. All execs currently active are terminated. HT Suppress SAY output. RENAME Used to change entries in a function package. RT Restart SAY output. SEARCHDD Specifies whether the system exec library is to be search in addition to the system procedure library. TE Terminate tracing. TS Start tracing. Example: 'executil searchdd(yes)' ═══ 7.2.5. HI Command ═══ The HI command terminates the execution of all REXX execs currently running. ──HI────────────────────────────────────────────────────── Example: 'hi' ═══ 7.2.6. HT Command ═══ The HT command suppresses SAY output. ──HT────────────────────────────────────────────────────── Example: 'ht' ═══ 7.2.7. MAKEBUF Command ═══ The MAKEBUF command creates a new buffer in the current stack. ──MAKEBUF───────────────────────────────────────────────── Example: 'makebuf' x = RC /* x now contains the buffer number created by MAKEBUF */ ═══ 7.2.8. NEWSTACK Command ═══ The NEWSTACK command creates a new stack, which becomes the current stack. ──NEWSTACK──────────────────────────────────────────────── Example: 'newstack' ═══ 7.2.9. QBUF Command ═══ The QBUF command returns the current number of buffers in the current stack.. ──QBUF──────────────────────────────────────────────────── Example: 'qbuf' say 'The current number of buffers is' RC ═══ 7.2.10. QELEM Command ═══ The QELEM command returns the number of elements in the current buffer. ──QELEM─────────────────────────────────────────────────── Example: 'qbuf' say 'The current number of elements is' RC ═══ 7.2.11. QSTACK Command ═══ The QSTACK command returns the current number of stacks. ──QSTACK────────────────────────────────────────────────── Example: 'qbuf' say 'The current number of stacks is' RC ═══ 7.2.12. SUBCOM Command ═══ The SUBCOM command determine if the exec is running in the specified environment. ──SUBCOM env────────────────────────────────────────────── env Specifies the subcommand environment to query. Example: 'subcom TSO' if RC = 0 then say 'TSO is the active environment' else say 'The TSO environment is not active' ═══ 7.2.13. TE Command ═══ The TE command terminates tracing. ──TE────────────────────────────────────────────────────── Example: 'te' ═══ 7.2.14. TS Command ═══ The TS command initiates tracing. ──TS────────────────────────────────────────────────────── Example: 'ts' ═══ 7.2.15. RT Command ═══ The RT command resumes SAY output. ──RT────────────────────────────────────────────────────── Example: 'rt' ═══ 7.3. TSO Environment ═══ The TSO environment is available to all REXX execs running in the TSO address space. All TSO commands can be addressed to the TSO Subcommand Environment. Refer to the TSO/E Commands Reference manual for details on TSO commands. ═══ 7.4. VM Environment ═══ *** Not yet written *** ═══ 8. OS/2 APIs ═══ Note: The examples and descriptions in the following sections are not meant to be a tutorial of REXX interface programming but a quick reference guide only. The following sections define the Application Programming Interfaces used in the OS/2 environment. The OS/2 APIs for REXX covers 7 topics: o Data types and structures o Invoking REXX o Subcommand Interface o External Functions o Macrospace Interface o Variable Pool Interface o System Exit Interface The APIs described here allow the REXX language to be extended in many different ways. This includes the creation of new subcommand environments, creation of new REXX functions, program access to REXX variables, manipulation of the REXX macrospace and many other functions. A complete example program which utilizes most of the common REXX APIs is included in the SAAREXX.ZIP file. You can use the example as a starting point for your own programs. All of the examples given in this section are shown in C, but other SAA languages are also capable of utilizing the APIs. General Characteristics Some general characteristics apply to applications which will be used as handlers, subcommands, external functions, and system exit handlers. o A handler must be written as a large model program. Other requirements are: - Use the PASCAL calling convention - All entry points must use the far calling convention - The function should use the caller's stack - The function should set up its own data segment o A handler must be packaged as either: - An OS/2 Dynamic Link Library (DLL) - A binary executable (EXE) o A handler must be registered before it can be used in a REXX program. Registration of the handler informs the REXX interpreter where the handler may be found and possibly how it should be invoked. Some constraints for handlers are noted below: - EXE handlers are known only to the local registering process. Functions in the handler may only be invoked by the registering process. - DLL handlers are known globally to all processes. Any REXX procedure running in any process may register and access functions in the DLL. ═══ 8.1. Data Types and Structures ═══ REXX uses several data structures in almost all of its APIs. These data structures are documented below. o RXSTRING Structure o RXSYSEXIT Structure o SCBLOCK Structure o SHVBLOCK Structure ═══ 8.1.1. RXSTRING Structure ═══ REXX strings are passed to and from the C application program using the following structure definition and macros: /*** Structure for external interface string (RXSTRING) */ typedef struct { ULONG strlength; /* length of string */ PCH strptr; /* far pointer to string */ } RXSTRING; typedef RXSTRING FAR *PRXSTRING; /* pointer to a RXSTRING */ #define RXNULLSTRING(r) (!(r).strptr) #define RXZEROLENSTRING(r) ((r).strptr && !(r).strlength) #define RXVALIDSTRING(r) ((r).strptr && (r).strlength) #define RXSTRLEN(r) (RXNULLSTRING(r)?0L:(r).strlength) #define RXSTRPTR(r) (r).strptr #define MAKERXSTRING(r,p,l) (r).strptr=(PCH)p;(r).strlength=(ULONG)l REXX strings may be larger than the 64K limit imposed by the 80286 architecture. The strings themselves may reside in a single segment or may reside in a huge segment. When used as arguments in APIs, the following notes apply: 1. REXX string arguments may be given a value (which may be a zero-length string) or not specified at all. o If an argument is specified then all parts of the RXSTRING structure will be given values. o If the null string is specified as an argument then strlength will be set to zero and strptr will be set to a valid address (it will be non-zero or non-NULL). o If no argument is specified the strptr will be set to NULL (zero). 2. When the RXSTRING is larger than 64K, strptr will point to memory that has been allocated by way of a call to DosAllocHuge. However, the meaning of the contents of the RXSTRING is exactly the same as for strings. 3. When a handler is called from REXX a return RXSTRING is required by REXX. In this case REXX will supply a RXSTRING with a strlength and buffer size of 250 bytes for the called function to use for the returned string. If the returned string is less than 250 characters in length then the buffer supplied by the caller should be utilized for the string and the strlength set to the string's length. ═══ 8.1.2. RXSYSEXIT Structure ═══ When invoking REXX through the REXXSAA( ) API the following data structure is used to specify which previously registered System Exits are to be utilized during this REXX call: /*** Structure for system exit block (RXSYSEXIT) */ typedef struct { PSZ sysexit_name; /* subcom enviro for sysexit */ SHORT sysexit_code; /* sysexit function code */ } RXSYSEXIT; typedef RXSYSEXIT FAR *PRXSYSEXIT; /* pointer to a RXSYSEXIT */ /* System Exit function and sub-function definitions */ #define RXENDLST 0 /* End of exit list. */ #define RXFNC 2 /* Process external functions. */ #define RXFNCCAL 1 /* subcode value. */ #define RXCMD 3 /* Process host commands. */ #define RXCMDHST 1 /* subcode value. */ #define RXMSQ 4 /* Manipulate queue. */ #define RXMSQPLL 1 /* Pull a line from queue */ #define RXMSQPSH 2 /* Place a line on queue */ #define RXMSQSIZ 3 /* Return num of lines on queue*/ #define RXMSQNAM 20 /* Set active queue name */ #define RXSIO 5 /* Session I/O. */ #define RXSIOSAY 1 /* SAY a line to STDOUT */ #define RXSIOTRC 2 /* Trace output */ #define RXSIOTRD 3 /* Read from char stream */ #define RXSIODTR 4 /* DEBUG read from char stream */ #define RXSIOTLL 5 /* Return linelength(N/A OS/2) */ #define RXHLT 7 /* Halt processing. */ #define RXHLTCLR 1 /* Clear HALT indicator */ #define RXHLTTST 2 /* Test HALT indicator */ #define RXTRC 8 /* Test ext trace indicator. */ #define RXTRCTST 1 /* subcode value. */ #define RXINI 9 /* Initialization processing. */ #define RXINIEXT 1 /* subcode value. */ #define RXTER 10 /* Termination processing. */ #define RXTEREXT 1 /* subcode value. */ #define RXNOOFEXITS 11 /* 1 + largest exit number. */ typedef PUCHAR PEXIT; /* ptr to exit parameter block */ Structure Member Values sysexit_name Pointer to a null-terminated character string containing the name of the System Exit. sysexit_code Contains one of the following values: RXENDLST Specifies the end of the exit list when an array of structures is used. RXFNC Specifies an external function exit. RXCMD Specifies a subcommand environment exit. RXMSQ Specifies a REXX queue exit. RXSIO Specifies a session i/o exit. RXHLT Specifies a session halt exit. RXTRC Specifies a session trace i/o exit. RXINI Specifies a session initialization exit. RXTER Specifies a session termination exit. Refer to the section Exit Handler Function Code Definitions for more information concerning the sysexit_code codes. ═══ 8.1.3. SCBLOCK Structure ═══ REXX System Exit handler and Subcommand handler registration utilizes the following data structure: /*** Structure of Rexx Subcomand Block (SCBLOCK) */ typedef struct subcom_node { struct subcom_node far *next; /* pointer to the next block */ PSZ scbname; /* subcom environment name */ PSZ scbdll_name; /* subcom module name */ PSZ scbdll_proc; /* subcom procedure name */ double scbuser; /* user area */ PFN scbaddr; /* subcom environment address */ USHORT scbmod_handle; /* dynalink module handle */ USHORT scbdrop_auth; /* Permission to drop */ PID scbpid; /* Pid of Registrant */ USHORT scbsid; /* Session ID. */ } SCBLOCK; typedef SCBLOCK FAR *PSCBLOCK; Structure Member Values subcom_node Pointer to the next SCBLOCK in the chain. This allows multiple Subcommand and Exit handlers to be registered with a single API call. The last block in the chain should set this value to NULL. scbname Pointer to a null-terminated character string containing the name of the Subcommand/Exit handler. scbdll_name Pointer to a null-terminated character string containing the name of the DLL which packages the handler. This is the field used to determine if the handler code resides in an EXE or a DLL. If this field is set to NULL then the handler code resides in an EXE, otherwise it resides in a DLL. scbdll_proc Pointer to a null-terminated character string containing the name of the exported entry point to the handler function in the DLL. This field should be set to NULL if an EXE registration is being performed. scbuser A double word to be used any way you wish. Usuall coded as 0L. scbaddr The address of the handler when performing an EXE registration. Set this field to NULL for a DLL registration. scbmod_handle For DLL registrations, if the DLL has already been loaded via DosLoadModule, then this field should be set to the module handle. Otherwise set this field to 0. scbdrop_auth Specifies the handler's drop authority. This field should be set to RXSUBCOM_DROPPABLE (any process may drop the handler) or RXSUBCOM_NONDROP (only the registering process may drop the handler). scbpid Specifies the process id of the registering process. scbsid Specifies the session id of the registering process. ═══ 8.1.4. SHVBLOCK Structure ═══ REXX Shared Variable Pool access is performed utilizing the following data structure: /*** Shared Variable Pool Interface */ #ifdef INCL_RXSHV /*** Function Codes for Variable Pool Interface (shvcode) */ #define RXSHV_SET 0x00 /* Set var from given value */ #define RXSHV_FETCH 0x01 /* Copy value of var to buffer */ #define RXSHV_DROPV 0x02 /* Drop variable */ #define RXSHV_SYSET 0x03 /* Symbolic name Set variable */ #define RXSHV_SYFET 0x04 /* Symbolic name Fetch variable*/ #define RXSHV_SYDRO 0x05 /* Symbolic name Drop variable */ #define RXSHV_NEXTV 0x06 /* Fetch "next" variable */ #define RXSHV_PRIV 0x07 /* Fetch private information */ #define RXSHV_EXIT 0x08 /* Set function exit value */ /*** Return Code Flags for Variable Pool Interface (shvret) */ #define RXSHV_OK 0x00 /* Execution was OK */ #define RXSHV_NEWV 0x01 /* Variable did not exist */ #define RXSHV_LVAR 0x02 /* Last var trans via SHVNEXTV */ #define RXSHV_TRUNC 0x04 /* Truncation occurred-Fetch */ #define RXSHV_BADN 0x08 /* Invalid variable name */ #define RXSHV_MEMFL 0x10 /* Out of memory failure */ #define RXSHV_BADF 0x80 /* Invalid funct code (shvcode)*/ #define RXSHV_NOAVL 0x90 /* Interface not available */ /*** Structure of Shared Variable Request Block (SHVBLOCK) */ typedef struct shvnode { struct shvnode FAR *shvnext; /* pointer to the next block */ RXSTRING shvname; /* Pointer to the name buffer */ RXSTRING shvvalue; /* Pointer to the value buffer */ ULONG shvnamelen; /* Length of the name value */ ULONG shvvaluelen; /* Length of the fetch value */ UCHAR shvcode; /* Function code for this block*/ UCHAR shvret; /* Individual Return Code Flags*/ } SHVBLOCK; typedef SHVBLOCK FAR *PSHVBLOCK; Structure Member Values shvnext Pointer to the next SHVBLOCK in the chain. This allows multiple variable pool requests to be handled with a single API call. shvname Pointer to an RXSTRING containing the name of the REXX variable. shvvalue Pointer to an RXSTRING buffer. For a shvcode value of RXSHV_SET or RXSHV_SYSET this is the value to be assigned to the REXX variable. For a shvcode value of RXSHV_FET or RXSHV_SYFET this points to the buffer to be used to obtain the current value of the specified REXX variable. shvnamelen Pointer to an RXSTRING that specifies the maximum length of shvname field. For a shvcode value of RXSHV_FET or RXSHV_SYFET this points to the buffer to be used to obtain the current value of the specified REXX variable. This field is unused for RXSHV_SET and RXSHV_SYSET. shvvaluelen Pointer to an RXSTRING that specifies the maximum length of shvvalue field. For a shvcode value of RXSHV_FET or RXSHV_SYFET this points to the buffer to be used to obtain the current value of the specified REXX variable. This field is unused for RXSHV_SET and RXSHV_SYSET. shvcode A code which specifies the variable function to be performed. Possible values are: RXSHV_SET Assign the shvvalue to the REXX variable specified by shvname. RXSHV_FETCH Fetch the REXX variable specified by shvname into the buffer specified by shvvalue and shvvaluelen. RXSHV_DROPV Drop the REXX variable specified by shvname. Performs the same function as the REXX DROP statement. RXSHV_SYSET Assign the shvvalue to the REXX variable specified by shvname. The shvname specifies an unresolved REXX variable name. RXSHV_SYFET Fetch the REXX variable specified by shvname into the buffer specified by shvvalue and shvvaluelen. The shvname specifies an unresolved REXX variable name. RXSHV_SYDRO Drop the REXX variable specified by shvname. Performs the same function as the REXX DROP statement. The shvname specifies an unresolved REXX variable name. RXSHV_NEXTV Fetch the next variable from the REXX variable pool into the buffer specified by shvvalue and shvvaluelen. This code is used to fetch all of the variables currently active from the REXX variable pool. RXSHV_PRIV Fetch REXX private information. Refer to the IBM Procedures Language 2/REXX Reference manual for a full description of this code. RXSHV_EXIT Sets the exit value for an External Function or a Subcommand handler. May only be executed by an external function or subcommand handler and may be called only once per invocation of the handler. shvret Return code from the API for this request block. See the example above for possible values. ═══ 8.2. Invoking REXX ═══ The following defines the API used to call the REXX interpreter from within a C application: /*** Main Entry Point to the REXXSAA Interpreter */ #define RXCOMMAND 0 /* Program called as Command */ #define RXSUBROUTINE 1 /* Program called as Subroutin */ #define RXFUNCTION 2 /* Program called as Function */ SHORT APIENTRY REXXSAA ( SHORT argc, /* Num of args passed to REXX */ PRXSTRING argv, /* Array of args passed to rex */ PSZ fname, /* [d:][path]filename[.ext] */ PRXSTRING instore, /* Loc of REXX proc in memory */ PSZ envname, /* ASCIIZ initial environment. */ SHORT calltype, /* type (command,subrtn,funct) */ PRXSYSEXIT exits, /* SysExit env. names & codes */ PSHORT retc, /* Ret code from if numeric */ PRXSTRING result); /* Retvalue from the REXX proc */ Parameters argc Is the number of arguments (the number of members of the array argv) for this call to REXX. argv Is a pointer to an array of RXSTRING structures that describe the arguments to this invocation of the REXX interpreter. fname A pointer to a zero-terminated string containing the filename of the REXX procedure. If no extension is specified then a default of .CMD is used. If no drive/path is specified then the OS/2 normal OS/2 program search will be conducted (current directory and then the PATH environment) for the file. instore Is an array of 2 RXSTRING descriptors for instorage REXX procedures. instore[0] Describes the memory buffer which contains the source of the REXX procedure. The source must be in the same format as it would reside on disk complete with all carriage-control characters. instore[1] Is used by the REXX interpreter to return the tokenized image of the REXX procedure. The REXX interpreter will allocate the storage necessary for the image via a call to DosAllocSeg or DosAllocHuge. This parameter can also be used to pass a tokenized image to the interpreter. This could be useful to protect the source code for REXX procedures from prying eyes. The following notes apply to the instore parameter. o If instore is not NULL, then no disk search is performed on pgmname. o If instore is not NULL then instore[0] must specify a valid memory location for the program source. o If insource[1].strptr is NULL then the interpreter will allocate storage for the tokenized image and set the contents of insource[1]. o If insource[1].strptr is not NULL then it should specify a valid memory location for the tokenized image of the procedure source. In this case insource[0].strptr may be NULL. envname Is a pointer to a zero-terminated string containing the name of the default environment. If envname is NULL then the environment name will be taken from the extension specified by pgmname. calltype A flag which specifies how REXX is to be called. The possible values are: RXCOMMAND - Program called as Command RXSUBROUTINE - Program called as Subroutine RXFUNCTION - Program called as Function exits Is an array of RXSYSEXIT structures which contain information about the system exits the caller wishes to be utilized during this invocation of the interpreter. retc If result is numeric then it will be converted to a binary integer and returned in retc. result The RETURN or EXIT value from the pgmname procedure. Returns REXXSAA( ) return an integer code describing the REXX interpreters action on the procedure. The possible return codes are: negative Interpreter errors. These are standard SAA-defined interpreter error codes. 0 No errors. The procedure executed normally. positive Specifies an OS/2 error loading the interpreter. Refer to the error codes from DosLoadModule and DosGetProcAddr for details. ═══ 8.3. Subcommand Interface ═══ This section describes how to create subcommand environments which can be made known to REXX. o Subcommand Handler Definition o Subcommand Handler Registration and Manipulation ═══ 8.3.1. Subcommand Handler Definition ═══ The following example shows an example subcommand handler definition: USHORT APIENTRY subcom_sample ( PRXSTRING cmdstr, /* command string passed from the caller */ PUSHORT retflag, /* pointer to short for return of flags */ PRXSTRING retstr) /* pointer to RXSTRING for return string */ { /* subcommand code goes here */ return (0); } CAUTION: The IBM OS/2 Procedures Language 2/REXX Reference manual's example subcommand procedure is incorrect. The IBM OS/2 Tools and Information Kit REXX subcommand example is correct. The problem is with the first parameter to the function; it should be a pointer to a RXSTRING, not the contents of the structure. Subcommands can be in the same module (EXE or DLL) as the application or can reside in a separate Dynamic Link Library. Subcommand Parameters cmdstr The entire command string completely resolved by REXX. retflag A flag returned by the subcommand handler to the REXX interpreter which indicates the command completion condition. RXSUBCOM_OK Subcommand completed normally. RXSUBCOM_ERROR An error occured during the execution of the subcommand. RXSUBCOM_FAILURE The subcommand failed. retstr The address of a RXSTRING to return the subcommand result. Note that the REXX interpreter provides a 250 byte area for your result. You may choose to use that default area or allocate your own area via DosAllocSeg. The integer value returned by the subcommand handler function is handled as follows: o If the return code is non-zero, that number is assigned to the special REXX variable RC. o If zero is returned and the retstr is not empty, then RC is set to the value of retstr. o Otherwise RC is set to zero. ═══ 8.3.2. Subcommand Handler Registration and Manipulation ═══ Subcommand environments can be registered from your own C program or via the OS/2 CMD Environment RXSUBCOM RESISTER command. The following describes the C Language APIs for manipulating subcommand environments: o RxSubcomRegister( ) o RxSubcomQuery( ) o RxSubcomExecute( ) o RxSubcomLoad( ) o RxSubcomDrop( ) ═══ 8.3.2.1. RxSubcomRegister( ) ═══ Registers a subcommand environment. ───RxSubcomRegister(subcomblock)───────────────────────────────── Parameter Definition subcomblock (PSCBLOCK) Pointer to a user allocated SCBLOCK structure. Returns C Define 0 RXSUBCOM_OK - success 10 RXSUBCOM_DUP - success, but a duplicate subcommand environment is already registered with your specified name ( a fully qualified subcommand name must be used when addressing this environment) 30 RXSUBCOM_MAXREG - error, cannot register any more environments 1002 RXSUBCOM_NOEMEM - error, no memory available for registration 1003 RXSUBCOM_BADTYPE - error, the subcomblock contains invalid data ═══ 8.3.2.2. RxSubcomQuery( ) ═══ Queries for a registered subcommand environment name. ───RxSubcomQuery(envname, modulename, flag, userword)──────────── Parameter Definition envname (PSZ) Pointer to a null-terminated character string containing the environment name to be located. modulename (PSZ) Pointer to a null-terminated character string containing the library name of the subcommand environment. This value can be NULL if there are no duplicate environment names registered. If it is NULL, the standard search order for environment names is searched. flag (PUSHORT) Pointer a USHORT for the return results of the search. If the return code from RxSubcomQuery() is RXSUBCOM_OK then this value contains either 1 (registered) or 0 (not registered). userword far * double Pointer a double. If the return code from RxSubcomQuery() is RXSUBCOM_OK then this value contains the user word assigned at the registration of the environment. Returns C Define 0 RXSUBCOM_OK - success 30 RXSUBCOM_NOTREG - specified subcommand environment is not registered 1003 RXSUBCOM_BADTYPE - error, the API parameters are incorrect invalid data ═══ 8.3.2.3. RxSubcomExecute( ) ═══ Sends a command to a previously registered subcommand environment. It will load the environment into memory if it has not been loaded previously. ───RxSubcomExecute(envname, modname, cmd, flags, ret, result)──── Parameter Definition envname (PSZ) Pointer to a null-terminated character string containing the environment name to be used in executing the command. modname (PSZ) Pointer to a null-terminated character string containing the library name of the subcommand environment. This value can be NULL if there are no duplicate environment names registered. If it is NULL, the standard search order for environment names is used. cmd (PRXSTRING) Pointer to and RXSTRING containg the command to be executed. flags (PUSHORT) Pointer a USHORT for the return results from the command execution. This is the return flags from the subcommand environment function itself. ret (PUSHORT) The return code from the subcommand handler function. result (PRXSTRING) The result string from the subcommand processing. Returns C Define 0 RXSUBCOM_OK - success 30 RXSUBCOM_NOTREG - specified subcommand environment is not registered 50 RXSUBCOM_LOADERR - error, not enough memory to load the DLL containing subcommand environment 127 RXSUBCOM_NOPROC - error, the specified DLL does not contain the specified procedure (environment) name ═══ 8.3.2.4. RxSubcomLoad( ) ═══ Loads a subcommand environment packaged as a DLL. ───RxSubcomLoad(envname, modulename)───────────────────────────── Parameter Definition envname (PSZ) Pointer to a null-terminated character string containing the environment name to be loaded. modulename (PSZ) Pointer to a null-terminated character string containing the library name of the subcommand environment. This value can be NULL if there are no duplicate environment names registered. If it is NULL, the standard search order for environment names is searched. Returns C Define 0 RXSUBCOM_OK - success 30 RXSUBCOM_NOTREG - specified subcommand environment is not registered 50 RXSUBCOM_LOADERR - error, not enough memory to load the DLL containing subcommand environment 127 RXSUBCOM_NOPROC - error, the specified DLL does not contain the specified procedure (environment) name ═══ 8.3.2.5. RxSubcomDrop( ) ═══ Drops a subcommand environment packaged as a DLL. ───RxSubcomDrop(envname, modulename)───────────────────────────── Parameter Definition envname (PSZ) Pointer to a null-terminated character string containing the environment name to be dropped. modulename (PSZ) Pointer to a null-terminated character string containing the library name of the subcommand environment. This value can be NULL if there are no duplicate environment names registered. If it is NULL, the standard search order for environment names is searched. Returns C Define 0 RXSUBCOM_OK - success 30 RXSUBCOM_NOTREG - specified subcommand environment is not registered 40 RXSUBCOM_NOCANDROP - error, subcommand environment was registered as not droppable 1003 RXSUBCOM_BADTYPE - error, the API parameters are incorrect ═══ 8.4. External Functions ═══ This section describes how to create external functions which can be made known to REXX. o External Function Definition o External Function Handler Registration and Manipulation ═══ 8.4.1. External Function Definition ═══ The following example shows an example external function definition: USHORT APIENTRY extfunc_sample ( PSZ name, /* function name used by REXX */ SHORT argc, /* number of arguments */ RXSTRING argv[], /* array of argument strings */ PSZ queue, /* current REXX queue name */ PRXSTRING retstr) /* pointer to RXSTRING for return string */ { /* function code goes here */ return (0); } Function Parameters name The name under which REXX invoked the external function. argc The number of arguments to the function. argv An array of RXSTRINGs which are the arguments to the function. queue An name of the currently active REXX queue. retstr The address of a RXSTRING to return the function result. Note that the REXX interpreter provides a 250 byte area for your result. You may choose to use that default area or allocate your own area via DosAllocSeg. The manuals are very unclear about how the return code from external functions should be handled. I always code this as RXFUNC_OK. ═══ 8.4.2. External Function Handler Registration and Manipulation ═══ External Functions can be manipulated from your own C program or from your REXX exec via the builtin functions RxFuncAdd( ), RxFuncDrop( ) and RxFuncQuery( ). The following describes the C Language APIs for manipulating external functions. o RxFunctionRegister( ) o RxFunctionCall( ) o RxFunctionDeregister( ) o RxFunctionQuery( ) ═══ 8.4.2.1. RxFunctionRegister( ) ═══ Registers an external function packaged in an EXE or DLL. ───RxFunctionRegister(fname, modname, entrypoint, modtype)─────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name of the function to register. This name should be used when refering to the function from your REXX exec. modname (PSZ) Pointer to a null-terminated character string containing the name of the DLL module packaging the function. This parameter is ignored if the modtype is RXFUNC_CALLENTRY. entrypoint (PSZ) Pointer to a null-terminated character string containing the name of the procedure in the DLL. If modtype is RXFUNC_DYNALINK then you must cast this argument to the address of the function in your EXE. modtype (USHORT) Flag to indicate the type of registration. RXFUNC_CALLENTRY - function is packaged as a DLL. RXFUNC_DYNALINK - function is packaged as an entry point in memory. Returns C Define 0 RXFUNC_OK - success 10 RXFUNC_DEFINED - error, function is already registered 1002 RXFUNC_NOMEM - error, no memory available for registration ═══ 8.4.2.2. RxFunctionCall( ) ═══ Call a registered external function packaged in an EXE or DLL. ───RxFunctionCall(fname, argc, argv, retv, result, queue)──────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name of the function to call. argc (USHORT) The number of function arguments. arv (PRXSTRING) Pointer to the array of RXSTRING arguments. retv (PUSHORT) The return code from the function. result (PRXSTRING) Pointer to the result string from the function. queue (PSZ) Name of the REXX queue to be used by the function. Returns C Define 0 RXFUNC_OK - success 30 RXFUNC_NOTREG - error, function is not registered 40 RXFUNC_MODNOTFND - error, Dll not found 50 RXFUNC_ENTNOTFND - error, function entry point in the DLL not found ═══ 8.4.2.3. RxFunctionDeregister( ) ═══ Drop a registered external function. ───RxFunctionDeregister(fname)─────────────────────────────────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name of the function to drop (deregister). Returns C Define 0 RXFUNC_OK - success 30 RXFUNC_NOTREG - error, function is not registered ═══ 8.4.2.4. RxFunctionQuery( ) ═══ Queries for a registered function. ───RxFunctionQuery(fname)──────────────────────────────────────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name of the function to searched for. Returns C Define 0 RXFUNC_OK - success, function is registered 30 RXFUNC_NOTREG - error, function is not registered ═══ 8.5. Macrospace Interface ═══ The REXX Macrospace Interface can reduce the time REXX functions take to load or be found by the interpreter. This especially useful for procrdures which are used repeatedly and never dropped. The following sections describe the C Language APIs for manipulating the REXX Macrospace: o RxMacroChange( ) o RxMacroDrop( ) o RxMacroErase( ) o RxMacroSave( ) o RxMacroLoad( ) o RxMacroQuery( ) o RxMacroReorder( ) ═══ 8.5.1. RxMacroChange( ) ═══ Change or add a new macro to the macrospace. ───RxMacroChange(fname, srcfile, position)─────────────────────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name name of the function to change or add. srcfile (PSZ) Pointer to a null-terminated character string containing the name of the file containing the source for the function. If no file extension is supplied then it will default to .CMD. position (USHORT) Flag indicating the position this function should be placed in the macrospace list of functions. Valid values are: RXMACRO_SEARCH_BEFORE Places the macro function at the head of the list. RXMACRO_SEARCH_AFTER Places the macro function at the tail of the list. Returns C Define 0 RXMACRO_OK - success 1 RXMACRO_NOSTORAGE - error, no memory available 7 RXMACRO_SOURCE_NOT_FOUND - error, source file not found 8 RXMACRO_INVALID_POSITION - invalid position specified ═══ 8.5.2. RxMacroDrop( ) ═══ Drops a function from the REXX macrospace. ───RxMacroDrop(fname)──────────────────────────────────────────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name of the function to drop. Returns C Define 0 RXMACRO_OK - success 2 RXMACRO_NOT_FOUND - error, specified macro not found ═══ 8.5.3. RxMacroErase( ) ═══ Drops all known functions from the REXX macrospace. ───RxMacroErase( )─────────────────────────────────────────────── Note: This is a very powerful function. Macro functions are dropped from the REXX Macrospace even if they are currently being used by other processes. Returns C Define 0 RXMACRO_OK - success 2 RXMACRO_NOT_FOUND - error, no macros found ═══ 8.5.4. RxMacroSave( ) ═══ Saves the binary image of a function from the REXX macrospace to a file. ───RxMacroSave(fcount, fnames, libfile)────────────────────────── Parameter Definition fcount (USHORT) Count of the number of pointers in the array fnames. fnames (* PSZ) An array of pointers to macrospace function names to be saved. libfile (PSZ) Pointer to a null-terminated character string containing the name of the file to use in saving the macro(s) to disk. Returns C Define 0 RXMACRO_OK - success 2 RXMACRO_NOT_FOUND - error, specified macro not found 3 RXMACRO_EXTENSION_REQUIRED - error, the libfile must contain a file extension in its name 5 RXMACRO_FILE_ERROR - error, access to the libfile was denied Note: If fcount is 0 (zero) or fnames is NULL then the entire macrospace will be saved. ═══ 8.5.5. RxMacroLoad( ) ═══ Loads the binary image of a function into the REXX macrospace from a file. ───RxMacroLoad(fcount, fnames, libfile)────────────────────────── Parameter Definition fcount (USHORT) Count of the number of pointers in the array fnames. fnames (* PSZ) An array of pointers to macrospace function names to be loaded. libfile (PSZ) Pointer to a null-terminated character string containing the name of the file to use in loading the macro(s) from disk. Returns C Define 0 RXMACRO_OK - success 1 RXMACRO_NOSTORAGE - error, no memory available 2 RXMACRO_NOT_FOUND - error, specified macro not found 4 RXMACRO_ALREADY_EXISTS - error, one or more of the specified macros already exist in the macrospace 5 RXMACRO_FILE_ERROR - error, access to the libfile was denied 6 RXMACRO_SIGNATURE_ERROR - error, the specified libfile does not contain a valid macro library ═══ 8.5.6. RxMacroQuery( ) ═══ Queries for the existence of a function in the REXX Macrospace. ───RxMacroQuery(fname, position)───────────────────────────────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name name of the function to be searched for. position (PUSHORT) Pointer to a flag indicating the position in the macrospace list of the function. A valid position is only retuned on successful execution of the function. Returns C Define 0 RXMACRO_OK - success 2 RXMACRO_NOT_FOUND - error, specified macro not found ═══ 8.5.7. RxMacroReorder( ) ═══ Changes the search-order position of a function in the REXX Macrospace. ───RxMacroReorder(fname, position)─────────────────────────────── Parameter Definition fname (PSZ) Pointer to a null-terminated character string containing the name name of the function to be repositioned. position (USHORT) Flag indicating the new search-order position for the specified function. Valid values are: RXMACRO_SEARCH_BEFORE Places the macro function at the head of the list. RXMACRO_SEARCH_AFTER Places the macro function at the tail of the list. Returns C Define 0 RXMACRO_OK - success 2 RXMACRO_NOT_FOUND - error, specified macro not found 8 RXMACRO_INVALID_POSITION - invalid position specified ═══ 8.6. Variable Pool Interface ═══ The REXX Variable Pool Service allows an OS/2 program to access REXX variables from External Functions, System Exit Handlers and Subcommand Handlers. The following definition describe the interface: ───RxVar(shvblock)─────────────────────────────────────────────── Parameter Definition shvblock (PSHVBLOCK) Pointer to an array of SHVBLOCK structures. Returns C Define 0 or positive Entire SHVBLOCK list was processed. The return code is the composite OR of the low-order 6 bits of the shvret field from all the structures. -1 Invalid API entry conditions. -2 Not enough storage to process a request set. Some blocks may not be processed. -3 The variable interface is not currently enabled. 127 The RxVar routine was not found by REXX. ═══ 8.7. System Exit Interface ═══ This section describes how to create system exit handlers. Exit handlers are specified on invocation of the REXXSAA( ) API. o Exit Handler Definition o Exit Handler Registration and Manipulation o Exit Handler Function Code Definitions ═══ 8.7.1. Exit Handler Function Definition ═══ The following example shows an example system exit handler definition: USHORT APIENTRY extfunc_sample ( USHORT func, /* exit function code */ USHORT subfunc, /* exit subfunction code */ PCHAR parm) /* function dependent control block */ { /* exit code goes here */ return (0); } Function Parameters func The exit function code. subfunc The exit subfunction code. parm A function dependent control block structure. Returns 0 Successful handling of the service. The parameter list has been updated for that service. 1 The exit chooses not to handle the service request. The interpreter will handle the request in a default manner. -1 A fatal error occurred during the execution of the service request. REXX will halt the current exec and issue an error code of 48. ═══ 8.7.2. Exit Handler Registration and Manipulation ═══ System exit handler must be registered before they may be used. The following sections describe the C Language APIs for manipulating System Exit Handlers: o RxExitRegister( ) o RxExitQueryl( ) o RxExitDrop( ) ═══ 8.7.2.1. RxExitRegister( ) ═══ Registers a system exit handler in an EXE or DLL. ───RxExitRegister(subcomblock)─────────────────────────────────── For complete information on the parameters refer to RxSubcomRegister( ). ═══ 8.7.2.2. RxExitQuery( ) ═══ Queries for a registered system environment name. ───RxExitQuery(envname, modulename, flag, userword)────────────── For complete information on the parameters refer to RxSubcomQuery( ). ═══ 8.7.2.3. RxExitDrop( ) ═══ Drops a previouslr registered system environment. ───RxExitDrop(envname, modulename)─────────────────────────────── For complete information on the parameters refer to RxSubcomDrop( ). ═══ 8.7.3. Exit Handler Function Code Definitions ═══ The following defines all the system exit function and subfunction codes: /* System Exit function and sub-function definitions */ #define RXENDLST 0 /* End of exit list. */ #define RXFNC 2 /* Process external functions. */ #define RXFNCCAL 1 /* subcode value. */ #define RXCMD 3 /* Process host commands. */ #define RXCMDHST 1 /* subcode value. */ #define RXMSQ 4 /* Manipulate queue. */ #define RXMSQPLL 1 /* Pull a line from queue */ #define RXMSQPSH 2 /* Place a line on queue */ #define RXMSQSIZ 3 /* Return num of lines on queue*/ #define RXMSQNAM 20 /* Set active queue name */ #define RXSIO 5 /* Session I/O. */ #define RXSIOSAY 1 /* SAY a line to STDOUT */ #define RXSIOTRC 2 /* Trace output */ #define RXSIOTRD 3 /* Read from char stream */ #define RXSIODTR 4 /* DEBUG read from char stream */ #define RXSIOTLL 5 /* Return linelength(N/A OS/2) */ #define RXHLT 7 /* Halt processing. */ #define RXHLTCLR 1 /* Clear HALT indicator */ #define RXHLTTST 2 /* Test HALT indicator */ #define RXTRC 8 /* Test ext trace indicator. */ #define RXTRCTST 1 /* subcode value. */ #define RXINI 9 /* Initialization processing. */ #define RXINIEXT 1 /* subcode value. */ #define RXTER 10 /* Termination processing. */ #define RXTEREXT 1 /* subcode value. */ #define RXNOOFEXITS 11 /* 1 + largest exit number. */ RXFNC Process External Functions. This function supports only one subfunction. RXFNCCAL - Process external function. When called: When the REXX interpreter is about to call an external function. Default action: Call the routine. Action: Call the routine, if possible. Continuation: If indicated by the exit function return code, raise error 40, 43 or 44. Resume interpretation. Parameters: /*** Subfunction RXFNCCAL - External Function Calls */ typedef struct { struct { unsigned rxfferr : 1; /* Invalid call to routine. */ unsigned rxffnfnd : 1; /* Function not found. */ unsigned rxffsub : 1; /* Called as a subroutine if */ /* set. Return values are */ /* optional for subroutines, */ /* required for functions. */ } rxfnc_flags ; PUCHAR rxfnc_name; /* Pointer to function name. */ USHORT rxfnc_namel; /* Length of function name. */ PUCHAR rxfnc_que; /* Current queue name. */ USHORT rxfnc_quel; /* Length of queue name. */ USHORT rxfnc_argc; /* Number of args in list. */ PRXSTRING rxfnc_argv; /* Pointer to argument list. */ /* List mimics argv list in */ /* REXXSAA -- array of */ /* RXSTRINGs. */ RXSTRING rxfnc_retc; /* Return value. */ } RXFNCCAL_PARM; Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXCMD Process Host Commands. This function supports only one subfunction. RXCMDHST - Process host commands. When called: When the REXX interpreter is about to process a host environment command. Default action: Pass the command to the environment. Action: Pass the command to the environment, if possible. Continuation: If indicated by the results, raise the ERROR or FAILURE condition. Resume interpretation. Parameters: /*** Subfunction RXCMDHST -- Process Host Commands */ typedef struct { struct { /* Condition flags */ unsigned rxfcfail : 1; /* Command failed. Trap with */ /* CALL or SIGNAL on FAILURE. */ unsigned rxfcerr : 1; /* Command ERROR occurred. */ /* Trap with CALL or SIGNAL on*/ /* ERROR. */ } rxcmd_flags; PUCHAR rxcmd_address; /* Pointer to address name. */ USHORT rxcmd_addressl; /* Length of address name. */ PUCHAR rxcmd_dll; /* dll name for command. */ USHORT rxcmd_dll_len; /* Length of dll name. 0 ==> */ /* .EXE file. */ RXSTRING rxcmd_command; /* The command string. */ RXSTRING rxcmd_retc; /* Pointer to return code */ /* buffer. User allocated. */ } RXCMDHST_PARM; Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXMSQ Manipulate queue. This function supports four subfunctions. RXMSQPLL - Pull a line from the queue. When called: Used in interpret the PULL statement. Default action: Pull from the current default queue. Action: Provide a result line. Continuation: Resume interpretation using the result. Parameters: /*** Subfunction RXMSQPLL -- Pull Entry from Queue */ typedef struct { RXSTRING rxmsq_retc; /* Pointer to dequeued entry */ /* buffer. User allocated. */ } RXMSQPLL_PARM; RXMSQPSH - Push a line on the queue. When called: Used in interpret the PUSH and QUEUE statements. Default action: Push to the current default queue. Action: Push the value on some queue where RXMSQPLL can subsequently fetch it. Continuation: Resume interpretation. Parameters: /*** Subfunction RXMSQPSH -- Push Entry on Queue */ typedef struct { struct { /* Operation flag */ unsigned rxfmlifo : 1; /* Stack entry LIFO if set, */ /* FIFO if reset. */ } rxmsq_flags; RXSTRING rxmsq_value; /* The entry to be pushed. */ } RXMSQPSH_PARM; RXMSQSIZ - Return number of lines in the queue. When called: Used in interpret the QUEUED builtin function. Default action: Find the size of the default queue. Action: Return the size. Continuation: Return the size and resume interpretation. Parameters: /*** Subfunction RXMSQSIZ -- Return the Current Queue Size */ typedef struct { ULONG rxmsq_size; /* Number of Lines in Queue */ } RXMSQSIZ_PARM; RXMSQNAM - Set the name of the active queue. When called: Used in interpret the RXQUEUE("SET", newname) builtin function. Default action: Chane the default queue to the specified name. Action: Change the default queue. Continuation: Resume interpretation. Parameters: /*** Subfunction RXMXQNAM -- Set Current Queue Name */ typedef struct { SEL rxmsq_name; /* Selector containing ASCIIZ */ /* queue name. Change length */ /* with DosReallocSeg if */ /* required. */ } RXMSQNAM_PARM; Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXSIO Session I/O. This function supports four subfunctions. RXSIOSAY - Output result of the SAY statement. When called: Used in interpret the SAY statement. Default action: Write to the session standard output device. Action: Send the line. Continuation: Resume interpretation. Parameters: /*** Subfunction RXSIOSAY -- Perform SAY Clause */ typedef struct { RXSTRING rxsio_string; /* String to display. */ } RXSIOSAY_PARM; RXSIOTRC - TRACE output processing. When called: To output the result of each line of trace processing. Default action: Write to the session standard error device. Action: Send the line. Continuation: Resume interpretation. Parameters: /*** Subfunction RXSIOTRC -- Write Trace Output */ typedef struct { RXSTRING rxsio_string; /* Trace line to display. */ } RXSIOTRC_PARM; RXSIOTRD - Read from the STDIN stream. When called: Read from the standard input stream. Note that if PULL may not call this function if its request can be satisfied by something from the stack. Default action: Read from the default input device. Action: Read the line. Continuation: Resume interpretation. Parameters: /*** Subfunction RXSIOTRD -- Read Input from the Terminal */ typedef struct { RXSTRING rxsiotrd_retc; /* RXSTRING for output. Note:*/ /* user allocates output */ /* buffer with DosAllocSeg() */ /* or DosAllocHuge(). */ } RXSIOTRD_PARM; RXSIODTR - Debug read. When called: Read from the standard input stream for interactive debug. The stack is not used by the subfunction to satisfy requests. Default action: Read from the default input device. Action: Read the line. Continuation: Resume interpretation. Parameters: /*** Subfunction RXSIODTR -- Read Debug Input from the Terminal */ typedef struct { RXSTRING rxsiodtr_retc; /* RXSTRING for output. Note:*/ /* user allocates output */ /* buffer with DosAllocSeg() */ /* or DosAllocHuge(). */ } RXSIODTR_PARM; Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXHLT Halt processing. This function supports two subfunctions. RXHLTCLR - Clear Halt indicator. This function has no inputs or outputs. When called: After raising the HALT and before the next (potential) call of RXHLTTST . Default action: Resets the polling of external interrupts. Action: Rest the polling of the external interrupt. Continuation: Continue interpretation. Parameters: None. RXHLTTST - Test Halt indicator. When called: The interpreter makes sufficient calls to poll whether an external attempt has been made to interrupt execution. Default action: Polls for external interrupts. Action: Set the result to indicate whether an external interrupt has occurred. Continuation: Raise HALT condition if an interrupt has occurred. Continue interpretation. Parameters: /*** Subfunction RXHSTTST -- Test for HALT Condition */ typedef struct { struct { /* Halt flag */ unsigned rxfhhalt : 1; /* Set if HALT occurred. */ } rxhlt_flags; } RXHLTTST_PARM; Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXTRC Test external trace indicator. This function supports one subfunction. RXTRCTST - Test external trace indicator. When called: Used to test the trace indicator by the interpreter from an external program request. Default action: Returns the trace indicator. Action: Returns the trace indicator. Continuation: Continue interpretation, with or without tracing. Parameters: /*** Subfunction RXTRCTST -- Test for TRACE Condition */ typedef struct { struct { /* Trace flags */ unsigned rxftrace : 1; /* Set to run external trace. */ } rxtrc_flags; } RXTRCTST_PARM; Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXINI Initialization processing. This function supports one subfunction. RXINIEXT - Initialization processing. When called: Just prior to beginning interpretation. Default action: None. Action: Initialize all other system exits. Continuation: Resume interpretation. Parameters: None. Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. RXTER Termination processing. This function supports one subfunction. RXTEREXT - Termination processing. When called: Just prior to returning control to the calling process. Default action: None. Action: Terminate all other system exits. Continuation: Resume, leaving interpreter. Parameters: None. Refer to the IBM Procedures Language 2/REXX Reference manual for further details on this exit function. ═══ ═══ BookMark When you place a bookmark on a topic, it is added to a list of bookmarks you have previously set. You can view the list, and you can remove one or all bookmarks from the list. If you have not set any bookmarks, the list is empty. To set a bookmark, do the following: 1. Select a topic from the Contents. 2. When that topic appears, choose the Bookmark option from the Services pull-down. 3. If you want to change the name used for the bookmark, type the new name in the field. 4. Click on the Place radio button (or press the Up or Down Arrow key to select it). 5. Click on OK (or select it and press Enter). The bookmark is then added to the bookmark list. ═══ ═══ Search You can specify a word or phrase to be searched. You can also limit the search to a set of topics by first marking the topics on the Contentes list. To search for a word or phrase in all topics, do the following: 1. Choose the Search option from the Services pull-down. 2. Type the word or words to be searched. 3. Click on All sections (or press the Up or Down Arrow keys to select it). 4. Click on Search (or select it and press Enter) to begin the search. 5. The list of topics where the word or phrase appears is displayed. If only one topic contains the word or phrase, a window containing that topic appears. ═══ ═══ Print You can print one or more topics. You can also print a set of topics by first marking the topics on the Contents list. To print the document Contents list, do the following: 1. Choose Print from the Services pull-down. 2. Click on Contents (or press the Up or Down Arrow to select it). 3. Click on Print (or select it and press Enter). 4. The Contents list is printed on your printer. ═══ ═══ Copy You can copy a topic you are viewing into a temporary file named TEXT.TMP. You can later edit that file by using the editor of your choice. To copy a topic, do the following: 1. Expand the Contents list and select a topic. 2. When a topic appears, choose Copy to file from the Services pull-down. 3. The system puts the text pertaining to that topic in the temporary TEXT.TMP file. For information on one of the other choices in the Services pull-down, highlight the choice and press the F1 key. ═══ ═══ Options You can control the appearance of the Contents list. To expand the Contents and show all levels for all topics, choose Expand all from the Options pull-down. You can also press the Ctrl and * keys together. For information on one of the other choices in the Services pull-down, highlight the choice and press the F1 key. ═══ ═══ environment a literal string or a single symbol denoting the "host" command environment or particular program to which a command will be directed. In all operating systems it is possible for users and programs to define new "environments". The most commonly used ones are shown below: TSO MVS LINK ATTACH ISPEXEC ISREDIT CMS COMMAND ISPEXEC ISREDIT CMD ISPCIR ═══ ═══ template a list of symbols that are separated by blanks and/or patterns. More formally: ┌────────────────────────────┐ ├─────────────,──────────────┤  │ ──┴──┬───────────────────────┬─┴── ├──variable─────────────┤ ├──(variable)───────────┤ ├──literalstring────────┤ ├── . ──────────────────┤ └──┬─────┬─wholenumber──┘ ├─ + ─┤ └─ - ─┘ variable name of a variable to receive part of the parsed string (variable) name of a variable whose value is used to match in the parsed string literalstring a character, hexadecimal, or binary (OS/2 only) string literal used to match in the parsed string . (period) a placeholder; just like matching to a dummy variable wholenumber move match position in parsed string to specified column + wholenumber move match position in parsed string ahead by specified number of columns - wholenumber move match position in parsed string back by specified number of columns , (comma) used to separate multiple patterns; available only in the ARG and PARSE ARG statements ═══ ═══ name a symbol or literal string that identifies a routine. This must be a valid symbol. ═══ ═══ trapname a symbol or literal string that identifies a routine to be called when the associated condition is trapped. ═══ ═══ Symbol A symbol can be a number, REXX keyword, or a name used for variables, labels, functions, etc. Names can't begin with digits or a period. All implementations allow names to include: a-z A_Z 0-9 underscore(_) exclamation(!) and question(?). The period can also be used, but it has a special meaning concerned with compound symbols. Symbols are not case sensitive, i.e., lower-case letters in symbols are translated to upper-case. The VM and TSO environments also support the characters @#$Ы in symbols. Avoid them for the sake of portability. ═══ ═══ Name expression An variable whose value is a list of variable names. This is a form of indirection. ═══ ═══ Labelname A labelname must be a valid REXX symbol and must reference a known internal or external procedure. ═══ ═══ Variable The name of a legal REXX variable.