═══ 1. Alpha Version Intro ═══ Next This is a work-in-progress -- parts are missing or incomplete. Your feedback on any and all parts of this online document is welcome. Brian Buck 76666,60 Next ═══ 2. Introduction ═══ Next Prev 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 OS/2, MVS, and VM environments; for OS/2, the IBM OS/2 EE REXX (REXXSAA) and the Mansfield Software Group's Personal REXX are covered. Why an Online REXX Reference? Why? - 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 EE 1.2. 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 OS/400, but I don't have those manuals; volunteers, anyone? Send me the details and I'll update this reference). The reference employs the OS/2 help manager (a.k.a. the IPF, Information Presentation Facility, or Boca-help) because I needed to learn how to use it, for creating both stand-alone references and in-context help documents. The other two alternatives, Microsoft QuickHelp and IBM BookManager/2 Read, have the distinct disadvantage that their viewing software is not available on every OS/2 system -- and online books are no good if you can't read them. This started out as a short list of syntax diagrams with no explanatory text, but it just looked too incomplete compared to the other online IPF books, and it just kept growing ... 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. (BASIC was my first language years ago, learned from its creators, Kemeny and Kurtz; however, I think REXX is far more appropriate as a universal command and macro language. Let's hope that the major players in OS/2, IBM and Microsoft, can reach some accord on this issue, or else OS/2 will end up like Unix, where standards are considered such a good idea that everybody has his/her own .) 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). This reference is released into the public domain; use it any way you like. I would appreciate hearing of any errors or omissions that you find; I will attempt to keep this reference up-to-date, and welcome the assistance of any and all who wish to contribute to the effort. Send no money to anyone for this: it is free. If you want to express any gratitude, give to your favorite charity. This is my way of thanking all those who have placed their sample OS/2 source codes into the public domain -- it would have been so difficult to learn about OS/2 without their generously shared examples. That is why the IPF source for this reference is also available; it demonstrates some techniques that can be used in creating a standalone online reference. Now, to satisfy the lawyers: no warranties, guarantees, etc. are implied, no liability is assumed. You break it and you own both halves. I am not affiliated in any way with any vendor of a REXX implementation or a related product. Any opinions expressed herein are my own, not that of my employer or any vendor. This reference is only available where you find it (bulletin boards); I cannot respond to individual requests for it, although I will respond to comments and suggestions. Brian Buck 23SEP90 Internet 76666.60@Compuserve.COM Compuserve 76666,60 BIX bbuck IBMLink NABSD0O at HONE83 IBM NSD BBS (Atlanta) Brian Buck Phone (312) 923-3328 Fax (312) 923-1251 Trademarks The following trademarks apply to all online information:  BookManager/2 is a trademark of International Business Machines Corporation.  IBM is a registered trademark of International Business Machines Corporation.  Microsoft is a trademark of the Microsoft Corporation.  Operating System/2 is a trademark of International Business Machines Corporation.  OS/2 is a trademark of International Business Machines Corporation.  Personal REXX is a trademark of Mansfield Software Group  Personal System/2 and PS/2 are registered trademarks of International Business Machines Corporation.  Presentation Manager is a trademark of International Business Machines Corporation.  Quickhelp is a trademark of the Microsoft Corporation.  REXX/2 is a trademark of Command Technology Corp.  SAA is a trademark of International Business Machines Corporation.  Systems Application Architecture is a trademark of International Business Machines Corporation. Next Prev ═══ 2.1. Other References ═══ Next Prev 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 EE 1.2), IBM P/N 2010 Personal REXX OS/2 Addendum Version 2.0, Mansfield Software Group P/N 2008 Personal REXX User's Guide Version 2.0, Mansfield Software Group SC24-5239-3 VM/SP System Product Interpreter Reference (VM/SP Release 6), IBM SC28-1883-1 TSO/E Version 2 REXX Reference (TSO/E 2.1.1), IBM SC26-4358-2 SAA CPI Procedures Language Reference, IBM 0-13-780735-X The Rexx Language: a Practical Approach to Programming by M. F. Cowlishaw, IBM UK Scientific Centre; 1985, Prentice-Hall, Inc., Englewood Cliffs, New Jersey 07632 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 (I haven't actually seen the second edition, yet; no bookstore in Chicago has it or can order it.) 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 (IBM Announcement 290-363 on 26Jun90 introduced Level 2 REXX -- the REXX 4.00 described in the second edition of Mike Cowlishaw's book; the manual will be available in the third quarter of 1990). "Rexx in Charge: You're not really multitasking in OS/2 unless you're using REXX" by Charles Daney, in BYTE August 1990, pp.245-253 SC28-1882 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-5228 The Design of the REXX Language, IBM Systems Journal article reprint from Vol. 23 No. 4, 1984 G321-5359 REXX on TSO/E, IBM Systems Journal article reprint from Vol. 28 No. 2, 1989 59731-1 Modern Programming Using REXX, by Robert O'Hara and David Gomberg, Prentice-Hall., Englewood Cliffs, New Jersey 07632 59732-9 Modern Programming Using REXX, Revised, by Robert O'Hara and David Gomberg, Prentice-Hall., Englewood Cliffs, New Jersey 07632 SHARE74 Procedures Language (REXX) Structure in SAA, by Stephen G. Price and Linda Suskind Green, IBM Corp., Endicott, New York; Session A631 in SHARE 74 Proceedings, Anaheim, California, March 4-9, 1990 SHARE Inc., 111 E. Wacker Drive, Chicago, IL 60601; (312) 822-0932. SHARE74 REXX 4.00, by Mike Cowlishaw, IBM UK Laboratories Systems Technology, Winchester, UK; Session A633 in SHARE 74 Proceedings, Anaheim, California, March 4-9, 1990 SHARE Inc., 111 E. Wacker Drive, Chicago, IL 60601; (312) 822-0932. SHARE74 Object-Oriented REXX, by Simon C. Nash, IBM UK Laboratories Systems Technology, Winchester, UK; Session A634 in SHARE 74 Proceedings, Anaheim, California, March 4-9, 1990 SHARE Inc., 111 E. Wacker Drive, Chicago, IL 60601; (312) 822-0932. SHARE74 REXX Programming Standards , Hints and Tips, by Eric Marc Lowbenberg, Bell Canada, Montreal, Quebec, Canada; Session A644 in SHARE 74 Proceedings, Anaheim, California, March 4-9, 1990 SHARE Inc., 111 E. Wacker Drive, Chicago, IL 60601; (312) 822-0932. SHARE74 REXX in the Age of Presentation Manager, by Charles Daney, Quercus Systems, 19567 Dorchester Drive, Saratoga, CA 95070; Session A644 in SHARE 74 Proceedings, Anaheim, California, March 4-9, 1990 SHARE Inc., 111 E. Wacker Drive, Chicago, IL 60601; (312) 822-0932. Next Prev ═══ 3. Usage Instructions ═══ Next Prev How to Use the Contents (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. Next Prev ═══ 4. How to Read These Syntax Diagrams ═══ Next Prev 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 EE Procedures Language/2 REXX does/doesn't have this item. indicates that Mansfield's Personal REXX for OS/2 does/doesn't contain 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 the item is/isn't valid in any IBM mainframe MVS environment. 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 original 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 just are 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──┘ Next Prev ═══ 5. Basic Concepts ═══ Next Prev 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 Reestructured 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 part of OS/2 EE (Extended Edition). There has been a lot of demand for it to become part of OS/2 SE as well, but given Microsoft's predisposition towards BASIC, it may never happen. (BASIC happened to be my first language, too ... but REXX is better suited to usage as a procedure and macro language. Of course, if I sold BASIC compilers, I suppose my opinion would be different, too ). In a briefing to IBM Technical Coordinators IBM indicated that OS/2 1.2 SE will contain IBM REXX. It would be nice now if they could get it to run as quickly and efficiently as the Mansfield implementation, which consistently beats IBM's in my own ad hoc benchmarks by 20% to 80 %. There is a REXX implementation available for owners of the current OS/2 SE (or EE, for that matter, since it benchmarks faster than the IBM REXX). It is called Personal REXX, and is manufactured by Mansfield_Software_Group Mansfield has had great success with Personal REXX under both DOS and OS/2. The point is that REXX is automatically available on about two-thirds of all OS/2 machines (because it comes with EE, and EE sales constitute about that proportion), and is easily and inexpensively available on the rest. 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. The Personal REXX implementation stores a partially translated version with the original source. 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. Next Prev ═══ 5.1. Syntax - tokens, continuations ═══ Next Prev 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 EE, 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 Next Prev ═══ 5.2. Expressions - terms & operators ═══ Next Prev REXX expressions are sequences of terms, operators, and parentheses (round brackets, for those of you in the UK). Terms are:  Literals, which include character strings, hexadecimal strings, binary strings, and numbers.  Variables,which are simple or compound symbols.  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  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 ..."  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 )  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  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 habits take 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 \ 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. Next Prev ═══ 5.3. Clauses - parts of instructions ═══ Next Prev REXX has five types of clauses: 1. Assignment statements A single clause of the form symbol = expression 2. 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). 3. 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. 4. 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. 5. 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. Next Prev ═══ 5.4. Variables - & values ═══ Next Prev 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". Next Prev ═══ 5.5. Commands - & environments ═══ Next Prev 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. Next Prev ═══ 6. Keyword Instructions ═══ Next Prev Keyword instructions provide the structure on which the rest of a REXX program hangs; the commands and builtin functions flesh out this skeleton. In the sections that follow, the REXX keyword instructions are described. For a description of the icons displayed and the syntax diagrams, see How to Read These Syntax Diagrams. Next Prev ═══ 6.1. Address - change cmd destination ═══ Next Prev The ADDRESS instruction will change the destination of commands, either temporarily or permanently. ──ADDRESS──┬────────────────────────────┬──;── ├─environment─┬────────────┬─┤ │ └─expression─┘ │ └┬───────┬──expression1──────┘ └─VALUE─┘ Related Functions: 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. ADDRESS environments:  OS/2 EE 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. ????? Used to send commands to the OfficeVision/2 Composite Correspondence Editor.  Personal REXX for OS/2 CMD Used for OS/2 commands, just like in a windowed or full screen OS/2 command session KEDIT Used in KEDIT edit macros to issue commands to the editor. (KEDIT is an editor from the Mansfield Software Group that is similar to VM's XEDIT). ???? Used in REXXTERM sessions to issue commands to the communications program. (REXXTERM is a product of Quercus_Systems).  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. ????? Used to issue commands to the SQL/DS relational data base. (Requires IBM product "?????").  MVS 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 TSO */ address ISREDIT "change 'DOS' 'OS/2' all" "save" Next Prev ═══ 6.2. Arg - parse parameters ═══ Next Prev 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, PROCEDURE Related Functions: 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." */ Next Prev ═══ 6.3. Call - invoke a routine ═══ Next Prev 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─────┤ │ │ └──NOREADY──┘ │ │ │ └──ON──┬──ERROR────┬─┬──────────────────┬──┘ ├──FAILURE──┤ └──NAME──trapname──┘ ├──HALT─────┤ └──NOREADY──┘ Related: ARG, PROCEDURE, SIGNAL, 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. NOREADY The NOREADY condition is only valid in OS/2 EE; 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 Next Prev ═══ 6.4. Do - repeat instructions ═══ Next Prev 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──┘ 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 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 Next Prev ═══ 6.5. Drop - unassign a variable ═══ Next Prev The DROP instruction unassigns variables; restores them to their original uninitialized state. ┌───────────────┐  │ ────DROP───┴┬────name─────┬┴───;────────── └─(name-expr)─┘ It's OK to specify the names of variables that are uninitialized already. PREXX doesn't support the use of a name-expr in parentheses. 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 */ Next Prev ═══ 6.6. Exit - leave a program ═══ Next Prev 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). Next Prev ═══ 6.7. If - maybe process instrs ═══ Next Prev 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. Next Prev ═══ 6.8. Interpret - build, do instrs at runtime ═══ Next Prev 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 ... Next Prev ═══ 6.9. Iterate - goto top of DO loop ═══ Next Prev 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 Next Prev ═══ 6.10. Leave - leave a DO loop ═══ Next Prev The LEAVE instruction leaves the innermost DO loop, or the named DO loop. ────LEAVE────┬──────┬───;──────────────── └─name─┘ Related Instruction: 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 Next Prev ═══ 6.11. Nop - dummy for THEN or ELSE ═══ Next Prev 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 Next Prev ═══ 6.12. Numeric - change math rules ═══ Next Prev 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──┘ Related Builtin Function: NUMERIC( ) 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"). 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 MVS). Note: On VM, the FORM keyword is only valid with options SCIENTIFIC and ENGINEERING for releases before VM/SP Release 6. Next Prev ═══ 6.13. Options - spcl, eg DBCS options ═══ Next Prev 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.) 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 Next Prev ═══ 6.14. Parse - break string into pieces ═══ Next Prev 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 MVS and VM only; LINEIN is OS/2 only. 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 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 EE REXX/Personal Mansfield Software Group's Personal REXX REXX370 MVS, TSO/E, VM interpreter REXXC370 VM CMS REXX compiler 2. The language level of the REXX implementation: 4.00 OS/2 EE, the new (2nd edition) Cowlishaw book 3.46 CMS Release 6 with and 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) 2.00 Mansfield Software Group (obviously, Mansfield doesn't use the same language level numbers as the IBM implementations). 3. The date of the implementation, in three tokens: 06 Feb 1990 OS/2 EE 11 Aug 1989 Mansfield Software Group's Personal REXX 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 EE fully qualified file name of procedure Personal REXX fully qualified file name of procedure name of exec as invoked default address env (DOS) 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 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. Next Prev ═══ 6.15. Procedure- def internal routine ═══ Next Prev 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──┴─┘ 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: 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. Next Prev ═══ 6.16. Pull - string <= queue/terminal/user ═══ Next Prev 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 Instruction: PARSE, PUSH, This is short for PARSE UPPER PULL. Example say "Please enter your name:" pull input say "Howdy," input"!" Next Prev ═══ 6.17. Push - (LIFO) string => queue ═══ Next Prev The PUSH instruction places an expression on top of the REXX queue. ──PUSH─────┬──────────────┬────────;── └──expression──┘ Related Instructions: PARSE, PULL, QUEUE Related Builtin Function: QUEUED( ) 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! Next Prev ═══ 6.18. Queue - (FIFO) string => queue ═══ Next Prev The QUEUE instruction places an expression on the bottom of the REXX queue. ──QUEUE────┬──────────────┬────────;── └──expression──┘ Related Instructions: PARSE, PULL, PUSH Related Builtin Function: QUEUED( ) 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! Next Prev ═══ 6.19. Return - exit routine to caller ═══ Next Prev Leaves an internal routine or function; "expression" is returned in variable RESULT. ──RETURN───┬──────────────┬────────;── └──expression──┘ Related Instruction: EXIT 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 Next Prev ═══ 6.20. Say - put text on screen ═══ Next Prev 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. Next Prev ═══ 6.21. Select - case statement ═══ Next Prev Use SELECT to choose amongst 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 is 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 */ Next Prev ═══ 6.22. Signal - special purpose GOTO ═══ Next Prev 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. FAILURE is not available on VM. 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. Next Prev ═══ 6.23. Trace - monitor/debug execution ═══ Next Prev TRACE supports the interactive debugging of REXX command procedures. ──TRACE──┬──────────────────────────────────────────┬──;─ ├────────number────────────────────────────┤ │ ┌───────────┐ │ │  │ │ └─┴─┬───────┬─┴─┬──────────────────────┬───┘ ├───?───┤ ├───All────────────────┤ ├───)───┤ ├───Commands───────────┤ └───!───┘ ├───Error──────────────┤ ├───Failure────────────┤ ├───Intermediates──────┤ ├───Labels─────────────┤ ├───Normal─────────────┤ ├───Negative───────────┤ ├───Off────────────────┤ ├───Results────────────┤ └───Scan───────────────┘ Or, alternatively: ──TRACE──┬────────────────────────────┬──;───────── ├────────string──────────────┤ ├────────symbol──────────────┤ └───┬───────┬───expression───┘ └─VALUE─┘ "Scan" is for MVS and VM only. ")" is for MVS only. "Failure" is not available on VM; "!" and "number" are for VM only; "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. Next Prev ═══ 6.24. Upper - make string all caps ═══ Next Prev UPPER translates text to uppercase. ┌───────────┐  │ ────UPPER───┴─variable──┴───────;────────────────── Note: MVS 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. Next Prev ═══ 7. REXX Builtin Functions ═══ Next Prev 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. Next Prev ═══ 7.1. Abbrev - match abbr string to full ═══ Next Prev 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. EXAMPLE 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 Next Prev ═══ 7.2. Abs - absolute value ═══ Next Prev ABS returns the absolute value of a number. ──ABS(number)──────────────────────────────────── 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 error like: 12 +++ Say 'abs("a") returns' abs('a'); REX0040: Error 40 running D:\Commands\TestREXX.cmd, line 12: Incorrect call to routine Next Prev ═══ 7.3. Address - return environment name ═══ Next Prev ADDRESS returns the name of the current environment for "host" commands, e.g., CMD, CMS, MVS, TSO, ISREDIT, etc. ──ADDRESS()────────────────────────────────────── This function is used only to query the current environment, not to set it. Next Prev ═══ 7.4. Arg - return argument, info ═══ Next Prev ARG returns the number of arguments, or the value of a specific argument. ──ARG(─┬───────────────────┬─)─────────────────── └─n──┬───────────┬──┘ └─,option───┘ 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 "" Next Prev ═══ 7.5. Beep - sound a tone ═══ Next Prev 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: quarter note = 120, so quarter note duration = 500 milliseconds. FULL 2000 HALF 1000 QUARTER 500 EIGHTH 250 SIXTEENTH 125 THIRTYSECOND 62 SIXTYFOURTH 31 Next Prev ═══ 7.6. BitAND - logical bit AND operation ═══ Next Prev BITAND does a logical AND of two strings on a bit-by-bit basis. ──BITAND(string1─┬───────────────────────┬─)───── └─,─┬────────┬─┬──────┬─┘ └─string2┘ └─,pad─┘ 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 operation 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 Next Prev ═══ 7.7. BitOR - logical bit OR operation ═══ Next Prev BITOR does a logical OR of two strings on a bit-by-bit basis. ──BITOR(string1─┬───────────────────────┬─)────── └─,─┬────────┬─┬──────┬─┘ └─string2┘ └─,pad─┘ 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 operation 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 Next Prev ═══ 7.8. BitXOR - logical exclusive OR operation ═══ Next Prev BITXOR does a logical XOR (exclusive OR) of two strings on a bit-by-bit basis. ──BITXOR(string1─┬───────────────────────┬─)───── └─,─┬────────┬─┬──────┬─┘ └─string2┘ └─,pad─┘ 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 operation 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 Next Prev ═══ 7.9. B2X - bit to hex conversion ═══ Next Prev B2X converts a character string containing ones and zeros into a character string containing hexadecimal characters. ──B2X(string)──────────────────────────────────── Note: not in MVS 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. B2X('11110001') is 'F1' B2X('101') is '5' B2X('1000 0010 1001 0001 1000 0010') is '829182' Next Prev ═══ 7.10. Center - center text in string ═══ Next Prev 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. Examples CENTER("ABC",8,'+') is '++ABC+++' CENTER('Catastrophe',5) is 'astro' CENTER('stints',0) is '' CENTER('stints',1) is 'i' CENTER('stints',2) is 'in' CENTER('stints',3) is 'tin' CENTER('stints',4) is 'tint' CENTER('stints',5) is 'stint' CENTER('stints',6) is 'stints' CENTER('stints',7) is 'stints ' CENTER('stints',8) is ' stints ' /* What's the longest word you can think of */ /* such that for all I from 1 to the */ /* length( yourword ), every instance of */ /* CENTER( yourword, I ) is an actual word in */ /* the dictionary? (like "stints" above) */ Note: the British spelling (CENTRE) is due to the origins of REXX with IBMer Mike Cowlishaw from England. Next Prev ═══ 7.11. CharIn - read a char from file ═══ Next Prev 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. 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. Next Prev ═══ 7.12. CharOut - write a char to file ═══ Next Prev CHAROUT writes lenght characters to the name stream. ──CHAROUT(─┬──────┬─┬───────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬─────────┬─┘ └─start──┘ └─,length─┘ Note: OS/2 EE has the only implementation. It is included in the new SAA REXX Level 2 specification. 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). Next Prev ═══ 7.13. Chars - return nr chars left in file ═══ Next Prev 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 EE has the only implementation. The new SAA REXX Level 2 specification includes it. 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 Next Prev ═══ 7.14. CMSFlag - return VM CMS settings ═══ Next Prev 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 │ └──────────┴────────────────────────────────────────┘ Next Prev ═══ 7.15. Compare - return pos of mismatch ═══ Next Prev 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 Next Prev ═══ 7.16. Condition - return trapped condition info ═══ Next Prev CONDITION returns information about a trapped condition, or the null string if no condition is currently trapped. ──CONDITION(─┬────────┬─)──────────────────────── └─option─┘ 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). Note: Not available on VM. Next Prev ═══ 7.17. Copies - return N copies of string ═══ Next Prev 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 "" Next Prev ═══ 7.18. C2D - char to decimal conversion ═══ Next Prev C2D converts the binary representation of a 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') is 193 /* EBCDIC */ C2D('A',1) is -63 /* EBCDIC */ C2D('A',2) is 193 /* EBCDIC */ C2D('A') is 65 /* ASCII */ C2D('A',1) is 65 /* ASCII */ C2D('A',2) is 65 /* ASCII */ C2D('2350'x) is 9040 /* portable */ Next Prev ═══ 7.19. C2X - char to hex conversion ═══ Next Prev C2X converts the binary representation of a string to a decimal number. ──C2X(string)──────────────────────────────────── Converts character to hexadecimal, like you would see in a dump of a file. Examples C2X('Aa.') is 'C1814B' /* EBCDIC */ C2X('Aa.') is '41612E' /* ASCII */ C2X('2350'x) is '2350' Next Prev ═══ 7.20. Datatype - return NUM, CHAR, (more) ═══ Next Prev DATATYPE classifies character strings as belonging to various lexical categories. ──DATATYPE(string─┬─────────┬─)────────────────── └──,type──┘ 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 │ │ DBCS string │ ├───────────────┼────────────────────────────────────────┤ │ DBCS │ returns 1 if string is a pure DBCS │ OS/2 │ │ 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 ') 'NUM' DATATYPE('') 'CHAR' DATATYPE('12-1') 'CHAR' DATATYPE('abc','A') 1 DATATYPE('abc','N') 0 DATATYPE('a285839985a3 83968485','X') 1 DATATYPE('?X','S') 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│ ├──────────╫──────┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │'. Next Prev ═══ 7.21. Date - return date, many formats ═══ Next Prev DATE returns a variety of formats for the current date . ──DATE(─┬──────────┬─)─────────────────────────── └──option──┘ The default option is "Normal." All calls in the same statement return the same value (thank goodness). ┌────────┬─────────────────────────────────────────────────────┐ │ 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, │MVS │ │ │ 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 │MVS,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 │no VM │ │ │between European and USA conventions │ ├────────┼───────────┼─────────────────────────────────────────┤ │Ordered │89/05/15 │yy/mm/dd │ ├────────┼───────────┼─────────────────────────────────────────┤ │Sorted │890515 │yymmdd │ ├────────┼───────────┼─────────────────────────────────────────┤ │Usa │05/15/89 │mm/dd/yy │ ├────────┼───────────┼─────────────────────────────────────────┤ │Weekday │Monday │day of week, English, mixed case │ └────────┴───────────┴─────────────────────────────────────────┘ 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 /* MVS,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 Next Prev ═══ 7.22. DBCS - Double Byte CharSet functions ═══ Next Prev 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 Next Prev ═══ 7.23. DelStr - return string w/o/substring ═══ Next Prev 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) is 'car' DELSTR('carpet',4,1) is 'caret' DELSTR('carpet',4,2) is 'cart' DELSTR('carpet',1,3) is 'pet' Next Prev ═══ 7.24. DelWord - return string w/o/subwords ═══ Next Prev 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) 'response is valid' DELWORD('response is not valid',2) 'response' Next Prev ═══ 7.25. Diag - issue VM CP DIAGNOSE instruction ═══ Next Prev DIAG communicates with the CP via a dummy DIAGNOSE instruction. ──DIAG(n──┬───┬──┬───────────┬─)───────────────── └─?─┘ │┌─────────┐│ │ ││ └┴─,number─┴┘ Note: VM only. See manual for details. Next Prev ═══ 7.26. DiagRC - return char version VM CP DIAGNOSE ═══ Next Prev DIAGRC is like DIAG, except data returned is prefixed by return and condition codes. ──DIAGRC(n──┬───┬──┬───────────┬─)─────────────── └─?─┘ │┌─────────┐│ │ ││ └┴─,number─┴┘ Note: VM only. See manual for details. Next Prev ═══ 7.27. Digits - return NUMERIC DIGITS ═══ Next Prev DIGITS returns the current NUMERIC DIGITS setting. ──DIGITS()─────────────────────────────────────── 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. Note: Not available on VM. Next Prev ═══ 7.28. Directory - change, return curr directory ═══ Next Prev 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. Next Prev ═══ 7.29. D2C - decimal to char conversion ═══ Next Prev 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) 'C1'x /* 'A' in EBCDIC */ D2C(65) '41'x /* 'A' in ASCII */ D2C(-1) /* illegal */ D2C(-1,2) 'FFFF'x D2C(-1,4) 'FFFFFFFF'x D2C(10000012,4) '0098968C'x D2C(9040) '2350'x D2C(9040,1) '50'x D2C(9040,2) '2350'x D2C(9040,3) '002350'x D2C(9040,4) '00002350'x Next Prev ═══ 7.30. D2X - decimal to hex conversion ═══ Next Prev 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) 'C1' D2X(193,1) '1' D2X(193,2) 'C1' D2X(193,3) '0C1' D2X(193,4) '00C1' D2X(-1) /* illegal */ D2X(-1,1) 'F' D2X(-1,2) 'FF' D2X(-1,3) 'FFF' D2X(-1,4) 'FFFF' C2X(D2C(number,n)) is D2X(number,2*n) Next Prev ═══ 7.31. EndLocal - restore environment ═══ Next Prev ENDLOCAL undoes the effect of the last SETLOCAL. ──ENDLOCAL( )────────────────────── 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 Next Prev ═══ 7.32. ErrorText - return REXX errmsg text ═══ Next Prev ERRORTEXT returns the error message text for REXX error message n. ──ERRORTEXT(n)─────────────────────────────────── 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. OS/2 EE Error Messages 1: File Table full (No message in Personal REXX) 2: Interpret expression > 64000 characters (No message in Personal REXX) 3: Program is unreadable (No message in Personal REXX) 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 12: Clause longer than 1000 characters (Personal REXX) 13: Invalid character in program 14: Incomplete DO/SELECT/IF 15: Invalid hexadecimal or binary string : Invalid hexadecimal constant (Personal REXX) 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 (No message in Personal REXX) 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 : Environment not found (Personal REXX) 30: Name or string too long : Name or string longer than 250 characters (Personal REXX) 31: Name starts with number or "." 32: Invalid use of stem (Personal REXX, TSO/E) 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 (No message in Personal REXX) 47: (No message in OS/2 EE, Personal REXX) 48: Failure in system service 49: Interpretation error 50: Error in called routine (Personal REXX) 51: Line is longer than 250 characters (Personal REXX) 52: Not compiled - cannot execute (Personal REXX) 53: INTERPRET not supported (Personal REXX) 115: The RXSUBCOM parameters are incorrect (No message in Personal REXX) 116: The RXSUBCOM parameter REGISTER is incorrect (No message in Personal REXX) 117: The RXSUBCOM parameter DROP is incorrect (No message in Personal REXX) 118: The RXSUBCOM parameter LOAD is incorrect (No message in Personal REXX) 119: Invalid file name (No message in Personal REXX) Next Prev ═══ 7.33. Externals - return nr elements in CMS terminal buffer ═══ Next Prev EXTERNALS returns the number of elements in the terminal input buffer (type-ahead). ──EXTERNALS( )─────────────────────────────────── Next Prev ═══ 7.34. FileSpec - parse OS/2 filespec ═══ Next Prev FILESPEC can return the drive, the directory, or the filename of a given file specification. ──FILESPEC(option,filespec)────────────── This is only guaranteed to work on file specifications that are valid. The options are:  Drive  Path  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") is "C:" filespec("p","C:CONFIG.SYS") is "" filespec("n","C:CONFIG.SYS") is "CONFIG.SYS" filespec("d","C:\CONFIG.SYS") is "C:" filespec("p","C:\CONFIG.SYS") is "\" filespec("n","C:\CONFIG.SYS") is "CONFIG.SYS" filespec("D","C:/os2\cmd.Exe") is "C:" filespec("P","C:/os2\cmd.Exe") is "/os2\" filespec("N","C:/os2\cmd.Exe") is "cmd.exe" filespec("D","abc\def") is "" filespec("P","abc\def") is "abc\def" filespec("N","abc\def") is "" filespec("D","abc\def:g:a.b/c") is "abc\def:" filespec("P","abc\def:g:a.b/c") is "abc\def:g:a.b/" filespec("N","abc\def:g:a.b/c") is "c" Next Prev ═══ 7.35. Find - VM name for WORDPOS ═══ Next Prev FIND is the same as WORDPOS(phrase, string). ──FIND(string,phrase)──────────────────────────── Same as WORDPOS(phrase,string); use FIND on VM - WORDPOS not implemented in older versions. Next Prev ═══ 7.36. Form - return NUMERIC FORM ═══ Next Prev FORM returns the current setting of NUMERIC FORM (SCIENTIFIC or ENGINEERING). ──FORM()───────────────────────────── Note: Not available on VM. Next Prev ═══ 7.37. Format - return rounded, formatted nr ═══ Next Prev FORMAT prepares a number for display, rounding and formatting. ──FORMAT(number─┬───────────────────────────────────────────┬─)─ └─,─┬──────┬─┬─────────────────────────────┬┘ └before┘ └,─┬─────┬─┬─────────────────┬┘ └after┘ └─,─┬────┬─┬─────┬┘ └expp┘ └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) ' 3' FORMAT('2.7128',2,0) ' 3' FORMAT('2.7128',2,3) ' 2.713' FORMAT('-2.7128',2,5) '-2.71280' FORMAT('3.14159262',0,4) '.1416' Note: VM (R.4) does not implement expp and expt. Next Prev ═══ 7.38. Fuzz - return NUMERIC FUZZ ═══ Next Prev ──FUZZ()───────────────────────────────────────── Returns current setting of NUMERIC FUZZ Not available on VM. Next Prev ═══ 7.39. Index - same as POS function ═══ Next Prev ──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 INDEX('abracadabra','dab') 7 INDEX('abracadabra','dba') 0 INDEX('abracadabra','ab') 1 INDEX('abracadabra','ab',2) 8 INDEX('abracadabra','ab',9) 0 Next Prev ═══ 7.40. Insert - insert new string into old ═══ Next Prev ──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." INSERT('abcd','efg') 'abcdefg' INSERT('abcd','efg',3) 'efgabcd' INSERT(' ','efg',2) 'ef g' INSERT('second','first',9,8,'*') 'first***second**' Next Prev ═══ 7.41. Justify - return justified text ═══ Next Prev ──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. JUSTIFY('This is balanced.',21) 'This is balanced.' Next Prev ═══ 7.42. LastPos - return pos of last needle in haystack ═══ Next Prev ──LASTPOS(needle,haystack──┬─────────┬─)───────── └─,start──┘ 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. LASTPOS('abra','abracadabra') 8 Next Prev ═══ 7.43. Left - return leftmost chars, padded ═══ Next Prev ──LEFT(string,length──┬───────┬─)──────────────── └─,pad──┘ returns the leftmost "length" characters of "string," padded, if necessary, with "pad." LEFT('abracadabra',2) 'ab' cols=LEFT('a',4)LEFT('b',4)'c' say cols 'a b c' Next Prev ═══ 7.44. Length - return string length ═══ Next Prev ──LENGTH(string)───────────────────────────────── returns the length of "string." LENGTH('ab c') 4 LENGTH('ab c ') 6 LENGTH('') 0 Next Prev ═══ 7.45. LineIn - read a line from file ═══ Next Prev ──LINEIN(─┬──────┬─┬───────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬────────┬─┘ └─start──┘ └─,count─┘ Note: OS/2 only; ?probably to be included in the next SAA spec. Returns a line from the input stream "name." The "count" defaults to 1. Count is 0 or 1. Next Prev ═══ 7.46. LineOut - write a line to file ═══ Next Prev ──LINEOUT(─┬──────┬─┬───────────────────────────┬─)─── └─name─┘ └─,──┬────────┬─┬───────┬─┘ └─string─┘ └─,line─┘ Note: OS/2 only; probably to be included in the next SAA spec. 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. Next Prev ═══ 7.47. Lines - return nr lines left in file ═══ Next Prev ──LINES(─┬──────┬─)─── └─name─┘ Note: OS/2 only; probably to be included in the next SAA spec. 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: call lineout outfile,,1 /* open, position to end */ do while lines(myfile) call linein myfile, thisline call lineout myfile, thisline end Next Prev ═══ 7.48. LineSize - return current terminal linesize ═══ Next Prev ──LINESIZE()───────────────────────────────────── returns the terminal line width - 1; in background TSO, always returns 132. Next Prev ═══ 7.49. Max - return largest in arg list ═══ Next Prev ──MAX(number─┬───────────┬─)───────────────────── │┌─────────┐│ │ ││ └┴─,number─┴┘ 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). Next Prev ═══ 7.50. Min - return smallest in arg list ═══ Next Prev ──MIN(number─┬───────────┬─)───────────────────── │┌─────────┐│ │ ││ └┴─,number─┴┘ 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). Next Prev ═══ 7.51. Numeric - return smallest in arg list ═══ Next Prev ──NUMERIC(number─┬───────────┬─)───────────────────── │┌─────────┐│ │ ││ └┴─,number─┴┘ xxxxxxxxxxxxxxxxxxxxxxxxxxxxin 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). Next Prev ═══ 7.52. Overlay - overlay part of old with new ═══ Next Prev ──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." OVERLAY(' ','invalid') ' valid' OVERLAY('1',OVERLAY('2','Version 1 Release 4',9),19) 'Version 2 Release 1' Next Prev ═══ 7.53. Pos - return pos of needle in haystack ═══ Next Prev ──POS(needle,haystack──┬─────────┬─)───────────── └─,start──┘ 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. POS('/','09/23/52') 3 POS('/','09/23/52',4) 5 POS('6','09/23/52',4) 0 Next Prev ═══ 7.54. Queued - return nr lines in queue ═══ Next Prev ──QUEUED()─────────────────────────────────────── 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. Next Prev ═══ 7.55. Random - return random whole nr in range ═══ Next Prev ──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. Next Prev ═══ 7.56. Reverse - return 'string' -> 'gnirts' ═══ Next Prev ──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. REVERSE('stop') 'pots' REVERSE('oprah') 'harpo' REVERSE('radar') 'radar' Next Prev ═══ 7.57. Right - return rightmost chars, padded ═══ Next Prev ──RIGHT(string,length──┬───────┬─)─────────────── └─,pad──┘ returns the rightmost "length" characters of "string," padded, if necessary, with "pad." RIGHT('example',5) 'ample' cols=RIGHT('a',4)RIGHT('b',4)'c' say cols ' a bc' Next Prev ═══ 7.58. Sign - return 1, 0, -1 ═══ Next Prev ──SIGN(number)─────────────────────────────────── returns -1 if negative, +1 if positive, 0 if zero. Next Prev ═══ 7.59. SourceLine - return line I of this REXX pgm ═══ Next Prev ──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. Next Prev ═══ 7.60. Space - return with N padchars between words ═══ Next Prev ──SPACE(string─┬─────────────────────┬─)───────── └─,──┬───┬─┬────────┬─┘ └─n─┘ └──,pad──┘ reformats the words in "string" by placing exactly "n" copies of "pad" between each word. SPACE('a b cd',3) 'a b cd' SPACE('a b cd',0) 'abcd' SPACE('This is an example') 'This is an example' Next Prev ═══ 7.61. Storage - return, modify machine storage ═══ Next Prev ──STORAGE(─┬─────────┬─┬────────────────────────┬─)─ └─address─┘ └─,─┬────────┬─┬───────┬─┘ └─length─┘ └─,data─┘ 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 manual before using this option. Next Prev ═══ 7.62. Strip - return w/leading and/or trailing removed ═══ Next Prev ──STRIP(string─┬──────────────────────────┬─)──── └─,──┬────────┬─┬────────┬─┘ └─option─┘ └──,char─┘ removes the leading and/or trailing "char" from the "string;" the options are "Leading(L)," "Trailing(T)," or "Both(B)." STRIP('0000981.3',L,0) '981.3' STRIP(' how are you? ') 'how are you?' a useful combination is: SPACE(STRIP(' how are you? ')) 'how are you?' Next Prev ═══ 7.63. Substr - return part of string ═══ Next Prev ──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. SUBSTR('basic',2,3) 'asi' SUBSTR('basic',2) 'asic' SUBSTR('DTSS CO',6,5,'.') 'CO...' Next Prev ═══ 7.64. Subword - return some words from string ═══ Next Prev ──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." SUBWORD('A quick brown ',2) 'quick brown' SUBWORD('A quick brown ',2,1) 'quick' SUBWORD('A quick brown ',4,1) '' Next Prev ═══ 7.65. Symbol - return VAR, LIT, BAD ═══ Next Prev ──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. Next Prev ═══ 7.66. Time - return time, many formats ═══ Next Prev ──TIME(─┬────────┬─)───────────────────────────── └─option─┘ ┌────────────┬──────────────────────────────────────────────┐ │ Option │ Example │ ├────────────┼──────────────────────────────────────────────┤ │ _Civil │ '7:15pm' │no VM ├────────────┼──────────────────────────────────────────────┤ │ _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' │no VM ├────────────┼──────────────────────────────────────────────┤ │ _Reset │ 123456789.123456 │ │ │ time since elapsed-time clock started/reset │ ├────────────┼──────────────────────────────────────────────┤ │ _Seconds │ 69331 /* 31 + 60*(15+60*19) */ │ └────────────┴──────────────────────────────────────────────┘ Next Prev ═══ 7.67. Trace - return, set TRACE options ═══ Next Prev ──TRACE(─┬────────┬─)──────────────────────────── └─option─┘ returns the current TRACE actions; can also set TRACE options. Example: save_trace = trace('?R') /* saves, sets ...*/ ... /* trace some code */ TRACE VALUE save_trace /* reset trace */ Next Prev ═══ 7.68. Translate - return string translated char for char ═══ Next Prev ──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. TRANSLATE('AbCdEfGhI') 'ABCDEFGHI' TRANSLATE('301-41-8397',,'-') '301 41 8397' TRANSLATE('12 34 56 78','C4A49497','12345678') 'C4 A4 94 97' Next Prev ═══ 7.69. Trunc - return integer part of nr ═══ Next Prev ──TRUNC(number─┬─────┬─)───────────────────────── └─,n──┘ truncates the "number" to "n" decimal places; "n" defaults to zero. TRUNC(123.456) 123 TRUNC(123.456,2) 123.45 TRUNC(123.4,2) 123.40 Next Prev ═══ 7.70. Userid - return system's id for user ═══ Next Prev ──USERID()─────────────────────────────────────── 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. USERID() '@64BB' Next Prev ═══ 7.71. Value - return value of name expression ═══ Next Prev ──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. Next Prev ═══ 7.72. Verify - return 0 or pos of non-verified char ═══ Next Prev ──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 "Match(M)" or "Nomatch(N);" "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). Note: VM only implements "Match" VERIFY('123','0123456789') 0 VERIFY('123','0123456789','N') 0 VERIFY('123','0123456789','M') 1 VERIFY('A23','0123456789','N') 1 VERIFY('A23','0123456789','M') 2 Next Prev ═══ 7.73. Word - return word N from string ═══ Next Prev ──WORD(string,n)───────────────────────────────────────── returns the "nth" blank-delimited word from "string;" same as SUBWORD(). Next Prev ═══ 7.74. WordIndex - return char pos of word N in string ═══ Next Prev ──WORDINDEX(string,n)──────────────────────────────────── returns the character position of the first character in the "nth" word of the "string." WORDINDEX('Four score and',1) 1 WORDINDEX('Four score and',2) 6 WORDINDEX('Four score and',3) 12 WORDINDEX('Four score and',4) 0 Next Prev ═══ 7.75. WordLength - return char lth of word N in string ═══ Next Prev ──WORDLENGTH(string,n)─────────────────────────────────── returns the length of the "nth" word in the "string." WORDLENGTH('Four score and',1) 4 WORDLENGTH('Four score and',2) 5 WORDLENGTH('Four score and',3) 3 WORDLENGTH('Four score and',4) 0 Next Prev ═══ 7.76. WordPos - return wordnr of needleword in haystackstring ═══ Next Prev ──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. Note: Not available on VM; see FIND. WORDLENGTH('Four','Four score and') 1 WORDLENGTH('score','Four score and') 2 WORDLENGTH('and','Four score and') 3 WORDLENGTH('score and','Four score and') 3 WORDLENGTH('seven','Four score and') 0 Next Prev ═══ 7.77. Words - return nr of words in string ═══ Next Prev ──WORDS(string)────────────────────────────────────────── returns the number of words in the "string." WORDS('Four score and') 3 WORDS('Four-score-and') 1 WORDS(' ') 0 WORDS('') 0 Next Prev ═══ 7.78. XRange - return all one-byte codes incl in range ═══ Next Prev ──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: Use: 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 exactly correctly with ASCII -- it includes too many characters with EBCDIC. Next Prev ═══ 7.79. X2C - convert hex to character ═══ Next Prev ──X2C(hexstring)───────────────────────────────────────── converts hexadecimal to character. X2C('d5a6a64089a240a38885') 'Now is the' X2C('F1F2F3') '123' Next Prev ═══ 7.80. X2D - convert hex to decimal ═══ Next Prev ──X2D(hexstring─┬────┬─)───────────────────────────────── └─,n─┘ converts hexadecimal 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. X2D('C1') 193 X2D('001') 1 X2D('2374') 9076 X2D('FF') 255 X2D('FF',0) 0 X2D('FF',2) -1 X2D('FF',4) 255 Next Prev ═══ 8. Functional Groupings ═══ Next Prev The sections that follow constitute functional groupings of the REXX builtin functions and keyword instructions. This functional view may prove more useful for lookups when you know what you want to do, but not the name of the REXX language part that does it. Next Prev ═══ 8.1. Command Environment ═══ Next Prev kwaddres bfaddres Next Prev ═══ 8.2. Programs - calling, defining, arguments ═══ Next Prev kwcall kwproced kwarg bfarg kwparse kwexit kwreturn Next Prev ═══ 8.3. Execution control - sequencing, conditionals, iteration ═══ Next Prev kwdo kwiterate kwleave kwif kwselect kwnop kwsignal kwcall on Next Prev ═══ 8.4. Input, Output ═══ Next Prev cmexecio kwpull kwpush kwqueue bfqueued kwsay bflinesize bfcharin bfcharout bfchars bflinein bflineout bflines Next Prev ═══ 8.5. Variables, interpretation, environment ═══ Next Prev kwdrop bfsymbol kwinterpret bfvalue kwnumeric kwoptions bfdbcs kwparse version, source bfdate bftime bfuserid bfdirectory bfsetlocal bfendlocal bffilespec bfexternals bfbeep bfcmsflag bfstorage Next Prev ═══ 8.6. Diagnostics, Tracing, Error Recovery ═══ Next Prev kwsignal kwcall on bfcondit bferrortext kwtrace bftrace bfdiag dfdiagrc bfsourceline Next Prev ═══ 8.7. Strings as Numbers ═══ Next Prev bfabs bfsign bftrunc bfdatatype bfd2x bfx2d bfd2c bfc2d kwnumeric bfform bffuzz bfdigits bfformat bfmax bfmin bfrandom Next Prev ═══ 8.8. Strings as bits ═══ Next Prev bfbitand bfbitor bfbitxor bfb2x bfx2b Next Prev ═══ 8.9. Strings as hexadecimal ═══ Next Prev bfc2x bfx2c bfd2x bfx2d bfxrange Next Prev ═══ 8.10. Strings as lists of words ═══ Next Prev bfdelword bfspace kwparse bfsubword bfword bfwordpos bfwordindex bfwordlength bfwords Next Prev ═══ 8.11. Changing Strings; making new strings ═══ Next Prev kwupper bftranslate kwparse bfinsert bfdelstr bfoverlay bfleft bfright bfcenter bfjustify bfspace bfstrip bfcopies bfreverse Next Prev ═══ 8.12. Searching, Matching, extracting Strings ═══ Next Prev bfabbrev bfcompare bffind bfindex bfpos bflastpos bfsubstr kwparse bfverify Next Prev ═══ 8.13. About Strings ═══ Next Prev bflength Next Prev ═══ 9. Parsing ═══ Next Prev Next Prev ═══ 10. Arithmetic ═══ Next Prev Next Prev ═══ 11. Input and Output ═══ Next Prev Next Prev ═══ 12. Debugging ═══ Next Prev Next Prev ═══ 13. Conditions and Traps ═══ Next Prev Next Prev ═══ 14. Reserved Words ═══ Next Prev Next Prev ═══ 15. Efficiency Considerations ═══ Next Prev Next Prev ═══ 16. Hints, Tips, and Tricks ═══ Next Prev Next Prev ═══ 17. Programming APIs ═══ Next Prev Next Prev ═══ 18. DBCS Support ═══ Next Prev Next Prev ═══ 19. Language Limits ═══ Prev ═══ ═══ Quercus Systems Quercus Systems PO Box 2157 Saratoga, CA 95070 (408) 257-3697 ═══ ═══ Name expression An variable whose value is a list of variable names. This is a form of indirection. ═══ ═══ 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 ═══ ═══ REXX expressions are sequences of terms, operators, and parentheses (round brackets, for those of you in the UK). Terms are:  Literals, which include character strings, hexadecimal strings, binary strings, and numbers.  Variables,which are simple or compound symbols.  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  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 ..."  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 )  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  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 habits take 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 \ 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. ═══ ═══ REXX expressions are sequences of terms, operators, and parentheses (round brackets, for those of you in the UK). Terms are:  Literals, which include character strings, hexadecimal strings, binary strings, and numbers.  Variables,which are simple or compound symbols.  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  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 ..."  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 )  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  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 habits take 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 \ 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. ═══ ═══ 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 EE 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 ═══ ═══ 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. ═══ ═══ non-negative numeric expression an expression that evaluates to a non-negative (>=0) numeric value. ═══ ═══ non-negative numeric expression an expression that evaluates to a non-negative (>=0) numeric value. ═══ ═══ numeric expression an expression that evaluates to a numeric value. ═══ ═══ numeric expression an expression that evaluates to a numeric value. ═══ ═══ non-negative numeric expression an expression that evaluates to a non-negative (>=0) numeric value. ═══ ═══ boolean expression an expression that evaluates to 1 (meaning true) or 0 (meaning false). Unlike C, all non-zero numbers are not considered to be equivalent to "true." ═══ ═══ boolean expression an expression that evaluates to 1 (meaning true) or 0 (meaning false). Unlike C, all non-zero numbers are not considered to be equivalent to "true." ═══ ═══ 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 Contents 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 key 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 the 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. "p.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 Options pull-down, highlight the choice and press the F1 key. ═══ ═══ 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, MVS, and TSO environments also support the characters @#$Ы in symbols. Avoid them for the sake of portability. ═══ ═══ Mansfield Software Group Mansfield Software Group PO Box 532 Storrs, CT 06268 (203) 429-8402 Compuserve: GO PCVENA (Section 2) BIX: mansfield ═══ ═══ Instruction **Not written yet** ═══ ═══ Length **Not written yet** ═══ ═══ Number **Not written yet** ═══ ═══ String **Not written yet** ═══ ═══ Variable **Not written yet**