of 56 /56
Advanced Rexx Advanced Rexx Topics Topics Phil Smith III Voltage Security, Inc. SHARE 111 SHARE 111 August 2008 Session 8331

Advanced Rexx Topics

Embed Size (px)

Text of Advanced Rexx Topics

Page 1: Advanced Rexx Topics

Advanced Rexx Advanced Rexx TopicsTopicsPhil Smith IIIVoltage Security, Inc.SHARE 111SHARE 111August 2008Session 8331

Page 2: Advanced Rexx Topics

Copyright InformationCopyright Information

SHARE Inc is hereby granted a non exclusiveSHARE Inc. is hereby granted a non-exclusive license to copy, reproduce or republish this presentation in whole or in part for SHARE p pactivities only, and the further right to permit others to copy, reproduce, or republish this presentation in whole or in part so long as such permission iswhole or in part, so long as such permission is consistent with SHARE's By-laws, Canons of Conduct, and other directives of the SHARE Board of Directors

Page 3: Advanced Rexx Topics


Why Rexx?Why Rexx?

“Power” uses for Rexx

H iHygiene

Robust Rexx

Non-IBM Rexx Implementations

Coding for portability


Page 4: Advanced Rexx Topics

Why Rexx?Why Rexx?

Extremely powerfulExtremely powerful Everyone with VM, TSO has Rexx

Available for diverse environments

Lots of products support Rexx macrosEasy to learn—similar to PL/I

Very “forgiving”, easy to debug

Compiler improves performance, control Few fully exploit Rexx capabilities!Few fully exploit Rexx capabilities!

Page 5: Advanced Rexx Topics

Power Uses for RexxPower Uses for Rexx

System debugging (with privileges)System debugging (with privileges)System monitor

Summarize performance data p

Front-end to end-user commands Simplify (or alter!) parsingS t d f lt i tSet up default environment

Application prototypingRobust, sophisticated applications!Robust, sophisticated applications!

Full applicationsEntire vendor products are written in Rexx

Page 6: Advanced Rexx Topics

Rexx Power ToolsRexx Power Tools

Logical variables Special function usesLogical variables PARSE Stemmed variables and arrays

Special function uses Obscure functions Word manipulation functions

Nested function calls Interactive tracing SIGNAL ON

INTERPRET and ADDRESS The stack DROPping variables

Internal vs. external functions p g

Page 7: Advanced Rexx Topics

Logical VariablesLogical Variables

Logical variables have values of 1 or 0Logical variables have values of 1 or 0 Are tested implicitly:

if logical variable then ...g _

Faster to execute, easier to read than: if non_logical_variable = 'YES' then …

All i l t l i l lAll comparisons resolve to logical values

Page 8: Advanced Rexx Topics

Logical VariablesLogical Variables

Exploit for efficiency readability:Exploit for efficiency, readability:Return 1 if rc is 3, else return 0:return (rc = 3)

Return 0 if rc is 0 or rc is 3:return (rc <> 3) * rc

Assign to variables:Assign to variables:var = (a = 3)

Not: if 3 th 1if a = 3 then var = 1else var = 0

Page 9: Advanced Rexx Topics

Logical VariablesLogical Variables

