Here are several advanced Rexx programming examples.
/* chgall.rex
replace all occurrences of one string, by another
this EXAMPLE PROGRAM that uses the 'CHANGESTR' function.
see the related 'changestr.rex' program.
usage:
exec chgall "/before/after" < infile > outfile
or:
exec chgall "!before!after" < infile > outfile
note:
the first character of the argument string
is an arbitrary character that is used to
separate the string to replace, and the
replacement string.
*/
parse value strip( arg( 1 ), 'B', '"' ) with sep +1 rest
if sep == '' then
call usagemsg
if pos( sep, rest ) = 0 then
call usagemsg 'The separator' sep 'was not found in:' rest
parse var rest before (sep) after
if length( before ) = 0 then
call usagemsg 'The separator' sep 'was not found in:' rest
do lines()
say changestr( linein(), before, after )
end
exit 0
usagemsg : procedure
if arg( 1 ) <> '' then
say arg( 1 )
say 'Usage:'
say ' exec chgall "/before/after" < infile > outfile'
say ''
say 'Or:'
say ' exec chgall "!before!after" < infile > outfile'
exit 1
|
/before/after
/* changestr.rex
an EXTERNAL PROCEDURE that emulates the 'changestr' builtin function
that is available in NetRexx, Object Rexx, and roo!(TM)
usage:
result = changestr( str, before, after )
*/
if arg() <> 3 then
return 40 /* incorrect call to routine */
parse arg str, before, after
/* note: the length of 'str' can be 0 */
if length( before ) = 0 then
return 40 /* incorrect call to routine */
/* note: the length of 'after' can be 0 */
res = ''
do while str <> ''
if pos( before, str ) = 0 then
leave
parse var str left (before) str
res = res || left || after
end
return res || str
|
The TWIRL program is a simple program that produces all of the permutations of the letters within a word. It can be helpful for solving common jumbles that appear in daily newspapers. It is a good example of various Rexx capabilities. The program is remarkably short.
/* twirl.rex
produce permutations of letters in a word (or jumbled word)
usage
rexx twirl wordToTwirl
*/
parse arg wordToTwirl rest
if wordToTwirl = '' then
call usagemsg 'Please specify a word to twirl...'
if rest <> '' then
call usagemsg 'Only one word is expected...'
call permute '', wordToTwirl
do queued()
parse pull lin
say lin
end
exit 0
permute : procedure
parse arg front, back
if length( back ) < 2 then do
push front || back
return
end
letters = '' /* remember letters that have been used */
do length( back )
parse var back letter +1 rest
if pos( letter, letters ) = 0 then
call permute front || letter, rest
letters = letters || letter /* used another letter */
back = rest || letter /* twirl the remaining letters */
end
return
usagemsg :
say 'Note:' arg(1)
say ''
say 'Usage:'
say ' rexx twirl wordToTwirl'
exit 1
|
The REXXTRY program is a simple, but useful, interactive Rexx command shell.
/* rexxtry.rex -- Rexx interactive shell program
usage:
rexx rexxtry
*/
prompt = '==>'
RC = 0 /* presume no errors */
call on halt
say "Type 'EXIT' to end" /* show how to stop */
resume : /* resumption point after erroneous expressions */
/* anticipate errors */
signal on error
signal on failure
signal on syntax
say time() prompt /* solicit initial REXX request */
do while lines() > 0 /* process requests until end of input */
parse linein _line_ /* get REXX request */
if _line_ = 'thanks' then /* answer unexpected praise from user */
say '...Your wish is my command' /* show humility */
else
interpret _line_ /* INTERPRET REXX statement(s) */
say time() prompt /* solicit next REXX request */
end
exit RC /* final code is returned upward */
error: failure: syntax: /* deal with erroneous requests */
say "???" condition( 'D' ) /* show befuddlement & beep */
say " " _line_ /* show erroneous request */
signal resume /* resume processing */
halt : procedure
exit 0
|
/* caldisp.rex, show calendar for current month
this is a fast calendar display program
because the days section is built by a
single instruction !
usage
rexx caldisp
*/
/* obtain year, month, and day of month */
parse value date( 'Standard' ) with year 5 month 7 dayofmon
dayofmon = strip( dayofmon, 'L', '0' ) /* strip leading zero */
/* show title lines */
say right( time('C'), 8) center( date('M'), 38 ) ,
substr( year, 3 )'.'right( date('D'), 3, '0' )
say center( year, 56 )
say ' Sun Mon Tue Wed Thu Fri Sat'
/* compute day of week: 1 to 7 */
dayofwk = 1 + ( date('B') // 7 )
/* identify #days in month */
daysinmo = word( '31 28 31 30 31 30 31 31 30 31 30 31', month )
/* add 1 to #days in month if it's February and this is a leap year */
if month = 2 then
daysinmo = daysinmo + leap( year )
/* compute day# of 1st day of month */
day1no = 1 + ((35 + dayofwk - dayofmon) // 7 )
vector = left( ' ', 8 * day1no ) || ,
overlay( ' > 'right( dayofmon, 2 )' < ' , ,
left( ,
' 1 2 3 4 5 ' || ,
' 6 7 8 9 10 ' || ,
' 11 12 13 14 15 ' || ,
' 16 17 18 19 20 ' || ,
' 21 22 23 24 25 ' || ,
' 26 27 28 29 30 ' || ,
' 31 ', (daysinmo * 8) ), ,
1 + ((dayofmon-1) * 8) )
/* show calendar lines */
do i=1 to length( vector ) by 56
say substr( vector, i, 56 )
end
exit
leap : procedure
arg yr
return (yr//4 = 0) & ((yr//100 <> 0) | (yr//400 = 0))
|
/* revise.rex, revise file lines using input template as per output form
Keywords
Pictorial form file revision
Usage
rexx revise {input_template} {output_form} [(selection_criteria)] <inf >outf
Arguments
{input_template} : a parsing template
{output_form} : emission form, using input_template terms
[(selection_criteria)] : conditional selection, using input_template terms
the special variable '_LNO' can be referenced.
Files used
Standard input
Standard output
Exit codes
0 => normal completion
non-0 => an error occurred
Input record format
an ASCII file
Sample input file
file to revise
Sample output file
revised file
Examples of use
rexx revise {f1 f2 rest} {f2 rest} <inf >outf
this removes the 1st word from every input line
rexx revise {f1 f2} {f2 f1} <inf >outf
this puts the 1st word at the end of every input line
rexx revise {lin} {lin} "(_lno <= 10)" <inf >outf
this extracts the first 10 lines of the input file
Explanation
This program is useful for a multitude of field rearranging operations. The
secret to its success is the use of two INTERPRET statements. The first
does generic parsing. The second does generic record selection versus
optional selection criteria, and then performs generic output emission.
Quoting is required for various command requests. In the last example
above "(_lno < 10)" is quoted. If it were unquoted, the '<' character
causes file redirection to be performed [from the file named '10']!
*/
if getenv( 'RXDEBUG' ) = 'Y' then
trace Results
parse arg '{' parseTemplate '}' '{' outputFormat '}' '(' selectionCondition ')'
if selectionCondition = '' then
selectionCondition = 1 /* select all */
trace off
if parseTemplate = '' | outputFormat = '' then
signal usagemsg
do _lno=1 while lines() > 0
interpret 'parse linein' parseTemplate /* parse line to terms */
interpret 'if (' selectionCondition ') then' , /* process this line ? */
'say' outputFormat /* emit output, as per form */
end
exit 0
usagemsg :
say 'Usage:'
say ,
' rexx revise {input_template} {output_form} [(selection_criteria)]' ,
' <inf >outf'
exit 1
|
| parseTemplate | parsing template |
| outputFormat | output format |
| selectionCondition | input line selection condition |