Upload
lamdien
View
284
Download
12
Embed Size (px)
The Rexx Language
A programmers introduction to the Rexx programming language
This presentation assumes some familiarity with a typical 3rd generation programming language such as COBOL
Road Map• Generalities• Symbols and symbol evaluation• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Road Map• Generalities• Symbols and symbol evaluation• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Rexx W5• Who?
M.F. Cowlishaw • Where?
IBM UK Labs (same lab responsible for CICS development)• When?
1982 – First commercial release from IBM• What?
General purpose, easy to use scripting language• Why?
Replacement for EXEC (CMS) and CLIST (TSO)
Rexx runs under many address spaces
MVS
TSO
ISPF
SPF Edit
Rexx (CUT / PASTE)
What is Rexx good for?• Glue! Connect multiple utilities in unique ways to add
“value” to their operation
• Small utility programs– Data fix SQL generation– Formatting data– Filtering data– Static code analysis
• Macros, CUT / PASTE
• Text manipulation
What does Rexx look like?
Multiple choice quiz:
Rexx looks like…
A) Any other procedural language (e.g. COBOL)B) Nothing that you have ever seen beforeC) Both of the above
What does Rexx look like?
Multiple choice quiz:
Rexx looks like…
A) Any other procedural language (e.g. COBOL)B) Nothing that you have ever seen beforeC) Both of the above
Correct answer: C
What does Rexx look like?/* this is what a comment looks like */say “count down by 2’s…”do i = 10 to 0 by -2 say iend
count down by 2’s…1086420
Rexx: Defining characteristics• Procedural language• Small set of instructions and functions• Minimal syntax and structure• Only one data type: String• “Associative” memory model• May be interpreted or compiled
Procedural language…• Assignments: A = B• Expressions: A + B• Conditional instructions: IF A = B THEN…• Looping instructions: DO WHILE A > B…• Procedures: CALL SOMEPROCEDURE• Functions: A = SOMEFUNCTION(B)• Return values from procedures: RETURN A
All “stuff” most programmers have seen beforeNote: Some variants of Rexx are Object Oriented (e.g. ooRexx)
Small set of instructions & functions
23 key word instructions:
ADDRESS, ARG, CALL, DO, DROP, EXIT, IF, INTERPRET, ITERATE, LEAVE, NOP, NUMERIC, OPTIONS, PARSE, PROCEDURE, PULL, PUSH, QUEUE, RETURN, SAY, SELECT, SIGNAL, TRACE
Compare to COBOL which has 56 verbs
Small set of instructions & functions
Built in Functions:ABBREV, ABS, ADDRESS, ARG, BITAND, BITOR, BITXOR, B2X, CENTER, CHARIN, CHAROUT, CHARS, COMPARE, CONDITION, COPIES, C2D, C2X, DATATYPE, DATE, DELSTR, DELWORD, DIGITS, D2C, D2X, ERRORTEXT, FORM, FORMAT, FUZZ, INSERT, LASTPOS, LEFT, LENGTH, LINEIN, LINEOUT, LINES, MAX, MIN, OVERLAY, POS, QUEUED, RANDOM, REVESE, RIGHT, SIGN, SOURCELINE, SPACE, STREAM, STRIP, SUBSTR, SUBWORD, SYMBOL, TIME, TRACE, TRANSALTE, TRUNC, VALUE, VERIFY, WORD, WORDINDEX, WORDLENGTH, WORDPOS, WORDS, XRANGE, X2B, X2C, X2D
You can probably get by only using the 20 underlined functions – or fewer.
Minimal syntax and structure• Free format
• Semicolon is the statement delimiter– Every source line is implicitly terminated by a
semicolon, unless explicitly continued with a comma…
• Comma has special significance as:– Line continuation character– Expression delimiter in argument lists
• Space is largely irrelevant, except when it is an operator!
Minimal syntax and structure• No reserved words (COBOL has about 400!)
• A symbol is identified as an instruction, function or variable depending upon the context in which it appears.
Consequently…. the following is a legal program!
IF = DOIF IF = DO THEN DO; SAY DO IF; ENDRETURN
Road Map• Generalities• Symbols and symbol evaluation
• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Symbols and Symbol Evaluation
• Understanding symbols and their evaluation is the key to understanding Rexx
• Symbols are composed of letters (upper or lower case), digits and the characters: period, exclamation mark, question mark and underscore (a-z A-Z 0-9 . ! ? _)
• Four types of symbol:– Constant– Simple– Stem– Compound
Each having distinct characteristics
Four types of symbol preview…
• Constant– Begins with a digit or period– Cannot be assigned a value– They usually look like, and are used as, numbers– Examples: 9 3e4 .9 5. 3.5 3D
• Simple– Does not start with a digit– Does not contain a period– Can be assigned a value– Examples: SIMPLE ?EH WHAT_THE!
• Stem– Looks like a simple symbol but last character is a period– Can be assigned a value– Examples: SIMPLE. ?EH. WHAT_THE!.
• Compound– Looks like a stem with the addition of a tail portion– The tail is an arbitrary number of nulls, constant or simple symbols each separated by a
period.– Can be assigned a value– Examples: SIMPLE.X ANOTHER.X.Y YET.ANOTHER.
Symbols: Common Attributes…• Symbol names are folded to upper case before evaluation
– Implication: Symbol names are case insensitive
• All symbols are evaluated as they are encountered
• All symbols evaluate to strings– String is the only data type that Rexx has
• The value of that string is the value of the symbol. – Implication: symbols play the role of variables (duh…)
• Symbols evaluate to their own name until assigned a value– Implication:
• Variables (symbols) are not explicitly declared • All symbols have a value• Unassigned symbols evaluate to their own name
Symbols continued…• Constant symbols
– Must begin with a digit or a period– Cannot be assigned a value– Evaluate to a string containing its name folded to upper case– The value of that string is value of the symbol (constant)
• 42 is a constant symbol evaluating to the string ‘42’
• Rexx can interpret any string that looks like a number as number: – Consequently 42 + 1 is a legal expression evaluating to the string ‘43’– Similarly, the literal string values ‘42’and ‘1’ look like a numbers so
the expression ‘42’ + ‘1’ also evaluates to the string ‘43’• Constant symbol: 9a evaluates to the string ‘9A’
42 is the Answer to the Ultimate Question of Life, the Universe, and Everything (Hitchhiker's Guide to the Galaxy)
Symbols continued…• Simple symbols (variables)
– Do not begin with a digit or contain a period– May be assigned a value– Evaluated by folding name to upper case and then evaluating that name – All symbols evaluate to their name until assigned a value– After assignment symbols evaluate to the value assigned to them– All symbols evaluate to strings
• MyVar is a symbol evaluating to the string ‘MYVAR’ until assigned an explicit value
• MyVar = 42 assigns the string value ‘42’ to the symbol MyVar• MyVar now evaluates to the string ‘42’
Symbols continued…• Stem Symbols (variables)
– Look like simple symbols but end with a period– Behave in a manner similar to simple symbols
• MyVar. is a stem symbol evaluating to the string ‘MYVAR.’ until assigned an explicit value
• MyVar. = 42 assigns the string value ‘42’ to the stem symbol MyVar. and every other symbol within scope sharing the same stem name
• Which quickly brings us to compound symbols…
Symbols continued…• Compound Symbols (variables)
– Looks like a stem with the addition of a tail portion– The tail is an arbitrary number of nulls, constant or simple symbols each
separated by a period.– Note: null, in this case, means nothing, as opposed to the null string
• MyVar.x is a compound symbol evaluating to the string ‘MYVAR.X’ until assigned an explicit value
• MyVar. = 42 assigns the string value ‘42’ to the stem symbol MyVar. and every other symbol within scope sharing the same stem name. Implication: MyVar.x now evaluates to: ‘42’ because its stem was assigned this value.
• MyVar.x = ‘Rexx’ assigns the string ‘Rexx’ to the compound symbol MyVar.x but all unassigned variables sharing the same stem will still evaluate to ‘42’
Symbols in action… Worth the pain…
Say MyVar /* display value of simple symbol */MyVar = Hello /* assign value to simple symbol */Say MyVar /* display it again… */
MYVAR HELLO
Produces…
Trivial…
Symbols in action…Say MyVar. /* display value of stem symbol */MyVar. = Hello /* assign value to stem symbol */Say MyVar. /* value of stem symbol */Say MyVar /* value of simple symbol */Say MyVar.MyVar /* value of compound symbol */MyVar.MyVar = ‘New’ /* assign to compound symbol */Say MyVar.MyVar /* value of compound symbol */MyVar = ‘x’ /* assign value to simple symbol */Say MyVar.MyVar
MYVAR. HELLO MYVARHELLONewHELLO
Produces…
Compound symbol evaluationCompound Symbol = Stem Symbol + Tail
Tail is a collection of Simple Symbols, constants and nulls separated by periods (dots)
Evaluation proceeds as follows:–Stem is taken as-is (fold to upper case, not evaluated)–Evaluate each symbol in the Tail (between the dots)–Derive ‘new’ symbol name from: Stem + Evaluated Tail
symbols (keeping dots)–Evaluate the derived name as a complete symbol (not
folded to upper case)
Compound symbol evaluationMyVar. = Hello /* assign value to stem symbol */MyVar.MyVar = ‘New’ /* assign to compound symbol */Say MyVar.MyVar /* value of compound symbol */
New
Produces…
• Simple symbol MyVar has not been assigned a value• Evaluates to its own name in upper case: MYVAR• Derived symbol name becomes: MYVAR.MYVAR• Assign ‘New’ to the derived symbol name• Say then applies the same process and displays the
value of symbol: MYVAR.MYVAR
Compound symbol evaluationMyVar. = Hello /* assign value to stem symbol */MyVar.MyVar = ‘New’ /* assign to compound symbol */MyVar = ‘x’Say MyVar.MyVar
HELLO
Produces…
Because…• Stem is assigned string value: ‘HELLO’• Simple symbol MyVar is assigned string value ‘x’• Compound symbol now yields derived name: MYVAR.x • Symbol MYVAR.x was never explicitly assigned a value.• All unassigned symbols having stem MyVar. take on
the stem default value: ‘HELLO’
Compound symbol evaluation
WeekDay.1 = ‘Sunday’WeekDay.2 = ‘Monday’…Weekday.7 = ‘Saturday’do i = 1 to 7 say i WeekDay.i /* looks like an “array” */end
1 Sunday2 Monday…7 Saturday
Produces…
The illusion of an array (table) may be created using compound symbols because:• Any string that looks like a number can be used as one• The evaluation process as it is applied to compound symbols
Compound symbol evaluationWeekDays = ‘Sun Mon Tue Wed Thu Fri Sat’WeekDay.Sun = ‘Sunday’WeekDay.Mon = ‘Monday’…Weekday.Sat = ‘Saturday’do i = 1 to words(WeekDays) wd = word(WeekDays, i) say i wd WeekDay.wdendProduces…
Compound symbol evaluationWeekDays = ‘Sun Mon Tue Wed Thu Fri Sat’WeekDay.Sun = ‘Sunday’WeekDay.Mon = ‘Monday’…Weekday.Sat = ‘Saturday’do i = 1 to words(WeekDays) wd = word(WeekDays, i) say i wd WeekDay.wdend
1 Sun WEEKDAY.Sun2 Mon WEEKDAY.Mon…7 Sat WEEKDAY.Sat
Produces…
• Stem + evaluated Tail yield a derived name. The derived name is evaluated as a symbol without folding to upper case
Compound symbol evaluationWeekDays = ‘SUN MON TUE WED THU FRI SAT’WeekDay.Sun = ‘Sunday’WeekDay.Mon = ‘Monday’…Weekday.Sat = ‘Saturday’do i = 1 to words(WeekDays) wd = word(WeekDays, i) say i wd WeekDay.wdend
1 SUN Sunday2 MON Monday…7 SAT Saturday
Produces…
Compound symbol evaluationWeekDays = ‘Sun Mon Tue Wed Thu Fri Sat’Sun = word(WeekDays, 1); WeekDay.Sun = ‘Sunday’Mon = word(WeekDays, 2); WeekDay.Mon = ‘Monday’…Sat = word(WeekDays, 7); Weekday.Sat = ‘Saturday’do i = 1 to words(WeekDays) wd = word(WeekDays, i) say i wd WeekDay.wdend
1 Sun Sunday2 Mon Monday…7 Sat Saturday
Produces…
Compound symbol evaluationA derived symbol name can be pretty much anything
• Does not have to look like a normal symbol• May contain non printable characters • Maximum length is 250 bytes on mainframe
Example:
A = “this is the symbol’s value”Say MyVar.AMyVar.A = 10Say MyVar.A + 1MYVAR.this is the symbol’s value11
Road Map• Generalities• Symbols and symbol evaluation
• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Rexx InstructionsThree types of Instruction:• Assignments
– symbol = expression– Symbol takes on the value of the expression
• Keyword– Begins with a keyword (if do call)– May contain multiple clauses, may contain nested instructions– 23 different keyword instructions
• Command– Single clause– Evaluated then passed to external environment as a command
Assignmentsymbol = expression
Symbol: • Already beat that to death…
Expression: • Always evaluate to a string• An expression contains term(s) interspersed with
zero or more operators
ExpressionExpression = Term(s) interspersed with Operator(s)
Term is one of:• String• Function call• Sub-expression (expression contained in parenthesis)
Operator is one of:• Concatenation• Arithmetic• Comparison• Logical
Term: StringThree types of string:
• Literal strings– Delimited using either single or double quote marks:
‘Single quote’ “double quote” ‘can contain “ marks’ or “can contain ‘ marks”‘it’’s escaped’
• Hexadecimal strings– Literal string containing hex characters terminated by an ‘X’
’01FF’X /* 10FF hex = 511 decimal */“A3B4”x /* A3B4 hex = 41908 decimal */’10 e3 b4 aa’x /* 10E3B4AA hex = 283358378 decimal */
• Binary strings– Literal string containing binary characters terminate by a ‘B’
‘111’b /* 111 binary = 7 decimal */“001 111’b /* 1111 binary = 15 decimal */
Concatenation operators• Forms a new string by evaluating its operands and joining them
together
• Three concatenation operators:– || (two vertical bars)
• Example: A || B where A and B can be symbols, functions or literals
– Space character• The space character can be an operator within the context of an expression.
In all other contexts it is a separator.• Example: A B
Equivalent to the expression: A || ‘ ‘ || B– Abuttal
• When two or more terms appear without an operator between them, they are concatenated without a separating space
• Examples: A’xxx’ and (A)(B)Are equivalent to the expressions: A || ‘xxx’ and A || B
Arithmetic operators• Strings that look like numbers may be used that way…
• Operators (all the usual suspects):
+ Add- Subtract* Multiply/ Divide% Integer divide (divide giving integer result)// Remainder (divide giving remainder)** Power (number raised to a whole number power)- As a prefix: -10 is equivalent to: 0 – 10+ As a prefix: +10 is equivalent to: 0 + 10
Comparison operators• Compare two terms yielding the string:
‘0’ (false)‘1’ (true)
• Normal Operators (all the usual suspects):= equal to\=, ¬=, <>, >< not equal to> greater than< less than>=, ¬<, \< greater than or equal to<=, ¬>, \> less than or equal to
Comparison operators• Strict Operators:
== strictly equal to\==, ¬== strictly not equal to>> strictly greater than<< strictly less than>>=, ¬<<, \<< strictly greater than or equal to<<=, ¬>>, \>> strictly less than or equal to
• Difference between Normal and Strict operators:‘0123’ = ‘123’ is true‘0123 == ‘123’ is false but ‘123’ == ‘123’ is true‘abc’ = ‘abc ’ is true‘abc’ == abc ’ is false but ‘abc’ == ‘abc’ is true
Logical operators• Logical operators are applied to the strings:
‘0’ meaning false‘1’ meaning true
• The result of a logical operator is a new string containing a zero or a one
• Logical operators (all the usual suspects):& And: Return ‘1’ if both terms are ‘1’, otherwise ’0’| Inclusive or: Return ‘1’ if either term is ‘1’, otherwise ’0’&& Exclusive or: Return ‘1’ if one term is ‘1’, otherwise ’0’¬, \ Logical not: Return ‘0’ if term is ‘1’ or ‘1’ if term is ‘0’
Assignment: symbol = expression
Some examples:A = ‘some text’A = BA = 3 + (B * 4)A = functionx(B) + 2A = B CA = A || ‘abc’A = A’abc’A = \((3 + B) = C * 2)
Keyword Instructions
Two broad categories:
• Flow of controlCALL, DO, EXIT, IF, ITERATE, LEAVE, RETURN, SELECT, SIGNAL
• ServicesADDRESS, ARG, DROP, INTERPRET, NOP, NUMERIC, OPTIONS, PARSE, PROCEDURE, PULL, PUSH, QUEUE, SAY, TRACE
DODO [repetitor] [conditional] ;
[instruction list]END [symbol] ;repetitor:
symbol = exp [TO exp] [BY exp] [FOR exp]expFOREVER
conditional:WHILE exp exp is evaluated before execution of intstruction listUNTIL exp exp is evaluated after execution of instruction list
exp:expression
DODO [repetitor] [conditional] ;
[instruction list]END [symbol] ;if exp then DO
Instructions…END
DO i = 1 TO 10 BY 2Instructions…
END iDO WHILE exp
Instructions…ENDDO FOREVER
Instructions…END
IFIF exp [;] THEN [;]
instruction[ELSE [;]
instruction]
IF exp THEN instruction
IF exp THEN doinstructions…
endIF exp THEN
instructionELSE
instruction
SELECTSELECT ;
WHEN exp [;] THEN [;] instruction…[OTHERWISE [;] [instructions] ]
END ;SELECT
WHEN exp THEN instructionWHEN exp THEN instruction
ENDSELECT
WHEN exp THEN instructionWHEN exp THEN
do instructions…end
OTHERWISEInstructions…
END
ITERATE and LEAVEITERATE [name] ; LEAVE [name] ;Used within the context of DO loop to either start the next iteration of that loop or exit the loop immediately
DO FOREVER…IF exp THEN ITERATE…IF exp THEN LEAVE
ENDDO I = 1 TO 100
DO J = 1 TO 10IF X.I.J = ‘DONE’ THEN LEAVE IIF X.I.J = ‘SKIP’ THEN ITERATE J Instructions…
ENDEND
DROPDROP symbollist ; symbollist:
one or more symbols. If symbol(s) are enclosed in parenthesis then that symbol is evaluated and the resulting symbol(s) are dropped.
x = ‘hello’say x /* hello */drop xsay x /* X */x. = ‘hello’ /* Stem and derived compound symbols: hello */x.2 = ‘bye’ /* compound symbol given a value */say x.1 x.2 /* hello bye */drop x.2 /* drop compound symbol */say x.1 x.2 /* hello hello */ drop x. /* drop stem and all derived compound symbols */say x.1 x.2 /* X.1 X.2 */droplist = ‘x.1 x.2’drop (droplist) /* drops symbols x.1 and x.2
NOPNOP; Does absolutely nothing
if x = ‘hello’ then nopelse x = ‘bye’
NUMERICNUMERIC DIGITS [exp] FORM …
FUZZ …Only going to talk about DIGITS…Digits sets the number of significant digits used in calculations. If you want to manipulate large numbers, posting balances for example, make sure to specify enough numeric digits to retain precision.
Balance = 123456789.00say Balance + 987654321.01NUMERIC DIGITS 15say Balance + 987654321.01
1.11111111E+91111111110.01
PARSEPARSE [UPPER] ARG [template] EXTERNAL [template]
PULL [template]SOURCE [template]VALUE [exp] WITH [template]VAR [symbol] [template]VERSION [template]
Only going to look at VAR version. Other variants work pretty much the same way.
Used to “deconstruct” strings into smaller parts.
Everyting in Rexx is a string – so this is a very important and often used instruction
PARSEPARSE [UPPER] VAR [symbol] [template]The UPPER option causes the symbol value to be converted to upper case before the template is applied (the symbol itself is unaltered).
The template provides a series of symbols and pattern matching directives used to break apart the input symbol value. Fragments of the input symbol value are assigned to template symbols as a result of this process
Template pattern matching directives can be “word”, content or offset oriented.
A “word” in Rexx is any string not containing a blank space. Words are therefore delimited by one or more space characters.
PARSE is a very powerful, but sometimes frustrating instruction
PARSEWord oriented:
The template is a list of symbols that are assigned values by taking successive blank delimited words from the subject symbol and assigning their values to successive template symbols.
The last template symbol is assigned whatever is “left over” after assigning values to prior symbols in the template
MyVar = “Neal Bredin, 7 Rue de L’Argile, Gatineau, Quebec ”PARSE Var MyVar First Second The_rest subject symbol template symbolsSay ‘First Name >’First‘<’Say ‘Second Name >’Second‘<’Say ‘The rest >’The_rest‘<’First Name >Neal<Second Name >Bredin,<The rest >7 Rue de L’Argile, Gatineau, Quebec <
PARSEContent oriented using literal string values:
A literal placed in a template is a request to match on the first occurrence of that value assigning unparsed content on its left to the template symbol to the left of the literal.
MyVar = “Neal Bredin, 7 Rue de L’Argile, Gatineau, Quebec ”PARSE Var MyVar First Second ‘,’ Street ‘,’ The_RestSay ‘First Name >’First‘<’Say ‘Second Name >’Second‘<’Say ‘Street >’Street’<‘Say ‘The rest >’The_rest‘<’ Literal delimiter strings
First Name >Neal<Second Name >Bredin<Street > 7 Rue de L’Argile<The rest > Gatineau, Quebec <
Note: Commas after “Second Name” and “Street” are gone but spaces are left before “Street” and “The Rest”
PARSEContent oriented using symbol values:
A symbol surrounded by parenthesis appearing in a template is a request to match using the evaluated content of that symbol.
MyVar = “Neal Bredin, 7 Rue de L’Argile, Gatineau, Quebec ”mc = ‘,’PARSE Var MyVar First Second (mc) Street (mc) The_RestSay ‘First Name >’First‘<’Say ‘Second Name >’Second‘<’Say ‘Street >’Street’<‘Say ‘The rest >’The_rest‘<’First Name >Neal<Second Name >Bredin<Street > 7 Rue de L’Argile<The rest > Gatineau, Quebec <
PARSEOffset oriented using absolute offsets:
An unsigned number placed in a template is a request to assign unparsed text to the left of the identified column number to the template symbol to the left of that number.
MyVar = “898950607AB00012011-01-012011-12-31”PARSE Var MyVar sid 10 pid 12 sqnbr 16 The_RestSay ‘Sys Id >’sid‘<’Say ‘Prog Id >’pid‘<’Say ‘Seq. Nbr >’sqnbr‘<’Say ‘The rest >’The_rest‘<’Sys Id >898950607<Prog Id >AB<Seq. Nbr >0001<The rest >2011-01-012011-12-31<
PARSEOffset oriented using relative offsets:
A signed number in a template is a request to assign text relative to the starting column number of the prior match. Essentially specifies the length of the text assigned to the symbol to its left. Assigning a negative number causes a “reparsing” of prior text.
MyVar = “898950607AB00012011-01-012011-12-31”PARSE Var MyVar sid +9 pid +2 sqnbr +4 The_RestSay ‘Sys Id >’sid‘<’Say ‘Prog Id >’pid‘<’Say ‘Seq. Nbr >’sqnbr‘<’Say ‘The rest >’The_rest‘<’Sys Id >898950607<Prog Id >AB<Seq. Nbr >0001<The rest >2011-01-012011-12-31<
PARSEOffset oriented using variable offsets:
A symbol or expression surrounded by parenthesis with a leading sign indicates a variable offset. An equal sign means absolute offset; plus sign means relative offset
MyVar = “898950607AB00012011-01-012011-12-31”abs = 10; rel = 2PARSE Var MyVar sid =(abs) pid +(rel) sqnbr +(rel + rel) The_RestSay ‘Sys Id >’sid‘<’Say ‘Prog Id >’pid‘<’Say ‘Seq. Nbr >’sqnbr‘<’Say ‘The rest >’The_rest‘<’Sys Id >898950607<Prog Id >AB<Seq. Nbr >0001<The rest >2011-01-012011-12-31<
PARSEAdditional Notes:
Get rid unwanted data from PARSE – use a dot as a “black hole” or place holder symbol.
MyVar = “898950607AB00012011-01-012011-12-31”PARSE Var MyVar sid 10 pid 12 sqnbr 16 .Say ‘Sys Id >’sid‘<’Say ‘Prog Id >’pid‘<’Say ‘Seq. Nbr >’sqnbr‘<’Sys Id >898950607<Prog Id >AB<Seq. Nbr >0001<
Everything assigned to the dot goes into a “black hole”
PARSEAdditional Notes:
Every symbol in a template is assigned a value, which may be null.
MyVar = “1 2 3”PARSE Var MyVar One . Three FourSay ‘One >’One‘<’Say ‘Three >’Three‘<’Say ‘Four >’Four‘<’One >1<Three >3<Four ><
The value of MyVar had been parsed before encountering template symbol Four.
PARSEAdditional Notes:
Failing to match on a content or offset oriented pattern value may result in “unexpected” results
MyVar = “Neal Bredin; 7 Rue de L’Argile, Gatineau, Quebec ”PARSE Var MyVar First Second ‘,’ Street ‘,’ The_RestSay ‘First Name >’First‘<’Say ‘Second Name >’Second‘<’Say ‘Street >’Street’<‘Say ‘The rest >’The_rest‘<’First Name >Neal<Second Name >Bredin; 7 Rue de L’Argile<Street > Gatineau<The rest > Quebec<
Semicolon never matched
CommandsPushing commands to an external environment for processing is the “glue” Rexx uses to build functionality
CommandsAnything Rexx does not recognize as an assignment or a keyword instruction is passed to its hosting environment as a command
DSN = ‘HLQ.SYSTEM.DATA(MBR001)' /* Assignment */'ALLOCATE DA('''DSN''') F(INFIL) SHR' /* Command */IF RC \= 0 THEN SAY “OUCH – THAT DIDN’T WORK”
Passes an ALLOCATE command to TSO causing the data set HLQ.SYSTEM.DATA(MBR001) to be allocated to DDName INFIL.
Success/failure of the command can be verified by evaluating the special Rexx variable RC, which is received from the hosting environment
CommandsThe ADDRESS instruction may be used to direct a command to a designated environment
ADDRESS 'LINKMVS' ICETOOL
Call the IBM ICETOOL utility (sort) from within a Rexx procedure.
Note: Prior commands or JCL DD statements must have been set up for this to work properly (e.g. TOOLIN DD)
Commands
var = OUTTRAP(stem | OFF [,[max][,[CONCAT | NOCONCAT]])var receives the name of the stem currently capturing output or OFF if not
capturing
stem stem symbol to receive captured output. The number of “lines” captured into the stem is stored as stem.0
OFF set capture off
max is the maximum number of lines to capture
CONCAT indicates whether to concatenate prior data to stemNOCONCAT
Some commands produce output that your Rexx program may need. The OUTTRAP function is used to capture command output.
CommandsOUTTRAP example:
DROP MBR. /* Stem symbol */X = OUTTRAP('MBR.') /* Trap output into Stem */"LISTDS '"IFILE"' MEMBERS" /* Issue TSO command */ X = OUTTRAP('OFF') /* Stop trappingIF RC \= 0 then return /* Check TSO return code */Names = 0 /* Member names not found, yet */DO I = 1 TO MBR.0 /* MBR.0 = trapped line count */ IF Names THEN SAY STRIP(MBR.I) IF MBR.I = '--MEMBERS--' THEN Names = 1 END I Capture output from the TSO LISTDS command into Rexx stem variable MBR.
Road Map• Generalities• Symbols and symbol evaluation
• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Standard set of built in functions
ABBREV, ABS, ADDRESS, ARG, BITAND, BITOR, BITXOR, B2X, CENTER, CHARIN, CHAROUT, CHARS, COMPARE, CONDITION, COPIES, C2D, C2X, DATATYPE, DATE, DELSTR, DELWORD, DIGITS, D2C, D2X, ERRORTEXT, FORM, FORMAT, FUZZ, INSERT, LASTPOS, LEFT, LENGTH, LINEIN, LINEOUT, LINES, MAX, MIN, OVERLAY, POS, QUEUED, RANDOM, REVESE, RIGHT, SIGN, SOURCELINE, SPACE, STREAM, STRIP, SUBSTR, SUBWORD, SYMBOL, TIME, TRACE, TRANSALTE, TRUNC, VALUE, VERIFY, WORD, WORDINDEX, WORDLENGTH, WORDPOS, WORDS, XRANGE, X2B, X2C, X2D
Common string functions• COPIES Return concatenated copies of a string• COMPARE Return position of first non matching character• INSERT Inserts one string inside another• LASTPOS Return position of last occurrence of a given string• LEFT Return leftmost characters from a given string• RIGHT Return rightmost characters from a given string• LENGTH Return length of a given string• POS Return position of first occurrence of a given string• STRIP Remove leading and/or trailing spaces from a string• SUBSTR Return a substring of a given string• VERIFY Verify that a string is composed of a given char set• WORD Return a blank delimited word from a string• WORDPOS Return word position of a given word in a string• WORDS Return number of blank delimited words in a string• WORDINDEX Return character position of nth word in a string
Other functions• ADDRESS Return name of current address space (eg. TSO)• ABS Return absolute value of a number• C2D Return decimal value of binary representation of a string• D2C Return binary string representation of a decimal value• DATATYPE Determine possible data types a string might represent• DATE Return current date• FORMAT Return a formatted numeric value• MAX Return maximum number from a given set of numbers• MIN Return minimum number from a given set of numbers• RANDOM Return a pseudo random number• SOURCELINE Return identified program source statement• TIME Return the current time
Road Map• Generalities• Symbols and symbol evaluation
• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Rexx Procedures• Like SECTIONs in COBOL
– Once invoked, control flows from statement to statement until a RETURN or EXIT is encountered
– Variable scope may span multiple procedures
• Like CALLed subroutines in COBOL– May receive parameters (linkage) using the ARG instruction– Variable scope may be limited to just the called routine
• Not like COBOL at all– Variables always (only) passed by value– May return a value (function)– Selectively choose scope of program variables
Rexx Procedures
Instructions related to procedures• call invoke a named procedure• arg retrieve (parse) parameters• return set a procedure result• exit terminate current program• label: define an “entry point”• procedure [expose] to define variable
scope
Rexx Procedures: Call instruction
call sub /* sub is a procedure name (label) */say a /* Will say “Hello” */exit /* exit program *//*******************************************************/sub: /* Label identifies procedure entry point */a = ‘Hello’ /* Modify value of global symbol */return /* return from call */
• Call is the Rexx instruction to invoke a procedure as a subroutine• The procedure is identified using a label name• Labels look like symbols, but end with a colon• Labels are evaluated as constants (Name folded to upper case but not
evaluated). Implication: no “dynamic” calls.• Labels need not be unique. Label search begins at top of source program
Rexx Procedures: Call with parameter
call sub ‘Hello’ /* ‘Hello’ is a parameter */say a /* Says: “HELLO there” Note case */Exit/******************************************************/sub:arg ba = b ‘there’ return
• arg is the Rexx instruction to retrieve parameters set on a call• arg by itself is a short form for: parse upper arg [template]• Parse arg works in a way similar to parse var • Parameters are evaluated before becoming available to the arg instruction
Implication: Stem symbols cannot be used as parameters
Rexx Procedures: Call with parameter
call sub ‘Hello’ /* ‘Hello’ is a parameter */say a /* Says: “Hello there” Note case */Exit/*****************************************************/sub:parse arg b /* Prevent case folding */a = b ‘there’ return
• Prevent case folding by using: parse arg [template]
Rexx Procedures: Call, multiple parameters
call sub ‘Hello’, ‘there! I am here’ /* 2 parameters */exit/*******************************************************/sub:parse arg a, b c /* 2 templates delimited by comma */ say a /* 1st word, 1st template: “Hello” */say b /* 1st word, 2nd template: “there!” */say c /* the rest, 2nd template: “I am here” */return• Comma used to delimit parameters• Each parameter is an expression • Each expression is evaluated before being made available to the arg
instruction• The arg instruction provides parsing templates for each parameter
Rexx Procedures: Call, multiple parameters
call sub ‘Hello’, ‘there! I am here’ /* 2 parameters */Comma serves two purposes in Rexx: • Expression delimiter (as shown above, separating two parameters)• Line continuation character
call sub ‘Hello’, /* 1st parameter */ ‘there! I am here’ /* continued… */Need two commas: One as an expression delimiter; one as a line continuation
call sub ‘Hello’, /* 1st parameter */ , ‘there! I am here’ /* 2nd parameter */
Rexx Procedures: Procedure keyword
a = ‘Hello’call sub asay a /* “Hello” */exit/*******************************************************/sub: procedureparse arg a /* “a” is a local symbol */say a /* “Hello” */a = ‘bye’ /* value of symbol “a” is changed */say a /* “bye” */return• The keyword procedure limits variable scope to just that procedure• Variables defined outside the procedure cannot be seen inside it • Variables defined within the procedure cannot be seen outside of it• Similar to variable scope in a CALLed COBOL program
Rexx Procedures: Procedure expose
a = ‘Hello’call sub ‘bye’say a /* “bye” */say b /* “B” because “b” was not exposed */exit/*******************************************************/sub: procedure expose aparse arg b /* “b” is a local symbol */say b /* “bye” */a = b /* value of symbol “a” is changed */return• Optional keyword expose makes named symbols visible• Changes to exposed symbols are seen outside the procedure• Variables defined within the procedure cannot be seen outside of it, unless
they too are exposed
Rexx Procedures: Procedure expose
WeekDay.1 = ‘Sunday’WeekDay.2 = ‘Monday’…Weekday.7 = ‘Saturday’call showday 2exit/******************************************************/Showday: procedure expose WeekDay.arg isay i WeekDay.i /* “2 Monday” */return
Stem symbols cannot be passed as parameters, but, they can be exposed making all symbols derived from the named stem visible
Rexx Procedures: Returning values
call sub 3, “Hello”say result /* “Hello Hello Hello” */exit/******************************************************/sub: procedureparse arg i, greetinganother = greetingdo i - 1 greeting = another greetingendreturn greetingSubroutines may return a result through the return instruction.
Rexx has two special symbols:• result contains the value of an expression given on the return
instruction from a subroutine call• rc contains a return code from last command to an external environment, or
the return code resulting from an internal Rexx signal or condition (e.g. syntax error)
Rexx Procedures: Functions
say sub(3, “Hello”) /* “Hello Hello Hello” */say result /* “RESULT” */exit/******************************************************/sub: procedureparse arg i, greetinganother = greetingdo i - 1 greeting = another greetingendreturn greeting
Subroutines may return a result through the return instruction, but, functions must return a value through the return instruction
The value of the return expression is the value of the function
The value of result is dropped on a function invocation
Rexx Procedures: Function vs Subroutine
say sub(3, “Hello”) /* Function: “Hello Hello Hello” */say result /* “RESULT” */call sub 3, “Hello” /* Subroutine call */say result /* “Hello Hello Hello” */exit/******************************************************/sub: procedureparse arg i, greetinganother = greetingdo i - 1 greeting = another greetingendreturn greeting
Functions are used as values in expressions – parenthesis around expression lists are required
Subroutines are called – parenthesis around expression lists are not used
Rexx Procedures: Function vs Subroutine
Any procedure that returns a value may be invoked as a function or as a subroutine
A subroutine call in Rexx is semantically equivalent to the function call:
result = name([exp] [,[exp]]…)Where:
name is a labelexp is an expression
Rexx Procedures: Exit vs return
Exit causes an immediate exit from a procedure
• Exit from a mainline procedure or an internal procedure causes an immediate program exit - control returns to the hosting environment (e.g. TSO)
• Exit from an external procedure causes an immediate return to the calling procedure – special symbol result is dropped
• Exit cannot be used in an external procedure invoked as a function (no return value)
Return causes a return to the invoking procedure
• May be used in a mainline, internal or external procedure
• May return a value to the invoking procedure (must do so when procedure is invoked as a function)
Rexx Procedures: Internal vs External
An invoked procedure may be either:• Internal - Contained in the same source as the invoking
procedure
• External - Contained in a different source file from the invoking procedure
Rexx searches for procedures by name starting from the top of the current program
If the named procedure is not found it then searches for an external procedure having that name
External procedures are found using the standard library search (e.g. SYSEXEC concatenation)
Rexx Procedures: Internal vs External
An external procedure search may be forced by enclosing the procedure name in quotes:call sub ‘first’ /* search internal then external */call “sub” ‘second’ /* external search only */returnsub: procedureparse arg xsay ‘Internal’ xreturn/* member called: sub */parse arg xsay ‘External’ xreturn
Internal firstExternal second
Rexx Procedures: Internal vs External
Internal and external procedures are alike except:
•External procedures implicitly assume the procedure instruction
– All symbols referenced in an external procedure have local scope
– External procedures may receive values passed to them as parameters through the usual parse arg [template] instruction
•An exit from an external procedure returns control to the invoking procedure
– Procedures called as functions cannot return using exit because they must return a value
Road Map• Generalities• Symbols and symbol evaluation
• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Queues• Queues are the “natural” data passing mechanism• Queues contain character strings• Queues are built LIFO, FIFO or mixed• Always read from head of queue• Principle queue related instructions:
– PULL (read from front of queue) – PUSH (stack oriented write – LIFO)– QUEUE (queue oriented write – FIFO)
• Principle queue related built in function– QUEUED() (number of queued strings)
QueuesQueues are the natural way to pass data between programs:
do i = 1 to 3 queue ‘count’ i /* evaluate and queue FIFO */endcall “mysub”exit
/* member called: mysub */do queued() /* returns number of queued lines */ parse pull x /* “read” from front of queue */ say xendreturn
QueuesQueues may be used to send commands to the host environment upon program termination*
do i = 1 to jobs.0 queue ‘submit’ jobs.i /* Batch jobs to submit */endqueue ‘%chkjobs’ /* Then run this exec… */exit
All of the jobs defined by the jobs. stem are submitted for execution under TSO and the chkjobs exec is then run
* Works under TSO but not under Windows
QueuesPulling from an empty queue causes the program to wait for input from the default input device (keyboard or SYSTSIN)
do forever say ‘Experssion:’ parse pull exp if exp = ‘’ then leave interpret ‘say exp "="’ expend
Expression: output from program(12 + 8) / 5 input pulled from keyboard(12 + 8) / 5 = 4 result of interpret instructionExpression:
QueuesUse parse external to obtain keyboard input under TSO when the data queue is not empty (or SYSTSIN background)
queue “some data” /* put data on queue */say “flip to upper case <y|n>:”parse upper external ans /* ignore data queue */if ans = ‘Y’ then parse upper pull dataelse parse pull datasay data
Flip to upper case <y|n>: output from programy input pulled from keyboardSOME DATA result of interpret instruction
Queues: Push vs Queue
Push: Last In First Out Queue: First In First Out Mixed
Push 1 Queue 1 Queue 1Push 2 Queue 2 Push 2Push 3 Queue 3 Queue 3do queued() do queued() do queued() pull x; say x pull x; say x pull x; say xend end end
3 1 22 2 11 3 3
Road Map• Generalities• Symbols and symbol evaluation
• Rexx instructions• Built in functions• Procedures• Queues• Rexx under TSO
Rexx under TSOSource Code•PDS or Sequential dataset (PDS is preferred)•Record length not restricted (80 bytes is traditional)
Allocate source dataset to SYSEXEC•Datasets allocated to SYSEXEC are assumed to contain Rexx execs
Allocate source dataset to SYSPROC•Datasets allocated to SYSPROC may contain CLIST or Rexx execs•Rexx execs allocated to SYSPROC must begin with a comment where the first word of the comment is “Rexx” (e.g. /* REXX */)
Can run Rexx exec from an unallocated dataset using TSO EXEC command
READYEXEC ‘USERID.MY.PDS(MYPROG)’
Rexx under TSO: File Input and Output
File based I/O is not part of the Rexx language. Implementation dependent routines must be called for I/O operations
TSO/E provides the EXECIO command interface for this purpose:
>>__EXECIO__ _lines_ ________________________________________________> |_*_____| >__ _DISKW__ddname__ _________________ ____________________ ________>< | |_| Write Parms |_| | |__ _DISKR__ _ddname_ _________ __ __________________ __| |_DISKRU_| |_linenum_| |__| Read Parms |__| Write Parms: |__ __________________________________________________ ______________| |_(__ _______________ __ ______ __ _______ __ ___ _| |_STEM var-name_| |_OPEN_| |_FINIS_| |_)_| Read Parms: |__ ____________________________________________________________ ____| |_(_ _______________ __ ______ __ _______ __ ______ __ ___ __| |_FIFO__________| |_OPEN_| |_FINIS_| |_SKIP_| |_)_| |_LIFO__________| |_STEM var-name_|
Rexx under TSO: EXECIO
lines Number of records, asterix (*) means all records
DISKW Open file specified by ddname for writingDISKR Open file specified by ddname for readingDISKU Open file specified by ddname for update
ddname DD Name allocating subject dataset
linenum Starting record number in associated file
Rexx under TSO: EXECIO
STEM Take data to be written from a stem symbolvar-name Stem symbol containing data to be written
OPEN Open the dataset before writing
FINIS Close the dataset when finished writing
Note: Opening parenthesis is required, closing one is optional
Rexx under TSO: EXECIO
FIFO Place records on data queue First In First Out (stack)LIFO Place records on data queue Last In First Out (queue)
STEM Place records in named stem symbolvar-name Stem symbol to receive data read
OPEN Open the dataset before reading
FINIS Close the dataset when finished reading
SKIP Read, but ignore, specified number of records
Rexx under TSO: EXECIO
"ALLOCATE DA('HLQ.SYSTEM.DATA') F(IFIL) SHR" /* TSO allocate command */"EXECIO * DISKR IFIL(FIFO OPEN FINI" /* EXECIO TSO service */"FREE DDNAME(IFIL)" /* TSO free command */do queued() pull X; say strip(X)endexit
Typical read and display program:•Pushes command to TSO to allocate a dataset•Opens dataset, reads it into data queue, then closes it•Frees the allocated dataset•Processes data off of queue
Works well for small datasets, 5 to 10K records
Rexx under TSO: EXECIO
'ALLOCATE DA(''HLQ.SYSTEM.DATA'') F(IFIL) OLD'block = 5000 /* Process file in blocks of records */do forever 'EXECIO' block 'DISKR IFIL(FIFO' /* Read “block” records into queue */ if queued() = 0 then leave /* If none read, we are finished... */ call process /* Process data on queue... */end'EXECIO 0 DISKR IFIL(FINIS' /* Close file */'FREE DDNAME(IFIL)' /* free dataset */return/*******************************************************************/process: procedure...Return
Strategy for reading larger datasets is to process them in blocks
1.Use an “infinite” read loop to fetch a block of records into the queue or a stem symbol2.Leave the read loop if no records were placed on the queue (reached end of file)3.Call processing procedure to process the block4.Repeat…
Rexx under TSO: EXECIO
"ALLOCATE DA('HLQ.SYSTEM.DATA') F(IFIL) SHR" /* TSO allocate command */"EXECIO * DISKR IFIL(FIFO OPEN FINI" /* EXECIO TSO service */"FREE DDNAME(IFIL)" /* TSO free command */do queued() /* Fix count… */ parse pull x /* Pull from front… */ x = process(x) /* Process the record */ queue x /* Queue to the back… */end"ALLOCATE DA('HLQ.SYSTEM.LIST') F(OFIL) OLD" /* TSO allocate command */"EXECIO * DISKW OFIL(OPEN FINIS" /* EXECIO TSO service */"FREE DDNAME(OFIL)" /* TSO free command */
Typical read/write program•Read data into queue•Determine queue size: queued()•Process that many records•Queue data to be written (placed at back of queue)•Write queued data (all new data)
Rexx under TSO: EXECIO
Examples so far have used the data queue. Using stem symbols is very similar, just add the STEM parameter with a named stem symbol.
Advantage of stem symbols are that you may define as many as needed, such as when multiple data sources are processed in parallel
Disadvantage is that stem symbols are not visible to external sub programs or internal sub programs with the procedure instruction
"ALLOCATE DA('HLQ.SYSTEM.DATA') F(IFIL) SHR" /* TSO allocate command */"EXECIO * DISKR IFIL(STEM X. OPEN FINI" /* EXECIO TSO service */"FREE DDNAME(IFIL)" /* TSO free command */do I = 1 to X.0 /* Stem.0 contains record count */ say strip(X.i)endexit
Rexx under TSO: BATCH
Easiest way to run Rexx as a batch job is to run it under a batch TSO session:
//REXX JOB ... Job card//STEP01 EXEC PGM=IKJEFT01 Create TSO address space//SYSEXEC DD DSN=MYHLQ.REXX,DISP=SHR Rexx exec PDS//SYSTSPRT DD SYSOUT=A “terminal” output//SYSTSIN DD * TSO commands%MYREXX Rexx exec/*//MYINPUT DD DSN=HLQ.SYSTEM.DATA,DISP=SHR Allocate data sets…//
Rexx procedures invoked this way may reference any DDNames from the job step. In the above example MYINPUT may be referenced in an EXECIO command. Alternatively the Rexx procedure could push “ALLOCATE” commands, as illustrated on prior slides, to gain access to datasets
Rexx under TSO: References
z/OS V1R7.0 TSO/E REXX Reference:
http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/IKJ4A360/CCONTENTS
z/OS V1R2.0 TSO/E REXX User's Guide:
http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/IKJ4C310/CCONTENTS