Can use logical values in arithmeticCan use logical values in arithmetic Example: determine length of year in daysdays = 365 + (substr(date('O'), 1, 2)//4 = 0)

Versus: if substr(date('O'), 1, 2)//4 = 0 then days = 366else days = 365

Page 10: Advanced Rexx Topics


One of Rexx’s most powerful featuresOne of Rexx s most powerful featuresCan parse variables, stacked data, function responses…Can parse on blank-delimited tokens, specific strings, variable strings, absolute column positions, relative column positions

PARSE usually faster than multiple SUBSTR y pPossible exceptions include huge strings

Page 11: Advanced Rexx Topics

PARSE ExamplesPARSE Examples

Parse date into month day and year:Parse date into month, day and year: parse var date mm '/' dd '/' yy

or:or: parse var date mm 3 . 4 dd 6 . 7 yy

not:mm = substr(date, 1, 2)dd = substr(date, 4, 2)yy = substr(date 7 2)yy = substr(date, 7, 2)

Page 12: Advanced Rexx Topics

PARSE ExamplesPARSE Examples

PARSE VALUE avoids intermediate variables:PARSE VALUE avoids intermediate variables: parse value diag(8, 'QUERY FILES') with ,

. rdrfiles . ',' .

not: files = diag(8, 'QUERY FILES')parse var files . rdrfiles ',' .p

Of course, if FILES will be used later, intermediate variable better than multiple function calls

Page 13: Advanced Rexx Topics

Stemmed Variables and ArraysStemmed Variables and Arrays

Rexx vectors/arrays have stem and tail:Rexx vectors/arrays have stem and tail: stem.tail = 27STEM. is the stem, including the dot; TAIL is the tail, g ;

May have non-numeric tails Allows “associative memory”, relating variable structures by suffix valuesuffix value Saves searching arrays: refer to compound name, Rexx finds it

Page 14: Advanced Rexx Topics

Stemmed Variables and ArraysStemmed Variables and Arrays

Easy to build and process list of values:Easy to build and process list of values: Build list of tails in variable (if simple keys)Otherwise build numeric-tailed key listBuild arrays with tails as suffixes Break down list of tails, process each value

Can set default array variable values:Can set default array variable values:things. = 0 /* Set all counts to 0 */…things user = things user + 1 /* Next */things.user = things.user + 1 /* Next */

Page 15: Advanced Rexx Topics

Compound Variable ExamplesCompound Variable Examples

Enables simple variable management:Enables simple variable management:parse var line user count commentsthings.user = things.user + count if find(users user) = 0 thenif find(users, user) = 0 then users = users user /* New user */

Scan array by parsing tail list:/* C li t f ID */users = users /* Copy list of IDs */

do while users <> '' /* Run the list */parse var users user users /* Next */say user 'has' things user 'things'say user has things.user things


Page 16: Advanced Rexx Topics

Nested Function CallsNested Function Calls

Nest function calls when appropriate:Nest function calls when appropriate: last = right(strip(substr(curline.3,1,72)) 1)

to get last non-blank byte of a line, not:g y ,line = substr(curline.3, 1, 72)line = strip(line)last = right(line, 1)g

Avoids useless intermediate variables

Within limits, nesting cheaper, easierO i ll t t d bl i t i blOccasionally two steps more readable, maintainable—use judgment

Page 17: Advanced Rexx Topics

Internal vs. External FunctionsInternal vs. External Functions

Rexx supports internal and external user functionsRexx supports internal and external user functions Internal functions are subroutines in programExternal functions are separate programs, called exactly like built-in functions

External commands can examine/set Rexx variablesSearch SHVBLOCK in Rexx Reference for detailsSearch SHVBLOCK in Rexx Reference for details

Page 18: Advanced Rexx Topics

Internal vs. External FunctionsInternal vs. External Functions


PROCEDURE instruction in internal functions provides isolation of variables

PROCEDURE EXPOSE varlist allows limited variable sharing in internal functionssharing in internal functions Can EXPOSE compound variable stem Use compound variables to avoid long EXPOSE lists

Page 19: Advanced Rexx Topics

Internal vs. External FunctionsInternal vs. External Functions

External functions can simplify maintenance ofExternal functions can simplify maintenance of mainlineExternal functions must use GLOBALV command ( i l t) t h i bl(or equivalent) to share variables Freeware GLOBALV implementations for TSO:

www.wjensen.com (Willy Jensen’s page)( y p g )www.btinternet.com/~ashleys/(Ashley Street, FADH)www.searchengineconcepts.co.uk/mximvs/rexx-functions.shtml

(Rob Scott’s STEMPUSH and STEMPULL)Tradeoff of function and performance vs.

d bili / i i bili / lireadability/maintainability/commonality

Page 20: Advanced Rexx Topics


TRANSLATE does what it sounds likeTRANSLATE does what it sounds likeWith no translation tables, TRANSLATE uppercases string:gmvariable = 'woof'uvariable = translate(mvariable)/* Now UVARIABLE = 'WOOF‘ */

UPPER theologically incorrectNot in Rexx language specificationW ’t b t t i i l t tiWon’t go away, but not in some implementations

Page 21: Advanced Rexx Topics


Also use TRANSLATE to rearrange stringsAlso use TRANSLATE to rearrange strings Input string, translate table specify old, new order: d = '01/31/90'd = translate('78612345', d, '12345678')/* Now D = '90/01/31' */

Much faster, easier than multiple SUBSTR callsMay be harder to read, though!

Page 22: Advanced Rexx Topics

Translate: How Does This Work??Translate: How Does This Work??

date = translate('78612345' date '12345678')date = '01/31/99'

date = translate('78612345' '01/31/99'date = translate('78612345' '01/31/99'date = translate('78612345' '001/31/99'date = translate('786002345' '001/31/99'date = translate('786002345' '001/31/99'date = translate('786002345' '0011/31/99'date = translate('7860011345' '0011/31/99'date = translate('7860011345' '0011/31/99'date = translate('7860011345' '0011//31/99'date = translate('7860011//45' '0011//31/99'date = translate('7860011//45' '0011//31/99'date = translate('7860011//3131' '0011//3131/99'date = translate('99/99/0011//3131' '0011//3131/99/99'date = translate( 78612345 , date, 12345678 )date = translate( 78612345 , 01/31/99 , '12345678')

date = translate( 78612345 , 01/31/99 , '112345678')

date = translate( 78612345 , 001/31/99 , '112345678')

date = translate( 786002345 , 001/31/99 , '112345678')

date = translate( 786002345 , 001/31/99 , '1122345678')

date = translate( 786002345 , 0011/31/99 , '1122345678')

date = translate( 7860011345 , 0011/31/99 , '1122345678')

date = translate( 7860011345 , 0011/31/99 , '11223345678')

date = translate( 7860011345 , 0011//31/99 , '11223345678')

date = translate( 7860011//45 , 0011//31/99 , '11223345678')

date = translate( 7860011//45 , 0011//31/99 , '1122334545678')

date = translate( 7860011//3131 , 0011//3131/99 , '1122334545678')

date = translate( 99/99/0011//3131 , 0011//3131/99/99 , '1122334545678678')

Key points:y pStrings must be unique (or expect confusion!)Evaluation is atomic, so:translate('12', '2x', '12')

Evaluates to “2x”, not “xx”

Page 23: Advanced Rexx Topics

Function: SPACEFunction: SPACE

SPACE can remove blanks from a stringSPACE can remove blanks from a string For example, squeeze user input:line = 'This is a line'line = space(line 0) /* Lose any blanks */line = space(line, 0) /* Lose any blanks *//* Now LINE = 'Thisisaline' */

Or (with TRANSLATE), remove “/” from date:date = date('U') /* Assume today is 01/31/90 */date = date( U ) / Assume today is 01/31/90 /date = space(translate(date, ' ', '/'), 0)/* Now DATE = '013190' */

Remove commas from number:Remove commas from number:n = '199,467,221'n = space(translate(n, ' ', ','), 0) /* Now NUMBER = '199467221' */

Page 24: Advanced Rexx Topics

Obscure FunctionsObscure Functions

Rexx has many, many built-in functions Often multiple ways to perform a given task


p y p g• Know the functions, avoid reinventing the wheel

Test if token is keyword abbreviation

COMPARE:Determine where two strings differ

Insert a string into another

LASTPOS:Determine last occurrence of string Determine where two strings differ

COPIES: Copy string specified # of times


RANDOM: Generate pseudo-random number

py g p

DELSTR: Delete part of a string

REVERSE: Reverse string

XRANGE:XRANGE: Generate hex value range

Page 25: Advanced Rexx Topics

Word Manipulation FunctionsWord Manipulation Functions

CMS TSO commands are blank delimited wordsCMS, TSO commands are blank-delimited words Many Rexx functions manipulate blank-delimited words:

SUBWORD, DELWORD, WORDINDEX, WORDLENGTH, WORDS, WORD, WORDPOSUseful in building and processing commandsUseful in building and processing commands

Page 26: Advanced Rexx Topics

The INTERPRET InstructionThe INTERPRET Instruction

Evaluates variables then executes resultEvaluates variables, then executes result Adds extra level of interpretation

Enables variables as compound variable stems p(although VALUE does, too)Eschewed by Rexx aficionados except where b l t l i dabsolutely required

Page 27: Advanced Rexx Topics

The INTERPRET InstructionThe INTERPRET Instruction

Enables powerful test program:Enables powerful test program: /* Rexx EXEC to execute from the terminal */

signal DO_FOREVER /* Skip error handler */SYNTAX: /* Here if syntax error *// y /

say 'SYNTAX ERROR' rc': ' errortext(rc)DO_FOREVER: /* Main loop */

signal on SYNTAX /* Catch syntax errors */d f /* L til EXIT */do forever /* Loop until EXIT */

parse external cmd /* Read a line */interpret cmd /* Execute the line */


Invoke program, enter lines to be executed Type EXIT to terminate

Page 28: Advanced Rexx Topics

The ADDRESS InstructionThe ADDRESS Instruction

Controls execution environment for non-Rexx commands

Can pass single command to another environment:address tso...some code...address ispexec 'some command'...some more code... /* ADDRESS TSO in effect */

ADDRESS operand not normally interpreted:ADDRESS operand not normally interpreted:address tso

Same result whether variable TSO set or notQuotes add apparent significance have no valueQuotes add apparent significance, have no value

You can force an operand interpretation:address value tso /* Use value of variable TSO */dd ( ) /* l f i bl SO */address (tso) /* Use value of variable TSO */

Page 29: Advanced Rexx Topics

The ADDRESS InstructionThe ADDRESS Instruction

With no operands returns to previous environment:With no operands, returns to previous environment:address tso...some code...address /* Back to environment before TSO */address /* Back to environment before TSO */

But usually you know the previous environmentBetter to be explicit—more readable/maintainable

Null operand meaningful in some environments:address '' /* Same as ADDRESS COMMAND in CMS */

As with omitted operand confusing for readers—avoidAs with omitted operand, confusing for readers avoid

Page 30: Advanced Rexx Topics

The StackThe Stack

Rexx supports a data stackRexx supports a data stackLines of data that can be “pulled” and “pushed”Concept came from VM/CMS

Many Rexx programs manipulate stackPrograms should tolerate pre-stacked lines

N t j t t l t b t t i d t tlNot just tolerate, but not consume inadvertentlyFailure to do so causes breakage in nested calls

“Leave the toys [lines] where you found them”y [ ] y

Page 31: Advanced Rexx Topics

The StackThe Stack

Commands exist to aid in stack managementCommands exist to aid in stack managementNEWSTACK/DELSTACK/QSTACK control stack isolation

Each stack is completely separate from others

MAKEBUF/DROPBUF/QBUF/QELEM manage t t kcurrent stack

MAKEBUF creates “stack level”DROPBUF deletes lines stacked in a stack levelQBUF returns number of stacksQELEM returns number of lines in current stack

Manage stack effectively and carefullyManage stack effectively and carefully

Page 32: Advanced Rexx Topics

DROPping VariablesDROPping Variables

DROP destroys variablesDROP destroys variables One or more variables can be DROPped per statement DROP stem destroys array

SYMBOL function returns LIT after variable DROPped R l t f d i blReleases storage for compound variables

Useful for reinitializing in iterative routines Can conserve storage in complex applications

Page 33: Advanced Rexx Topics

Performance: Quoting CallsPerformance: Quoting Calls

Built in functions can be quoted:Built-in functions can be quoted:line = 'SUBSTR'(line, 1, 8)

Avoids search for local function with same name

Appears to offer improved performance Untrue: function search parses entire program, builds function lookaside entryfunction lookaside entry Quoted calls do not generate lookaside Repeated quoted calls require extra resources A id if l d littl iAvoid even if only used once—little or no savings

Page 34: Advanced Rexx Topics

Performance: SemicolonsPerformance: Semicolons

C PL/I programmers find Rexx “;” statement delimiterC, PL/I programmers find Rexx ; statement delimiter familiar

Many programmers end all statements with “;” Bad idea: generates null Rexx statement internally, requires additional processing

Page 35: Advanced Rexx Topics


Use PROCEDURE to isolate subroutinesUse PROCEDURE to isolate subroutinesAlways specify literal strings in quotes:

Know which commands are part of Rexx, specify non-Rexx p , p ycommands in quotes Specify quoted strings in capitals unless mixed-case desired Specify interpreted function operands in quotes: date('U')Specify interpreted function operands in quotes: date( U ) not date(u)Consider SIGNAL ON NOVALUE to enforce

Good Re h giene pa s off in impro ed reliabilitGood Rexx hygiene pays off in improved reliability, readability, maintainability

Page 36: Advanced Rexx Topics

Debugging: Interactive TracingDebugging: Interactive Tracing

Stop after each statement (? operand)Stop after each statement (? operand) Examine variables, change values Re-execute line with new values (= operand)Re execute line with new values ( operand) Suppress command execution (! operand) Suppress tracing for n statements pp gTrace without stopping for n statements

Page 37: Advanced Rexx Topics

Debugging: Interactive TracingDebugging: Interactive Tracing

Enabled by TRACE instruction in programEnabled by TRACE instruction in programSubroutine tracing can be reset without affecting mainline

In large programs, consider conditional tracing: g p g , gif (somecondition) then trace ?r

Page 38: Advanced Rexx Topics

Debugging: SIGNAL ONDebugging: SIGNAL ON

SIGNAL ON similar to PL/I ON conditionSIGNAL ON similar to PL/I ON condition Transfers control when condition raised

Five conditions:1. ERROR: Trap non-zero RC 2. FAILURE: Trap negative RC 3 SYNTAX: Trap Rexx syntax errors3. SYNTAX: Trap Rexx syntax errors 4. HALT: Trap HI Immediate command (CMS, TSO)5. NOVALUE: Trap uninitialized variable reference

Can specify label, or use default (condition name):signal on syntaxsignal on syntax name SomeLabel

Page 39: Advanced Rexx Topics

Debugging: SIGNAL ONDebugging: SIGNAL ON

SIGNAL allows graceful recovery from errorsSIGNAL allows graceful recovery from errors Special variable SIGL contains line number where execution interrupted Use SOURCELINE(SIGL) to extract source of error

For syntax errors, RC contains error code Use ERRORTEXT(RC) to extract syntax error textUse ERRORTEXT(RC) to extract syntax error text

CONDITION function adds details about conditionVariable name for NOVALUE conditions, for example

Page 40: Advanced Rexx Topics


Use SIGNAL ON HALT whenever there’s cleanup toUse SIGNAL ON HALT whenever there s cleanup to be done:

Halt:call Halted /* Go close files, etc. */say 'We got halted!' /* Notify */call Quit 999 /* Go do normal cleanup */call Quit 999 / Go do normal cleanup /

Page 41: Advanced Rexx Topics


In any “serious” program prepare for theIn any “serious” program, prepare for the “impossible”:

S t /* S t t ll l */Syntax: /* Syntax error: tell people */signal off syntax /* Don't want to recurse */badline = sigl /* Remember where it happened */emsgtxt = errortext(rc) /* And why */sourcel = GetSourceLine(badline) /* Get source */

/* Go allow debugging, say what happened */call DebugLoop 'SYNTAX ERROR' rc 'in' g Efn':'call DebugLoop SYNTAX ERROR rc in g._Efn : , ,

emsgtxt, 'Error occurred in line' badline':', ,sourcel

call Quit 20040 /* And exit */

Use variable names not used in rest of program…

Page 42: Advanced Rexx Topics


Get error details display on consoleGet error details, display on console

NoValue: /* Undefined variable referenced */signal off novalue /* Don't want to recurse */signal off novalue /* Don't want to recurse */badline = sigl /* Remember where it happened */var = condition('D') /* And why */sourcel = GetSourceLine(badline)call DebugLoop 'NOVALUE of "'var'" raised in', ,

g._Execname, ,'Error occurred in line' badline':', sourcel

call Quit 20040 /* And exit */call Quit 20040 / And exit /

Page 43: Advanced Rexx Topics

GetSourceLine FunctionGetSourceLine Function

Get entire source line even if continuedGet entire source line, even if continuedGetSourceLine: Procedure /* Note no EXPOSE list! */

arg lif sourceline(l) = '' then return '(compiled, no source available)'line = ''do forever

temp = sourceline(l)line = line tempif right(strip(temp), 2) = '*/' thenif pos('615c'x, temp) > 0 then parse var temp temp '615c'xif right(strip(temp), 1) <> ',' then return line

l = l + 1end

Page 44: Advanced Rexx Topics

DebugLoop: Interactive DebuggingDebugLoop: Interactive Debugging

Example of common subroutine for interactiveExample of common subroutine for interactive debugging:

DebugLoop:do DebugI = 1 to arg()

say arg(DebugI) /* Display the message(s) */endend

/* Go into interactive trace */trace ?rd fdo forever

nopendcall Quit 20040 /* And exit nicely */Q y

Page 45: Advanced Rexx Topics

Alternative: Rexx “Dump” & TracebackAlternative: Rexx “Dump” & Traceback

For end users interactive debugging is just confusingFor end-users, interactive debugging is just confusingA “dump” is much more useful

Easy if Pipelines available (z/VM example):y p ( p )'PIPE rexxvars | > DUMP FILE A'say 'Dump is in DUMP FILE A'

More difficult if no PipelinesMore difficult if no PipelinesCould write program to traverse Rexx variable treeFetch SHVBLOCKs (referenced earlier)

F t b k tForce traceback, toosay 'Forcing traceback:'signal off syntax /* Should be off already */signal value '' /* Force traceback */signal value '' /* Force traceback */

Page 46: Advanced Rexx Topics

First Failure Data Capture in RexxFirst Failure Data Capture in Rexx

FFDC: IBM term for “Get enough data the first time”FFDC: IBM term for Get enough data the first time“Reboot and see if it happens again” is not FFDC

Rexx facilities enable FFDCSIGNAL ON CONDITION()SOURCELINE()SOURCELINE()Interactive debugging

With these “smarts”, you can (sometimes) fix a problem and continue running

Especially valuable in servers or programs with significant startup costp

Page 47: Advanced Rexx Topics


Error trapped by SIGNAL ON SYNTAX:Error trapped by SIGNAL ON SYNTAX:badEntering interactive debug modeSYNTAX ERROR 40 i BAD EXEC A2SYNTAX ERROR 40 in BAD EXEC A2Incorrect call to routineError occurred in line 2315:yesterday = space(translate(date('O' date('B'yesterday = space(translate(date( O , date( B , ,

yy'/'mm'/'dd, 'O') - 1, 'B'), ' ', '/'), 0)+++ Interactive trace. TRACE OFF to end debug,

ENTER to continue. +++ENTER to continue.

Page 48: Advanced Rexx Topics


Now let’s figure out what broke:Now let s figure out what broke:say yy07say mmsay mm12say dd91

Ah, we have a bad date (…or maybe it was December 7, 1991, or July 12, 1991, and we parsed it wrong?)it wrong?)

Enough information to at least start real debugging!Obviously much more interesting examples will occurFailing program might send email about the error as well or instead

Page 49: Advanced Rexx Topics


whateverwhateverWHATEVER running at 2:46 on Tuesday, July 31, 2007NOVALUE of "N" raised in WHATEVER EXEC A1Error occurred in line 39:g._ConsoleToFor = substr(g._ConsoleToFor, 1, n)+++ Interactive trace. TRACE OFF to end debug, ENTER to

continue. +++say g consoletoforsay g._consoletofor TO PHSDEV RDR DIST PHSDEV FLASHC 000 DEST OFFsay nN

We now know which variable was not set!

Page 50: Advanced Rexx Topics

Other Rexx ImplementationsOther Rexx Implementations

Personal Rexx Quercus (was Mansfield)Personal Rexx — Quercus (was Mansfield) Rexx for PC-DOS/MS-DOS, OS/2 www.quercus-sys.com

R i O SRegina — Open SourceFreeware Rexx for *ix, Windows, etc.regina-rexx.sourceforge.net

UniRexx — The Workstation Group Rexx for VMS, UniXEDIT also available www.wrkgrp.comwww.wrkgrp.com

Object RexxIBM product; recently Open Sourcedwww oorexx orgwww.oorexx.org

Page 51: Advanced Rexx Topics


Rexx is well definedRexx is well-definedLeads to consistency across implementationsSlight implementation differences make testing important

Issues when writing portable programs:System commandsFilenamesFilenamesUtilities such as EXECIO, CMS Pipelines

Use stream I/O functions instead for portabilitySometimes less convenientSometimes slower

Page 52: Advanced Rexx Topics


Use PARSE SOURCE to determine platform:Use PARSE SOURCE to determine platform:parse upper source g._Host . g._Efn g._Eft.../* Set the output fileid *// Set the output fileid /

selectwhen g._Host = 'CMS' then file = 'MY FILE A'when g._Host = 'WIN32' then file =

'C:\TEMP\MY.TXT'C:\TEMP\MY.TXTwhen g._Host = 'UNIX' then file = '/tmp/my.txt/'otherwise say 'Unsupported platform "'g._Host'"'exit 24

endend...if lineout(file) then … /* Write, handle errors */

Page 53: Advanced Rexx Topics


When performance critical multipathing may beWhen performance critical, multipathing may be worthwhile:/* Process the xxx,xxx input variables */select

when g._Host = 'CMS' then'PIPE …' /* Do it in a Pipe */when g._Host = 'WIN32' then call TheHardWay /* Call pure Rexx subroutine */when g._Host = 'UNIX' then'awk …' /* Do it in awk */

Page 54: Advanced Rexx Topics

Portability ExamplePortability Example

Tournament scheduler written in RexxTournament scheduler written in RexxOT: www.firstlegoleague.org — Check it out!

Input parameters in flat file:p psomename FLL A on CMSsomename.fll in current directory (or FQN) on Windows, LinuxLinux

1448 lines of RexxFive tests for host type, all related to file managementOne of the five is just make a message environment-specific

About as portable as anything! (Java, eat my…)Doesn’t handle blanks in directories; could if neededDoesn t handle blanks in directories; could if needed

Page 55: Advanced Rexx Topics


Rexx is powerful rich in functionRexx is powerful, rich in function Offers more function than most people use

Inexperienced users can add skills easily p yLearning more about it increases productivity

Once you feel proficient, read reference manual N t f ili f ilitiNote unfamiliar facilities Try them, discover their power Experimenting is fun and easy!

What Rexx tips can you share?

Page 56: Advanced Rexx Topics


Phil Smith III

(703) 476-4511

[email protected]