zOs/REXX.O13/GEOM
/* REXX *************************************************************
this editmacro moves points by different geometric maps
default
-f<xy> from point 0, 0
-g<xy> if set select only points in select all points
rectangle (-f, -g)
-r<a> rotate by a * 90 degrees 0
-d<a> rotate Direction values by a -r
-s<f> stretch by a factor f 1
-s<xy> stretch in x/y direction 1 1
-t<xy> to point -f
.<fr> from label .zf
.<to> to label .zl
<a> angle an integer
<f> a float, e.g 13 or 45.67
<xy> coordinatesgates eg 0,34.6
**********************************************************************/
call adrEdit('macro (args)')
say 'macro args' args
if args = '' then
args = '-f121.0,289.5 -t100,100 .a .b -r2'
call analyseArgs args
rst = rotStrTraArgs(optR optS optF optT)
say 'rst' rst '-f =>' rotStrTra(rst optF)
call adrEdit '(lnF) = linenum' labF
call adrEdit '(lnT) = linenum' labT
say 'labels' labF lnF labT lnT
selPos = 0
do lx=lnF to lnT
call adrEdit '(li) = line' lx
new = editPosition(lx, li)
if optD <> 0 & new <> '' then do
new = editDirection(lx, new)
end
if new <> '' then
call adrEdit "line" lx "= (new)"
end
exit
/* *****************************************
FIELD POSIT 100.0 100.0 Font A2828I direction BACK 11 ;
FIELD POSIT 81.0 100.0 Font A2828I direCTI DOWN 8 ;
FIELD POSIT 154.5 289.5 Font A1817I START 20 LENGTH 11 ;
**********************************************************/
/* *****************************************
FIELD POSIT 121.0 289.5 Font A2828I direction across 11 ;
FIELD POSIT 140.0 289.5 Font A2828I direCTI up 8 ;
FIELD POSIT 154.5 289.5 Font A1817I START 20 LENGTH 11 ;
FIELD POSIT 170.8 289.5 Font A1817I START 31 LENGTH 4 ;
SN: Seitennummer
FIELD POSIT 179.5 289.5 Font A1817I START 35 LENGTH 8 ;
FIELD POSIT 192.3 289.5 Font A1817I START 43 LENGTH 2 ;
**********************************************************/
call testGeom
editPosition: procedure expose optG RST
parse arg lx, li
up = translate(li)
px = pos('POSI', up)
if px < 1 then
return ''
xx = wordIndex(substr(li, px), 2) + px - 1
yx = wordIndex(substr(li, px), 3) + px - 1
rx = wordIndex(substr(li, px), 4) + px - 1
if rx < 1 then
rx = length(li) + 1
if xx <= px | yx <= xx then do
say 'missing words skipping line' lx li
return ''
end
x = word(substr(li, xx), 1)
y = word(substr(li, yx), 1)
if datatype(x) <> 'NUM' | datatype(y) <> 'NUM' then do
say 'not numeric skipping line' lx li
return ''
end
if optG <> '' then do
if word(optG, 1) > x | x > word(optG, 3) ,
| word(optG, 2) > y | y > word(optG, 4) then
return ''
end
n2 = rotStrTra(RST x y)
xS = pos(' ', li, px) + 1
rS = rx - (rx <= length(li))
return left(li, xS-1),
|| reformat(n2, substr(li, xS, rS-xS)),
|| substr(li, rS)
endProcedure editPosition
reformat: procedure
parse arg nums, like
res = ''
do wx=1 to words(nums)
w = word(nums, wx)
dx = pos('.', w)
if dx > 0 & length(w) - dx > 2 then
res = res format(w,,2)
else
res = res w
end
if length(res) > 0 then
res = substr(res, 2)
if length(res) >= length(like) then
return res
do wx=1 to words(nums)
rw = wordIndex(res, wx)
rx = verify(res, '. ', 'm', rw)
if rx < rw then
rx = length(res)
lw = wordIndex(like, wx)
lx = verify(like, '. ', 'm', lw)
if lx < lw then
lx = length(like)
if rx < lx then do;
if lx-rx >= length(like) - length(res) then
return left(res, rw-1) ,
|| left('',length(like) - length(res)),
|| substr(res,rw)
res = left(res, rw-1)left('',lx-rx)substr(res,rw)
if length(res) >= length(like) then
return res
end
end
return left(res, length(like))
endProcedure reformat
editDirection: procedure expose optD
parse arg lx, li
dirs = '0=ACROSS 1=DOWN 2=BACK 3=UP '
dx = pos('DIRE', translate(li))
if dx < 1 then
return ''
vx = wordIndex(substr(li, dx), 2) + dx - 1
w = translate(word(substr(li, vx), 1))
if w = '' then do
say 'direction missing' lx li
return ''
end
cx = pos('='w, dirs)
if cx < 2 then do
say 'direction illegal' w 'line' lx li
return ''
end
nx = angleNorm(optD + substr(dirs, cx-1, 1))
cx = pos(nx'=', dirs)
nn = word(substr(dirs, cx+2), 1)
qx = length(nn) - length(w)
if qx <= 0 then do
new = left(li, vx-1)nn||left('',-qx)substr(li,vx+length(w))
end
else do
rx = verify(substr(li, vx+length(w)), ' ');
if rx <= 0 then
rx = 1 + length(li)
else if rx - 2 > qx then
rx = vx + length(w) + qx
else
rx = vx + length(w) + rx - 2
new = left(li, vx-1)nn||strip(substr(li,rx), 't')
end
return new
end editDirection
analyseArgs: procedure expose optD optF optG optR optS optT labF labT
parse arg args
parse value '0 *' with optR optD optF optG optT labF labT
optS = 1 1
do wx=1 by 1
w = word(args, wx)
if w = '' then
leave
wL = left(w, 2)
wR = substr(w, 3)
select
when wL = '-d' then optD = wR
when wL = '-f' then optF = translate(wR, ' ', ',')
when wL = '-g' then optG = translate(wR, ' ', ',')
when wL = '-r' then optR = wR
when wL = '-s' then do
optS = translate(wR, ' ', ',')
if words(optS) = 1 then
optS = optS optS
end
when wL = '-t' then optT = translate(wR, ' ', ',')
when left(wL, 1) = '.' then do
if labF = '' then labF = w
else if labT = '' then labT = w
else call err 'more than two labels' w
end
when wL = '-?' | left(wL, 1) = '?' then do
call help
exit
end
otherwise call err 'bad Option' w
end /* select */
end /* do each word */
if optF = '' then optF = 0 0
if optT = '' then optT = optF
if labF = '' then labF = '.zf'
if labT = '' then labT = '.zl'
if optG <> '' then do
if word(optF, 1) <= word(optG, 1) then do
tl = word(optF, 1)
br = word(optG, 1)
end
else do
tl = word(optG, 1)
br = word(optF, 1)
end
if word(optF, 2) <= word(optG, 2) then
optG = tl word(optF, 2) br word(optG, 2)
else
optG = tl word(optG, 2) br word(optF, 2)
end
if optD = '*' then
optD = optR
else if optD = '' then
optD = 0
say 'analyseArgs -f='optF '-g='optG '-r='optR '-d='optD,
'-s='optS '-t='optT,
'from' labF 'to' labT
return
endProcedure analyseArgs
testGeom: procedure
say 'mod(112, 10)' mod(112, 10)
say 'mod(-112, 10)' mod(-112, 10)
say testRotate(0 4 5)
say testRotate(1 4 5)
say testRotate(1 4 '-5')
say testRotate(2 4 '-5')
say testRotate(3 4 '-5')
say testRotate(-297 4 '-5')
/* say testRotate(297.1 4 '-5') */
call testRST 0 1 1 1 2 7 9
call testRST 3 1 1 1 2 7 9
call testRST 2 2 3 1 2 7 9
return
end gestGeom
testRotate: procedure
parse arg aa
return 'rotate('aa') => 'rotate(aa)
endProcedure testRotate
rotate: procedure
parse arg a x y
select
when a=0 then return x y
when a=1 then return -y x
when a=2 then return -x (-y)
when a=3 then return y (-x)
otherwise return rotate(angleNorm(a) x y)
end
endProcedure rotate
testRST: procedure
parse arg r sx sy f g t u
aa = rotStrTraArgs(r sx sy f g t u)
say 'rotStrTraArgs('r sx sy f g t u ') =>' aa
say 'from RST('f g') =>' rotStrTra(aa f g)
say ' RST(-7 0 +7, -3) =>' left(rotStrTra(aa (-7) (-3)), 12) ,
left(rotStrTra(aa ( 0) (-3)), 12) ,
left(rotStrTra(aa (+7) (-3)), 12)
say ' RST(-7 0 +7, 0) =>' left(rotStrTra(aa (-7) ( 0)), 12) ,
left(rotStrTra(aa ( 0) ( 0)), 12) ,
left(rotStrTra(aa (+7) ( 0)), 12)
say ' RST(-7 0 +7, +3) =>' left(rotStrTra(aa (-7) (+3)), 12) ,
left(rotStrTra(aa ( 0) (+3)), 12) ,
left(rotStrTra(aa (+7) (+3)), 12)
return
end testRST
rotStrTra: procedure
parse arg r sx sy t u x y
return trans(stretch(sx sy rotate(r x y)) t u)
endProcedure trans
rotStrTraArgs: procedure
parse arg r sx sy f g t u
/* rotate and stretch origin (f g) */
z = stretch(sx sy rotate(r f g))
/* move it to (t u) */
return r sx sy trans(t u rotate(2 z))
endProcedure rotStrTraArgs
trans: procedure
parse arg a b x y
return (a+x) (b+y)
endProcedure trans
stretch: procedure
parse arg fx fy x y
return (fx*x) (fy*y)
endProcedure stretch
angleNorm: procedure
parse arg a
n = mod(a, 4)
if length(n) <> 1 | verify(n, '0123') > 0 then
call err 'bad angle' a
return n
endProcedure angleNorm
mod: procedure
parse arg a, b
if a >= 0 then
return a // b
else
return b + a // b
endProcedure mod
/************** member copy adr **************************************/
/**********************************************************************
dsn*: manipulate dataSetNames
dsn2Jcl: convert from tso to JCL format
dsnFromJcl: convert from jcl to TSO format
dsnGetLLQ: get the llq from a dsn
dsnGetMbr: get the Member name from a dsn
dsnApp: cleanup and append dsn parts (preserve apos ...)
dsnSetMbr: set a Member name or remove it if mbr = ''
***********************************************************************/
say dsnApp("a.b c(d e) f' ))) h")
say dsnApp("'a.b c(d e) f' ))) h")
call help
call errHelp(test errHelp)
dsn2jcl: procedure
parse arg dsn .
if left(dsn,1) = "'" then
return strip(dsn, 'b', "'")
else if sysvar('SYSPREF') = '' then
return dsn
else
return sysvar('SYSPREF')'.'dsn
endProcedure dsn2Jcl
dsnFromJcl: procedure
parse arg dsn .
return "'"dsn"'"
endProcedure dsnFromJcl
dsnApp: procedure
parse arg parts
dsn = ''
do wx=1 by 1
w = word(parts, wx)
if w = '' then
leave
do while w <> ''
if pos(right(w, 1), "') ") <= 0 then
leave
w = left(w, length(w)-1)
end
dsn = dsn || w
end
if pos('(', dsn) > 0 then
dsn = dsn')'
if left(dsn,1) = "'" then
return dsn"'"
else
return dsn
endProcedure dsnApp
dsnSetMbr: procedure
parse arg dsn, mbr
mbr = strip(mbr)
bx = pos('(', dsn)
if mbr = '' then do
if bx < 1 then
return dsn
else if left(dsn, 1) = "'" then
return left(dsn,bx-1)"'"
else
return left(dsn,bx-1)
end
else do
if bx < 1 then
return dsnApp(dsn '('mbr)
else
return dsnApp(left(dsn, bx) mbr)
end
endProcedure dsnSetMbr
dsnGetMbr: procedure
parse arg dsn
lx = pos('(', dsn)
rx = pos(')', dsn, lx+1)
if lx < 1 then
return ''
else if lx < rx then
return substr(dsn, lx+1, rx-lx-1)
else
return strip(substr(dsn,lx+1), 't', "'")
endProcedure dsnGetMbr
dsnGetLLQ: procedure
parse arg dsn
rx = pos('(', dsn) - 1
if rx < 0 then
rx = length(dsn)
lx = lastPos('.', dsn, rx)
return strip(substr(dsn, lx+1, rx-lx), 'b', "'")
endProcedure dsnGetLLQ
/**********************************************************************
lmd: catalog read
call sequence: lmdBegin, lmdNext*, lmdEnd
mit lmd service (mit save in file und read,
weil list zu langsam und listcat abstürzt)
1. arg (grp) als group dataset für lmd save
und dd name für file read
***********************************************************************/
lmdTest: procedure
parse arg lev
say showTime() 'lmdTest' lev
call lmdBegin 'test', lev
say showTime() 'lmdTest after begin' lev
z = 0
do while lmdNext('test', st.)
do y=1 to st.0
z=z+1
say z word(st.y, 1)
end
end
call lmdEnd 'test'
say showTime() 'lmdTest' z 'files in' lev
return /* readTest */
lmdBegin: procedure
parse arg grp, lev
call adrIsp 'lmdinit listid(lmdId) level('lev')'
call adrIsp 'lmdlist listid(&lmdId) option(save) group('grp')'
call adrIsp 'lmdfree listid(&lmdId)'
say showTime() 'lmdlist save' grp lev
call readBegin grp, grp'.datasets'
return /* end lmdBegin */
lmdNext:
parse arg lvGrp, lvSt
return readNext(lvGrp, lvSt)
lmdEnd: procedure
parse arg grp
call readEnd grp
return /* end lmdEnd */
/**********************************************************************
member list of a pds:
call sequence x=lmmBegin(dsn) lmmNext(x) * lmmEnd(x)
***********************************************************************/
lmmTest: procedure
parse arg dsn
if dsn = '' then
dsn = 'wk.pli(*)'
say 'lmmTest for dsn' dsn
id = lmmBegin(dsn)
do ix=1 by 1
m = lmmNext(id)
if m = '' then
leave
say ix m
end
call lmmEnd id
say 'lmmTest end' (ix-1) 'members in' dsn
return
endProcedure lmmTest
lmmBegin: procedure
parse arg dsn
mbr = dsnGetMbr(dsn)
pds = dsnSetMbr(dsn, )
call adrIsp "LMINIT DATAID(lmmId) DATASET("pds") ENQ(SHRW)"
call adrIsp "LMOPEN DATAID("lmmId") OPTION(INPUT) "
res = lmmId
if mbr <> '' then
res = res 'pattern('mbr')'
say 'lmmBegin returning' res
return res
end lmmBegin
lmmEnd: procedure
parse arg lmmId opt
if adrIspRc("LMMLIST DATAID("lmmId") option(free)") <> 0 then
if rc <> 8 then
call err "lmmEnd" id lmmId "rc" rc "for lmmList free"
call adrIsp "LMCLOSE DATAID("lmmId")"
call adrIsp "LMFREE DATAID("lmmId")"
return
endProcedure lmmEnd
lmmNext: procedure
parse arg lmmId opt
gmRc = adrIspRc("LMMLIST DATAID("lmmid")" ,
"OPTION(LIST) MEMBER(Mbr)" opt)
if gmRc = 0 then
return mbr
else if gmRc = 8 | gmRC = 4 then
return ''
else
call err 'lmmList rc' gmRc
endProcedure lmmNext
/**********************************************************************
read: read a file
call sequence: readBegin, readNext*, readEnd
1. arg (dd) dd name, wird alloziert in begin und free in end
readNext liest 100 records in übergebenen stem,
returns false at eof
***********************************************************************/
readTest: procedure
parse arg dsn
say showTime() 'readTest' dsn
call readBegin 'ddEins', dsn
z = 0
do while readNext('ddEins', st.)
do y=1 to st.0
z=z+1
say z strip(st.y, 't')
end
end
call readEnd 'ddEins'
say showTime() 'readTest' z 'records in' dsn
return /* readTest */
readBegin: procedure
parse arg dd, dsn
call adrTso 'alloc dd('dd') shr reuse dsn('dsn')'
return /* end readBegin */
readNext:
parse arg lv_DD, lv_St
if adrTsoRc('execio 100 diskr' lv_DD '(stem' lv_St')') = 0 then
return 1
else if rc = 2 then
return (value(lv_St'0') > 0)
else
call err 'execio 100 diskr' lv_DD 'rc' rc
return /* end readNext */
readEnd: procedure
parse arg dd
call adrTso 'execio 0 diskr' dd '(finis)'
call adrTso 'free dd('dd')'
return /* end readEnd */
/**********************************************************************
writeApp: append lines to a file
ggDsn: dsn to append lines
ggStem stem containing line (with dot|)
ggNr number of lines, if empty <stem>.0
***********************************************************************/
writeApp:
parse arg ggDsn, ggStem, ggNr
if ggNr = '' then
ggNr = value(ggStem'0')
if pos('(', ggDsn) < 1 then do /* sequential ds, use disp=mod */
call adrTso 'alloc mod reuse dd(ddApp) dsn('ggDsn')'
end
else do /* pds: read and rewrite */
call adrTso 'alloc shr reuse dd(ddApp) dsn('ggDsn')'
if sysdsn(ggDsn) = 'OK' then do
call adrTso 'execio * diskr ddApp (stem ggL. finis)'
call adrTso 'execio' ggL.0 'diskw ddApp (stem ggL.)'
end
end
call adrTso 'execio' ggNr 'diskw ddApp (stem' ggStem 'finis)'
call adrTso 'free dd(ddApp)'
return
endProcedure writeApp
log: procedure
parse arg logLine
l.1 = date('s') time() logLine
call writeApp 'wk.out(ll)', l., 1
return
endProcedure log
/**********************************************************************
variable Expansion: replace variable by their value
***********************************************************************/
varExpandTest: procedure
m.v.eins ='valEins'
m.v.zwei ='valZwei'
m.l.1='zeile eins geht unverändert'
m.l.2='$EINS auf zeile ${ZWEI} und \$EINS'
m.l.3='...$EINS?auf zeile ${ZWEI}und $EINS'
m.l.4='...$EINS,uf zeile ${ZWEI}und $EINS$$'
m.l.5='${EINS}$ZWEI$EINS${ZWEI}'
m.l.0=5
call varExpand l, r, v
do y=1 to m.r.0
say 'old' y m.l.y
say 'new' y m.r.y
end
return
endProcedure varExpandTest
varExpand: procedure expose m.
parse arg old, new, var
varChars = ,
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
do lx=1 to m.old.0
cx = 1
res = ''
do forever
dx = pos('$', m.old.lx, cx)
if dx < cx then do
m.new.lx = res || strip(substr(m.old.lx, cx), 't')
leave
end
res = res || substr(m.old.lx, cx, dx - cx)
if dx >= length(m.old.lx) then
call err '$ at end line m.'old'.'lx'='m.old.lx
if substr(m.old.lx, dx+1, 1) = '$' then do
res = res || '$'
cx = dx + 2
iterate
end
if substr(m.old.lx, dx+1, 1) = '{' then do
cx = pos('}', m.old.lx, dx+1)
if cx <= dx then
call err 'ending } missing line m.'old'.'lx'='m.old.lx
na = substr(m.old.lx, dx+2, cx-dx-2)
cx = cx + 1
end
else do
cx = verify(m.old.lx, varChars, 'N', dx+1);
if cx <= dx then
cx = length(m.old.lx) + 1
na = substr(m.old.lx, dx+1, cx-dx-1)
end
if symbol('m.v.na') = 'VAR' then
res = res || m.var.na
else
call err 'var' na 'not defined line m.'old'.'lx'='m.old.lx
end
m.new.0 = m.old.0
end
return /* var expand */
/**********************************************************************
adrSql: execute sql thru the dsnRexx interface
***********************************************************************/
adrSql: /* no procedure, to keep variables sql... */
parse arg ggStmt, ggNo
if ggNo <> '1' then
ggStmt = 'execSql' ggStmt
address dsnRexx ggStmt
if rc = 0 then
nop /* say "sql ok:" ggStmt */
else if rc > 0 then
say "sql warn rc" rc sqlmsg()':' ggStmt
else
call err "sql rc" rc sqlmsg()':' ggStmt
return
endSubroutine adrSql
adrSqlConnect: procedure
parse arg sys
if adrTSORc("SUBCOM DSNREXX") <> 0 then do
sRC = RXSUBCOM('ADD','DSNREXX','DSNREXX') /* ADD HOST CMD ENV */
say 'subcom' sRc
end
call adrSql "connect" sys, 1
return
endProcedure adrSqlConnect
adrSqlDisconnect: procedure
call adrSql "disconnect ", 1
return
endProcedure adrSqlDisconnect
sqlMsg: /* no procedure, to keep variables sql... */
if sqlCode = 0 then
return 'ok (sqlCode=0)'
else
return 'sqlCode='sqlCode,
'errMc' strip(translate(sqlerrmc, ',', 'FF'x))
endSubroutine sqlMsg
/**********************************************************************
adrDsn: send a command to db2 with the TSO dsn command
***********************************************************************/
adrDsn: procedure
parse arg sys, cmd, rcOk
call adrTso 'alloc dd(sysprint) new reuse'
push 'END'
push cmd
rr = adrTsoRc('DSN SYSTEM('sys')')
say 'rc' rr 'adrTso DSN SYSTEM('sys') cmd' cmd
if wordPos(rr, rcOk) < 1 then do
say 'error rc' rr 'in adrTso DSN SYSTEM('sys') cmd' cmd
call adrTso 'execio * diskr sysprint (finis stem pr.)'
say 'sysprint' pr.0 'lines'
do x=1 to pr.0
say strip(pr.x, 't')
end
call adrTso 'free dd(sysprint) '
call err 'rc' rr 'in adrTso DSN SYSTEM('sys') cmd' cmd
end
call adrTso 'free dd(sysprint)'
return rr
endProcedure adr Dsn
/**********************************************************************
adr*: address an environment
adrTso: fails if rc <> 0
adrTsoRc: returns rc without failing
***********************************************************************/
adrTsoRc:
parse arg tsoCmd
address tso tsoCmd
return rc /* end adrTsoRc */
adrTso:
parse arg tsoCmd
address tso tsoCmd
if rc <> 0 then
call err 'adrTso rc' rc 'for' tsoCmd
return /* end adrTso */
adrIspRc:
parse arg ispCmd
address ispexec ispCmd
return rc /* end adrIspRc */
adrIsp:
parse arg ispCmd
address ispexec ispCmd
if rc <> 0 then
call err 'adrIsp rc' rc 'for' ispCmd
return /* end adrIsp */
adrEdit:
parse arg editCmd, ret
address isrEdit editCmd
if rc <> 0 then
call err 'adr isrEdit rc' rc 'for' editCmd
return /* end adrEdit */
adrEditRc:
parse arg editCmd
address isrEdit editCmd
return rc /* end adrEditRc */
err:
parse arg txt
parse source s1 s2 s3 .
say 'fatal error in' s3':' txt
exit 12
errHelp: procedure
parse arg errMsg
say 'fatal error:' errMsg
call help
call err errMsg
endProcedure errHelp
help: procedure
parse source . . s3 .
say 'help for rexx' s3
do lx=1 by 1
if pos('/*', sourceLine(lx)) > 0 then
leave
else if lx > 10 then do
say 'initial commentblock not found for help'
return
end
end
do lx=lx+1 by 1
li = strip(sourceLine(lx), 't', ' ')
if pos('*/', li) > 0 then
leave
say li
end
return
endProcedure help
showtime:
parse arg showmsg
return time() sysvar('syscpu') sysvar('syssrv') showmsg