home *** CD-ROM | disk | FTP | other *** search
- Path: news-m01.ny.us.ibm.net!usenet
- From: husin@ibm.net
- Newsgroups: comp.unix.amiga
- Subject: Run this program on Amiga,PC,Unix,Mainframes * without changes!
- Date: 7 Jan 1996 06:18:26 GMT
- Message-ID: <4cnoji$4g9u@news-s01.ny.us.ibm.net>
- Reply-To: husin@ibm.net
- NNTP-Posting-Host: slip37-241-74.ibm.net
- X-Newsreader: IBM NewsReader/2 v1.2.5
-
- /* REXX */
- /*====================================================================*\
- FREEWARE
-
- ENDLESS
-
- A Multi-platform
- Execute-ready
- REXX Show Program
-
- Released and maintained by Simon Husin (husin@ibm.net)
- Version: 1996/01/06
- ========================================================================
- This program is based on the well-known 'Towers of Hanoi' problem.
-
- It is created by Simon Husin to show REXX program's flexibility and
- portability.
-
- You are encouraged to modify this program to make it run on your REXX
- engine. To make sure that it is maintained properly, I am inviting you
- to send me your modifications which I will apply on my copy to release
- it back to (more) public. To show my gratitudes, I will include your
- name and contribution(s) in the list of contributors below.
-
- I thank you in advance for your interests and cooperations.
-
- For latest news and releases, please read newsgroup 'comp.lang.rexx'!
- ------------------------------------------------------------------------
- List Of Contributors
- And Supported Platforms To-date
-
- Hard- Operating REXX YYYY/MM/DD
- Ware System Engine Applied Contributed By
- .......................................................................
- Intel+ IBM PC DOS 7.0 IBM PC DOS REXX 1995/12/25 Simon Husin
- Any? Any PC/MS-DOS+ Quercus Systems 1995/12/25 Simon Husin
- Personal/REXX 3.0
- Intel+ IBM OS/2 & Warp IBM PL/2 REXX 1995/12/25 Simon Husin
- Intel+ IBM OS/2 & Warp Quercus Systems 1995/12/25 Simon Husin
- Personal/REXX 3.0
- Intel+ IBM OS/2 & Warp IBM PL/2 REXX & 1995/12/27 Simon Husin
- Under Tritus SPF Quercus P/REXX 3.0
- Any? PC/MS-DOS+& ANSI Tritus SPF REXX 1995/12/27 Simon Husin
- Any? PC/MS-DOS+& ANSI Regina REXX 1995/12/28 Mark Hessling
- Any? Any Unix Regina REXX 1995/12/28 Mark Hessling
- Any? Any PC/MS-DOS+ Kilowatt Software 1995/12/29 Simon Husin
- Portable/REXX 1.x
- Any? PC/MS-DOS+& ANSI BNV REXX 1.x 1995/12/30 Mathew Goldstein
- Any? MS-Windows+ & Quercus Systems 1996/01/01 Simon Husin
- IBM-WinOS2 Personal/REXX 3.0
- Any? MS-Windows+ & Kilowatt Software 1995/01/01 Simon Husin
- IBM-WinOS2 Portable/REXX 1.x
- Amiga Amiga DOS William Hawes 1995/01/01 Simon Husin
- Release 2/newer ARexx ?
- IBM370+MVS-TSO/E IBM REXX/370 ? 1995/01/02 Simon Husin
- IBM370+VM/CMS IBM REXX/370 1995/01/01 Gil P.?
- Graphics + 1995/01/04 Paul Barnett
- Interpreter+Compiler
- .......................................................................
- Notes: + = Including compatibles
- ? = Still waiting for (your) confirmation
- \*====================================================================*/
-
- /*--------------------------------------------------------------------*\
- Check operating system environment
- Initial system specific commands for local system interpret(ation)
- \*--------------------------------------------------------------------*/
- parse version interpreter version release
- interpreter = translate(interpreter)
- addr = translate(address())
- parse source env . gen.SRC3 .
- gen.Footer = 'EndLess * OS-Env:'env'-'addr||,
- ' * REXX Engine:'interpreter' V.'version' of 'release
- gen.Footer = center(strip(left(gen.Footer, 78)), 78)
-
- select
- when interpreter = 'REXX370' |, /* IBM Mainframe interpreter */
- interpreter = 'REXXC370' then do /* or Mainframe compiler v2 */
- select
- when addr = 'MVS' then
- gen.Engine = 'IBMMVSREXX' /* MVS */
- when addr = 'TSO' then do
- if strip(sysvar('sysenv')) = 'FORE' then /* TSO/E */
- gen.Engine = 'IBMTSOFOREREXX' /* Foreground */
- else
- gen.Engine = 'IBMTSOBATCHREXX' /* Batch */
- end
- otherwise
- gen.Engine = 'IBMVMREXX' /* VM/CMS */
- end
- end
- when interpreter = 'UNI-REXX' then /* Unix/AIX Workstation */
- gen.Engine = 'WRKUNIREXX' /*The Workstation Group uni-REXX*/
- when interpreter = 'REXXSAA' &,
- addr = 'COMMAND' then do /* New IBM REXX environment */
- if env = 'DOS' then
- gen.Engine = 'IBMPCDOSREXX' /* IBM PC-DOS 7.x REXX */
- else
- gen.Engine = 'IBMOS400REXX' /* IBM OS/400 REXX */
- end
- when interpreter = 'REXXSAA' &,
- addr = 'CMD' then /* IBM PL 2/REXX */
- gen.Engine = 'IBMOS2REXX'
- when interpreter = 'REXXSAA' &,
- addr = 'ISPEXEC' then
- gen.Engine = 'IBMOS2REXXTSPF' /* IBM PL 2/REXX in Tritus SPF */
- when interpreter = 'REXX/PERSONAL' then do /* Quercus Systems REXX */
- if addr = 'CMD' then
- gen.Engine = 'QUERCUSOS2REXX' /* under OS/2 */
- else if addr = 'DOS' then
- gen.Engine = 'QUERCUSDOSREXX' /* under PC/MS-DOS */
- else if addr = 'WINREXX' then
- gen.Engine = 'QUERCUSWINREXX' /* under MS-Windows/IBM WinOS2*/
- else if addr = 'ISPEXEC' then
- gen.Engine = 'QUERCUSOS2REXXTSPF' /* Tritus SPF under OS/2 */
- end
- when left(interpreter, 9) = 'REXX-KILO' then /* PC/MS-DOS */
- gen.Engine = 'KILODOSREXX' /*Kilowatt Software Portable/REXX */
- when left(interpreter, 9) = 'REXX/WIND' then /* Windows/Win-OS2 */
- gen.Engine = 'KILOWINREXX' /* Kilowatt Software REXX/Windows */
- when interpreter = 'REXX:OPEN-REXX179' then
- gen.Engine = 'TRITUSDOSREXX' /* Tritus REXX under DOS TSPF */
- when interpreter = 'AREXX' then
- gen.Engine = 'AMIGAREXX' /* Amiga Micro Computer w/ ARexx */
- when left(interpreter, 11) = 'REXX-REGINA' then
- gen.Engine = 'REGINAREXX' /* Regina REXX under UNIX or DOS */
- when interpreter = 'REXX' & left(release, 3) = 'BNV' then
- gen.Engine = 'BNVREXX' /* BNV (?) REXX under PC/MS-DOS */
- otherwise
- gen.Engine = 'UNKNOWNREXX' /* Unknown OS/REXX environment */
- end
-
- /*--------------------------------------------------------------------*\
- Set engine- & platform-dependent features
- \*--------------------------------------------------------------------*/
- gen.ANSIesc = d2c(27)||d2c(91)
- /* ANSI Esc char. + open bracket */
- gen.Block = '' /* Block character for graphical present.*/
- gen.Cleanup = 'NOP' /* Exit processing (VM/CMS Graph.support)*/
- gen.Clear = "'CLS'" /* To clear screen */
- gen.Console = 'CON:' /* Name of output device */
- gen.CursorOFF = 'NOP' /* To hide the cursor during gr. present.*/
- gen.CursorON = 'NOP' /* To show the cursor after gr. present. */
- gen.DelayDur = 'call DelayTime'
- /* Instruction/command to pause in moves */
- gen.Hanoi = 'T' /* Graphical or Textual presentation */
- gen.MaxRow = 24 /* Maximum number of rows on the screen */
- gen.Q.Start = '' /* String w/ disk numbers on pole Start */
- gen.Q.Temp = '' /* String w/ disk numbers on pole Temp */
- gen.Q.Target = '' /* String w/ disk numbers on pole Target */
- gen.Start = 1 /* 1st pole pos. for graphical present. */
- gen.Steps = 0 /* Disk movements needed to solve */
- gen.Target = 53 /* last pole pos. for graphical present. */
- gen.Temp = 27 /* 2nd pole pos. for graphical present. */
-
- select
- when gen.Engine = 'AMIGAREXX' then do
- gen.Block = '*'
- gen.Console = 'STDOUT'
- gen.Clear = 'call writech' gen.Console',' gen.ANSIesc'2J'
- gen.DelayDur = 'call delay'
- gen.Hanoi = 'G'
- end
- when gen.Engine = 'BNVREXX' then
- gen.Hanoi = 'G'
- when left(gen.Engine, 10) = 'IBMOS2REXX' then do
- call rxfuncadd 'sysloadfuncs', 'REXXUTIL', 'sysloadfuncs'
- call sysloadfuncs
- if right(gen.Engine, 4) = 'TSPF' then
- gen.Clear = 'ADDRESS CMD CLS'
- gen.CursorOFF = "call syscurstate 'OFF'"
- gen.CursorON = "call syscurstate 'ON'"
- gen.DelayDur = 'call syssleep'
- gen.Hanoi = 'G'
- end
- when gen.Engine = 'IBMPCDOSREXX' then do
- gen.Console = 'CON'
- gen.CursorOFF = "call rxcrstat 'OFF'"
- gen.CursorON = "call rxcrstat 'ON'"
- gen.DelayDur = 'call rxsleep'
- gen.Hanoi = 'G'
- end
- when gen.Engine = 'IBMTSOFOREREXX' then
- gen.Clear = "'CLRSCRN'"
- when gen.Engine = 'IBMVMREXX' then do
- gen.Block = '*'
- gen.Clear = '"VMFCLEAR";'
- gen.Console = ''
- gen.DelayDur = 'CALL diag 8,"SLEEP" gen.Delay "SEC";'
- ADDRESS COMMAND
- 'QUERY CMSLEVEL ( LIFO'
- parse pull 'Level' cmslevel ','
- 'QUERY DISPLAY ( LIFO'
- parse pull terminal gen.MaxRow cols .
-
- if terminal = 'DISPLAY' & cmslevel >= 5.6 then do
- gen.Hanoi = 'G'
- 'VSCREEN DELETE' gen.SRC3
- 'VSCREEN DEFINE' gen.SRC3 gen.MaxRow cols '0 0'
- 'WINDOW DEFINE' gen.SRC3 gen.MaxRow cols '1 1'
- 'WINDOW SHOW ' gen.SRC3 'ON' gen.SRC3 '1 1'
- gen.Cleanup = gen.Delaydur ';' ,
- '"VSCREEN DELETE" gen.SRC3;' ,
- '"WINDOW DELETE" gen.SRC3;'
- gen.DelayDur = '"VSCREEN CURSOR" gen.SRC3 "1 1";' ,
- '"VSCREEN WAITT" gen.SRC3;' ,
- '"PSCREEN REFRESH";' gen.DelayDur
- end
- end
- when gen.Engine = 'KILODOSREXX' then do
- gen.Console = '!'
- gen.DelayDur = 'call delay'
- gen.Hanoi = 'G'
- end
- when gen.Engine = 'KILOWINREXX' then
- gen.DelayDur = 'call delay'
- when left(gen.Engine, 14) = 'QUERCUSDOSREXX' |,
- left(gen.Engine, 14) = 'QUERCUSOS2REXX' then do
- if right(gen.Engine, 4) = 'TSPF' then
- gen.Clear = 'ADDRESS CMD CLS'
- gen.DelayDur = 'call delay'
- gen.Hanoi = 'G'
- end
- when gen.Engine = 'QUERCUSWINREXX' then
- gen.DelayDur = 'call delay'
- when gen.Engine = 'REGINAREXX' then do
- gen.Block = '*'
- gen.Clear = 'call UnixClear'
- gen.Console = '/dev/tty'
- gen.DelayDur = 'call UnixSleep'
- gen.MaxRow = 23
- gen.Hanoi = 'G'
- end
- when gen.Engine = 'TRITUSDOSREXX' then do
- gen.Clear = 'ADDRESS CMD CLS'
- gen.Console = 'CON'
- gen.Hanoi = 'G'
- end
- otherwise nop
- end
-
- if gen.Hanoi = 'G' then do
- if gen.Block = '' then gen.Block = d2c(240)
- gen.MaxRowMin = gen.MaxRow - 1
- end
-
- /*--------------------------------------------------------------------*\
- Request number of disks to play with
- \*--------------------------------------------------------------------*/
- interpret gen.Clear
- say 'Please enter the number of disks to play with:'
- say '(if not entered, or entered but wrong it will be set to 3)'
- pull gen.Disks
- if datatype(gen.Disks) = 'NUM' then nop
- else gen.Disks = 3
- gen.Disks = gen.Disks % 1
- if gen.Disks < 1 then gen.Disks = 3
-
- /*--------------------------------------------------------------------*\
- Request for delay in seconds between disk movements
- \*--------------------------------------------------------------------*/
- say 'Please enter delay factor in seconds:'
- say '(if not entered, '||,
- 'or entered but unacceptable it will be set to 2 sec.)'
- pull gen.Delay
- if datatype(gen.Delay) = 'NUM' then nop
- else gen.Delay = 2
- gen.Delay = gen.Delay % 1
- if gen.Delay < 0 | gen.Delay > 99 then gen.Delay = 2
- if gen.Engine = 'IBMVMREXX' then nop
- else gen.DelayDur = gen.DelayDur gen.Delay
-
- /*--------------------------------------------------------------------*\
- Put as many disks as requested in 'START'
- \*--------------------------------------------------------------------*/
- do ix = 1 to gen.Disks
- gen.Q.Start = gen.Q.Start ix
- end
- gen.Q.Start = strip(gen.Q.Start)
-
- /*--------------------------------------------------------------------*\
- Start the real presentation and recursive process
- \*--------------------------------------------------------------------*/
- call time 'R'
- timestarted = time()
- if gen.Hanoi = 'T' then
- call Hanoi gen.Disks, 'START', 'TEMP', 'TARGET'
- else do
- interpret gen.Clear
- interpret gen.CursorOFF
- call GStart gen.Disks
- call GHanoi gen.Disks, 'START', 'TEMP', 'TARGET'
- interpret gen.CursorON
- end
-
- /*--------------------------------------------------------------------*\
- Show process statistics
- \*--------------------------------------------------------------------*/
- call CursorSet 1, 1
- interpret gen.Cleanup
- say
- say 'Process started at' timestarted'. It is now' time()'.'
- say 'It took' gen.Steps 'moves to solve with' gen.Disks 'disks.'
- say 'Total duration' time('E') / 1 'seconds,'
- say ' with' gen.Delay 'seconds delay for each move.'
- return
-
- /*--------------------------------------------------------------------*\
- Recursive Process (textual presentation)
- \*--------------------------------------------------------------------*/
- Hanoi: procedure expose gen.
- parse arg disks, start, temp, target
- disks = strip(disks)
- if disks = 1 then
- say 'Move disk#' DiskMove(start, target) ||,
- ' from' left(start, 6) 'to' target
- else do
- call Hanoi (disks - 1), start, target, temp
- say 'Move disk#' DiskMove(start, target) ||,
- ' from' left(start, 6) 'to' target
- call Hanoi (disks - 1), temp, start, target
- end
- return
-
- /*--------------------------------------------------------------------*\
- Move a disk from one pole to another (textual presentation)
- \*--------------------------------------------------------------------*/
- DiskMove: procedure expose gen.
- parse arg start, target
- if gen.Delay > 0 then interpret gen.DelayDur
- parse var gen.Q.Start disknum gen.Q.Start
- gen.Q.Target = disknum gen.Q.Target
- gen.Steps = gen.Steps + 1
- return right(disknum, 3)
-
- /*--------------------------------------------------------------------*\
- Show the starting pile
- \*--------------------------------------------------------------------*/
- GStart: procedure expose gen.
- arg disks
- if disks < gen.MaxRow - 2 then
- row = gen.MaxRow - 2 - disks
- else
- row = 0
- call XYString gen.MaxRow, gen.Start, gen.Console, gen.Footer
- call XYString gen.MaxRowMin, gen.Start,,
- gen.Console, center('Start', 24, gen.block)
- call XYString gen.MaxRowMin, gen.Temp,,
- gen.Console, center('Temp', 24, gen.block)
- call XYString gen.MaxRowMin, gen.Target,,
- gen.Console, center('Target', 24, gen.block)
-
- do ix = disks to 1 by -1
- call XYString (row + ix), 1,,
- gen.Console, center(center(ix, ix, gen.block), 24)
- end
- return
-
- /*--------------------------------------------------------------------*\
- Recursive Process (primitive graphical presentation)
- \*--------------------------------------------------------------------*/
- GHanoi: procedure expose gen.
- parse arg disks, start, temp, target
- disks = strip(disks)
- if disks = 1 then
- call GDiskMove start, target
- else do
- call GHanoi (disks - 1), start, target, temp
- call GDiskMove start, target
- call GHanoi (disks - 1), temp, start, target
- end
- return
-
- /*--------------------------------------------------------------------*\
- Move a disk from one pole to another (primitive graphical presentation)
- \*--------------------------------------------------------------------*/
- GDiskMove: procedure expose gen.
- parse arg start, target
- if gen.Delay > 0 then interpret gen.DelayDur
- call XYString (gen.MaxRowMin - words(gen.Q.Start)), gen.Start,,
- gen.Console, ' '
- parse var gen.Q.Start disknum gen.Q.Start
- gen.Q.Target = disknum gen.Q.Target
- call XYString (gen.MaxRowMin - words(gen.Q.Target)), gen.target,,
- gen.Console, center(center(disknum,disknum,gen.block),24)
- gen.Steps = gen.Steps + 1
- return
-
- /*--------------------------------------------------------------------*\
- General routine to write a string at a specified position on screen
- \*--------------------------------------------------------------------*/
- XYString: procedure expose gen.
- parse arg row, col, device, data
- select
- when gen.Engine = 'BNVREXX' then
- say gen.ANSIesc||row';'col'H'data
- when gen.Engine = 'IBMVMREXX' then
- 'VSCREEN WRITE' gen.SRC3 row col 1 + length(data) '( FIELD' data
- otherwise
- call CursorSet row, col
- call XCharout device, data
- end
- return
-
- /*--------------------------------------------------------------------*\
- Set the cusor on the screen at the specified location
- \*--------------------------------------------------------------------*/
- CursorSet: procedure expose gen.
- parse arg row, col
- select
- when gen.Engine = 'AMIGAREXX' then call ANSIcursor row, col
- when gen.Engine = 'BNVREXX' then say gen.ANSIesc||row';'col'H'
- when gen.Engine = 'IBMOS2REXX' then call syscurpos row, col
- when gen.Engine = 'IBMOS2REXXTSPF' then call syscurpos row, col
- when gen.Engine = 'IBMPCDOSREXX' then call rxsetpos row, col
- when gen.Engine = 'KILODOSREXX' then call cursor row, col
- when gen.Engine = 'QUERCUSDOSREXX' then call cursor row, col
- when gen.Engine = 'QUERCUSOS2REXX' then call cursor row, col
- when gen.Engine = 'QUERCUSOS2REXXTSPF' then call cursor row, col
- when gen.Engine = 'REGINAREXX' then call ANSIcursor row, col
- when gen.Engine = 'TRITUSDOSREXX' then call ANSIcursor row, col
- otherwise nop
- end
- return
-
- /*--------------------------------------------------------------------*\
- General routine to write a string of characters to screen
- \*--------------------------------------------------------------------*/
- XCharout: procedure expose gen.
- parse arg device, data
- if gen.Engine = 'AMIGAREXX' then
- call writech device, data
- else
- call charout device, data
- return
-
- /*--------------------------------------------------------------------*\
- Internal function to use ANSI escape sequence to position cursor
- \*--------------------------------------------------------------------*/
- ANSICursor: procedure expose gen.
- parse arg row, col
- call XCharout gen.Console, gen.ANSIesc||row';'col'H'
- return
-
- /*--------------------------------------------------------------------*\
- Internal functions to call Unix commands
- \*--------------------------------------------------------------------*/
- UnixClear: procedure expose gen.
- Address System 'clear'
- return
-
- UnixSleep: procedure expose gen.
- parse arg seconds
- Address System 'sleep' seconds
- return
-
- /*--------------------------------------------------------------------*\
- Internal function to simulate delay
- \*--------------------------------------------------------------------*/
- DelayTime: procedure
- parse arg delay
- start= time('S')
- now = start
- done = start + delay
- do until now >= done
- now = time('S')
- if now < start then now = now + 86400
- end
- return
-
-