/* YOU 0 | pipe | YOU 1 first | YOU 2 | pipe | YOU 1 */ /* / \ / \ */ /* \_ pull <==== queue _/ \_ pull <==== queue _/ */ call trace 'O' /* disable any SET RXTRACE=ON */ signal on novalue name TRAP ; signal on syntax name TRAP signal on failure name TRAP ; signal on halt name TRAP call UTIL 'SysSleep' ; arg IO QU QD if wordpos( IO, '0 1 2' ) = 0 | QD <> '' then do parse source . . IO ; QU = 'examples (looping "forever"):' say 'usage:' IO '0|1|2 [queue]' say '0 : copy queue to standard output (top)' say '1 : copy standard input to queue (tail)' say '2 : copy STDIN and then queue to STDOUT' say ' XYZ: create / delete queue XYZ' say ' else: use default SESSION queue,' QU say 'echo loop |' IO '2 | tee \dev\con |' IO '1' say 'echo dito |' IO '2 | tee \dev\con | rxqueue' say 'echo fail |' IO '2 XYZ | tee \dev\con | rxqueue XYZ' say 'echo okay |' IO '2 XYZ | tee \dev\con |' IO '1 XYZ' say IO '0 XYZ | chess white | chess black |' IO '1 XYZ' exit 1 end QD = ( QU <> '' & IO <> 1 ) /* QD = 0: no QUeue Deletion */ if QD then do call rxqueue 'DELETE', QU /* delete old & create new QU */ if rxqueue( 'CREATE', QU ) <> QU then exit TRAP( 'cannot create queue' QU ) end signal on novalue name DONE ; signal on syntax name DONE signal on failure name DONE ; signal on halt name DONE if QU <> '' then do /* wait for new QU creation */ call SysSleep 1 ; call rxqueue 'SET', QU end if IO = 2 then do /* first copy STDIN to STDOUT */ IO = 0 ; signal on notready name LOOP do while lines() > 0 ; say linein() ; end end /* NOTREADY continues at LOOP */ LOOP: /* no procedure: using IO, QD */ signal on notready name DONE /* signal on any I/O problems */ do forever if IO = 0 then do while queued() > 0 ; say PULL() ; end else do while lines( ) > 0 ; queue linein() ; end call SysSleep 0 /* wait for other end of pipe */ end PULL: procedure /* artificial pull wrapper to */ parse pull X ; return X /* get "beautified" LOOP code */ UTIL: procedure /* load necessary RexxUtil entry */ if RxFuncQuery( arg( 1 )) then if RxFuncAdd( arg( 1 ), 'RexxUtil', arg( 1 )) then exit TRAP( "can't add RexxUtil" arg( 1 )) return 0 DONE: /* either STDIN or STDOUT is */ if IO = 0 /* NOTREADY, drain other side */ then do while queued() > 0 ; pull ; end else do while lines( ) > 0 ; call linein ; end call SysSleep 1 /* wait for other end of pipe */ if IO = 0 /* (it will see NOTREADY now) */ then do while queued() > 0 ; pull ; end else do while lines( ) > 0 ; call linein ; end if condition( 'c' ) = 'HALT' then call charout 'STDERR', 'terminated ' if QD then do /* erase the named REXX queue */ call rxqueue 'DELETE', QU /* and show result (expect 0) */ call lineout 'STDERR', 'deleting' QU '(' || result || ')' end if condition( 'c' ) = 'HALT' then exit 0 /* interrupted or */ if condition( 'c' ) = 'NOTREADY' then exit 0 /* terminated ok. */ /* otherwise after FAILURE, SYNTAX, or NOVALUE drop into TRAP: */ /* see , (c) F. Ellermann */ TRAP: /* select REXX exception handler */ call trace 'O' ; trace N /* don't trace interactive */ parse source TRAP /* source on separate line */ TRAP = x2c( 0D ) || right( '+++', 10 ) TRAP || x2c( 0D0A ) TRAP = TRAP || right( '+++', 10 ) /* = standard trace prefix */ TRAP = TRAP strip( condition( 'c' ) 'trap:' condition( 'd' )) select when wordpos( condition( 'c' ), 'ERROR FAILURE' ) > 0 then do if condition( 'd' ) > '' /* need an additional line */ then TRAP = TRAP || x2c( 0D0A ) || right( '+++', 10 ) TRAP = TRAP '(RC' rc || ')' /* any system error codes */ if condition( 'c' ) = 'FAILURE' then rc = -3 end when wordpos( condition( 'c' ), 'HALT SYNTAX' ) > 0 then do if condition( 'c' ) = 'HALT' then rc = 4 if condition( 'd' ) > '' & condition( 'd' ) <> rc then do if condition( 'd' ) <> errortext( rc ) then do TRAP = TRAP || x2c( 0D0A ) || right( '+++', 10 ) TRAP = TRAP errortext( rc ) end /* future condition( 'd' ) */ end /* may use errortext( rc ) */ else TRAP = TRAP errortext( rc ) rc = -rc /* rc < 0: REXX error code */ end when condition( 'c' ) = 'NOVALUE' then rc = -2 /* dubious */ when condition( 'c' ) = 'NOTREADY' then rc = -1 /* dubious */ otherwise /* force non-zero whole rc */ if datatype( value( 'RC' ), 'W' ) = 0 then rc = 1 if rc = 0 then rc = 1 if condition() = '' then TRAP = TRAP arg( 1 ) end /* direct: TRAP( message ) */ TRAP = TRAP || x2c( 0D0A ) || format( sigl, 6 ) signal on syntax name TRAP.SIGL /* throw syntax error 3... */ if 0 < sigl & sigl <= sourceline() /* if no handle for source */ then TRAP = TRAP '*-*' strip( sourceline( sigl )) else TRAP = TRAP '+++ (source line unavailable)' TRAP.SIGL: /* ...catch syntax error 3 */ if abbrev( right( TRAP, 2 + 6 ), x2c( 0D0A )) then do TRAP = TRAP '+++ (source line unreadable)' ; rc = -rc end select when 1 then do /* in pipes STDERR: output */ parse version TRAP.REXX . . /* REXX/Personal: \dev\con */ signal on syntax name TRAP.FAIL if TRAP.REXX = 'REXXSAA' /* fails if no more handle */ then call lineout 'STDERR' , TRAP else call lineout '\dev\con', TRAP end when 0 then do /* OS/2 PM: RxMessageBox() */ signal on syntax name TRAP.FAIL call RxMessageBox , /* fails if not in PMREXX */ translate( TRAP, ' ', x2c( 0D )), , 'CANCEL', 'WARNING' end /* replace any CR by blank */ otherwise say TRAP ; trace ?L /* interactive Label trace */ end if condition() = 'SIGNAL' then signal TRAP.EXIT TRAP.CALL: return rc /* continue after CALL ON */ TRAP.FAIL: say TRAP ; rc = 0 - rc /* force TRAP error output */ TRAP.EXIT: exit rc /* exit for any SIGNAL ON */