zOs/REXX.O08/VDPS

mbr = vdpspe0
call readDsn '~wk.text('mbr')', i.
say 'read' i.0 'from' mbr
sum = 0
dlt = 1000000
nxt = dlt
laKy = ''
laSu = 0
m.fld = instrumentid

do i=1 to i.0
    key = word(i.i, 1)
    cnt = word(i.i, 2)
    if translate(key) = 'FROM' then do
        say 'from' cnt
        m.table = cnt
        iterate
        end
    if words(i.i) ^= 2 then do
        if 0 then
            say 'ignore words' strip(i.i)
        iterate
        end
    if ^(datatype(key, 'N')& datatype(cnt, 'N')) then do
        if 0 then
           say 'ignore numbr' strip(i.i)
        iterate
        end
    sum = sum + cnt
    if 0 then
        say i strip(i.i) 'sum' sum
    if sum >= nxt then do
        call emit laKy, key, sum - laSu
        laKy = key
        laSu = sum
        nxt = sum + dlt
        end
    end
    call emit laKy, , sum - laSu
    if 0 then
        call mShow o
call writeDsn '~wk.text('mbr'o)', m.o., , 1
exit

emit: procedure expose m.
parse arg prev, act, cc
     r = ''
     if prev ^= '' then
        r = m.fld '>' prev'0000'
     if act ^= '' then do
        if r ^= '' then
            r = r 'and'
        r = r m.fld '<=' act'0000'
        end
     r = r'; --' cc
     say '***' r
     call mAdd o,
           , 'UPDATE ' m.table 'SET PROVIDERTYPE = 1',
           , '    where' r,
           , '  commit;' ,
           , '  select current timestamp from sysibm.sysdummy1;'
     return r
endProcedure emit

err:
    call errA arg(1), 1
endSubroutine err
/* copy m begin ********************************************************
    stem and tree handling
***********************************************************************/
/*--- increase m.m and return it (fail if undefined) -----------------*/
mInc: procedure expose m.
    parse arg m, delta
    if delta = '' then
        m.m = m.m + 1
    else
        m.m = m.m + delta
    return m.m
endProcedure mInc

/*--- increase m.m and return it (also if undefined) -----------------*/
mIncD: procedure expose m.
    parse arg m, delta
    if symbol('m.m') <> 'VAR' then
        m.m = 0
    return mInc(m)
endProcedure mIncD

/*--- return Ky of m ------------------------------------------------*/
mKy: procedure expose m.
    parse arg m
    return m.mKey.m
endProcedure mKy

/*--- return number of children of node m or 0 -----------------------*/
mSize: procedure expose m.
    parse arg m
    if symbol('m.m.0') == 'VAR' then
        return m.m.0
    else
        return 0
endProcedure mSize

/*--- return parent of node m or '' ----------------------------------*/
mPar: procedure expose m.
parse arg m
    dx = lastPos('.', m)
    if dx <= 1 then
        return ''
    else
        return left(m, dx - 1)
endProcedure mPar

/*--- create a new tree root -----------------------------------------*/
mRoot: procedure expose m.
parse arg m, Ky, val
    if m == '' then
        m = 'mRoot.' || mIncD('mRoot.0')
    m.m = val
    m.mKey.m = Ky
    m.m.0 = 0
    return m
endProcedure mRoot

/*--- add one or several values to stem m.m --------------------------*/
mAdd: procedure expose m.
    parse arg m
    ix = mSize(m)
    do ax = 2 to arg()
        ix = ix + 1
        m.m.ix = arg(ax)
        end
    m.m.0 = ix
    return m'.'ix
endProcedure mAdd

/*--- add to m.dst.* a (sub)sequence of m.src.* ----------------------*/
mAddSeq: procedure expose m.
    parse arg dst, src, begX, endX
    if begX = '' then
        begX = 1
    if endX = '' then
        endX = mSize(src)
    dx = mSize(dst)
    do sx = begX to endX
        dx = dx + 1
        m.dst.dx = m.src.sx
        end
    m.dst.0 = dx
    return dst
endProcedure mAddSeq

/*--- add one value to the stem m.m ----------------------------------*/
mAddNd: procedure expose m.
    parse arg m
    ix = mSize(m)
    do ax = 2 to arg()
        ix = ix + 1
        m.m.ix = arg(ax)
        m.m.ix.0 = 0
        end
    m.m.0 = ix
    return m'.'ix
endProcedure mAddNd

/*--- add one Ky value pair to stem m.m -----------------------------*/
mAddKy: procedure expose m.
    parse arg m, Ky, val
    nn = mAddNd(m, val)
    m.mKey.nn = Ky
    return nn
endProcedure mAddKy

/*--- add one indexable Ky value pair to stem m.m -------------------*/
mAddK1: procedure expose m.
    parse arg m, ky, val
    if symbol('m.mIndex.m.mKey.ky') == 'VAR' then
        call err 'duplicate Ky' ky 'for node' m
    nn = mAddNd(m, val)
    m.mKey.nn = ky
    m.mIndex.m.mKey.ky = nn
    return nn
endProcedure mAddK1

/*--- put value at Ky if it exists otherwise add the node -----------*/
mPut: procedure expose m.
parse arg m, Ky, val
    if symbol('m.mIndex.m.mKey.Ky') == 'VAR' then do
        ch = m.mIndex.m.mKey.Ky
        m.ch = val
        return ch
        end
    else do
        return mAddK1(m, Ky, val)
        end
    return
endProcedure mPut

/*--- return the child of m at the given Ky, '' if not exists -------*/
mAtK1: procedure expose m.
parse arg m, ky
    if symbol('m.mIndex.m.mKey.ky') == 'VAR' then
        return m.mIndex.m.mKey.ky
    else
        return ''
endProcedure mAtK1

/*--- return the value of the child at Ky, fail if not exists -------*/
mVaAtK1: procedure expose m.
parse arg m, Ky
    if symbol('m.mIndex.m.mKey.Ky') ^== 'VAR' then
        call err 'no Ky' Ky 'at node' m
    ch = m.mIndex.m.mKey.Ky
    return m.ch
endProcedure mVaAtK1

/*--- return the value of the first defined ky in the list of nodes
      def if ky isn't defined ---------------------------------------*/
mFirst: procedure expose m.
parse arg Ky, def
    do ax=3 to arg()
        m = arg(ax)
        if symbol('m.mIndex.m.mKey.Ky') == 'VAR' then do
            ch = m.mIndex.m.mKey.Ky
            return m.ch
            end
        end
    return def
endProcedure mFirst

/*--- return the child at sequenceNo seq of node m -------------------*/
mAtSq: procedure expose m.
parse arg m, seq
    if symbol('m.m.seq') ^== 'VAR' then
        return ''
    else
        return m'.'seq
endProcedure mAtSq

/*--- remove all or all after nwSz children --------------------------*/
mRemCh: procedure expose m.
parse arg pa, nwSz
    if nwSz = '' then
        nwSz = 0
    do cx=nwSz+1 to mSize(pa)
        ch = pa'.'cx
        call mRemCh ch
        ky = m.mKey.ch
        drop m.mIndex.pa.mKey.ky m.mKey.ch m.ch m.ch.0
        end
    m.pa.0 = nwSz
    return pa
endProcedure mRemCh

/*--- add to m.dst a (sub)tree of m.src.* ----------------------------*/
mAddTree: procedure expose m.
parse arg dst, src, begX, endX
    if begX = '' then
        begX = 1
    if endX = '' then
        endX = mSize(src)
    do sx=begX to endX
        sCh = src'.'sx
        if symbol('m.mKey.sCh') ^= 'VAR' then do
            dCh = mAddNd(dst, m.sCh)
            end
        else do
            ky = m.mKey.sCh
            if symbol('m.mIndex.src.mKey.ky') ^= 'VAR' then
                dCh = mAddKy(dst, ky, m.sCh)
            else
                dCh = mAddK1(dst, ky, m.sCh)
            end
        call mAddTree dCh, sCh
        end
    return dst
endProcedure mAddTree

/*--- show from one node everything that is defined ------------------*/
mShowNd: procedure expose m.
parse arg m
    pa = mPar(m)
    t = 'node' m 'pa='pa
    if symbol('m.m') == 'VAR' then
        t = t 'va='m.m
    if symbol('m.m.0') == 'VAR' then
        t = t 'size='m.m.0
    if symbol('m.mKey.m') == 'VAR' then do
        ky = m.mKey.m
        t = t 'ky='ky
        if symbol('m.mIndex.pa.mKey.ky') == 'VAR' then
            t = t 'index='m.mIndex.pa.mKey.ky
        end
    say t
    return
endProcedure mShowNd

/*--- show the tree at m recursively ---------------------------------*/
mShow: procedure expose m.
parse arg m, lv
    if lv = '' then
        lv = 0
    t = left('', lv)m
    if symbol('m.mKey.m') == 'VAR' then do
        ky = m.mKey.m
        pa = mPar(m)
        if symbol('m.mIndex.pa.mKey.ky') == 'VAR' then
            t= t ky '>'
        else
            t= t ky '='
        end
    say t strip(m.m, 't')
    do cx=1 to mSize(m)
        call mShow mAtSq(m, cx), lv+1
        end
    return
endProcedure treeShow

/* copy m end *********************************************************/
/* copy adrTso begin *************************************************/
/*--- send ggTsoCmd to tso, fail if rc <> 0 or not listed in ggRet ---*/
adrTso:
    parse arg ggTsoCmd, ggRet
    address tso ggTsoCmd
    if rc == 0                     then return 0
    else if ggRet == '*'           then return rc
    else if wordPos(rc, ggRet) > 0 then return rc
    else
        call err 'adrTso rc' rc 'for' ggTsoCmd
return /* end adrTso */
/*--- format dsn from tso format to jcl format -----------------------*/
dsn2jcl: procedure
parse arg dsn ., addPrefix
    if left(dsn,1) = "'" then
        return strip(dsn, 'b', "'")
    else if sysvar('SYSPREF') = '' | addPrefix = 0 then
        return dsn
    else
        return sysvar('SYSPREF')'.'dsn
endProcedure dsn2Jcl

/*--- format dsn from jcl format to tso format -----------------------*/
jcl2dsn: procedure
parse arg dsn .
    return "'"dsn"'"
endProcedure jcl2dsn

dsnSetMbr: procedure
parse arg dsn, mbr
     bx = pos('(', dsn)
     if bx > 0 then
         dsn = strip(left(dsn, bx-1))
     if mbr <> '' then
         dsn = dsn'('strip(mbr)')'
     return dsn
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))
endProcedure dsnGetMbr
/**********************************************************************
    io: read or write a dataset with the following callsequences:
        read:  readDDBegin, readDD*,  readDDEnd
        write: writeBegin,  writeDD*, writeEnd

        readDD returns true if data read, false at eof
***********************************************************************/

/*--- prepare reading from a DD --------------------------------------*/
readDDBegin: procedure
return /* end readDDBegin */

/*--- read from DD ggDD into ggSt, return false at eof ---------------*/
readDD:
    parse arg ggDD, ggSt, ggCnt
    if ggCnt = '' then
        ggCnt = 100
    call adrTso 'execio' ggCnt 'diskr' ggDD '(stem' ggSt')', 2
    return (value(ggSt'0') > 0)
return /* end readDD */

/*--- finish reading DD  ggDD ----------------------------------------*/
readDDEnd: procedure
    parse arg ggDD
    call adrTso 'execio 0 diskr' ggDD '(finis)'
return /* end readDDEnd */

/*--- prepare writing to DD ggDD -------------------------------------*/
writeDDBegin: procedure
    parse arg ggDD
                  /* ensure file is erased, if no records are written */
    call adrTso 'execio' 0 'diskw' ggDD '(open)'
return /* end writeDDBegin */

/*--- write to gg ggDD from stem ggSt, ggCnt records -----------------*/
writeDD:
    parse arg ggDD, ggSt, ggCnt
    if ggCnt == '' then
        ggCnt = value(ggst'0')
    call adrTso 'execio' ggCnt 'diskw' ggDD '(stem' ggSt')'
    return
endSubroutine writeDD

/*--- end writing to dd ggDD (close) --------------------------------*/
writeDDEnd: procedure
    parse arg ggDD
    call adrTso 'execio 0 diskw' ggDD '(finis)'
return /* end writeDDEnd */

/*--- alloc a dsn or a dd -------------------------------------------*/
dsnAlloc: procedure expose m.
parse upper arg spec, disp, dd
    m.dsnAlloc.dsn = ''
    if left(spec, 1) = '=' then
        return strip(substr(spec, 2))
    addPref = pos('~', spec) > 0
    if addPref then
        spec = strip(spec, 'b', '~')
    do wx=1 to 3
        w = word(spec, wx)
        if w = '.' then do
            wx = wx + 1
            leave
            end
        if w = '' then
            leave
        if wordPos(w, 'OLD SHR MOD NEW')>0 | abbrev(w, 'SYSO') then
            disp = w
        else if abbrev(w, 'DD(') then
            dd = substr(w, 4, length(w)-4)
        else if m.dsnAlloc.dsn = '' then
            m.dsnAlloc.dsn = dsn2jcl(w, addPref)
        else
            leave
        end
    if dd = '' then
        dd = 'DD' || ooNew()
    if disp = '' | (disp = 'OLD' & pos('(', dsn) > 0) then
        disp = 'SHR'
    if m.dsnAlloc.dsn <> '' then
        disp = disp "dsn('"m.dsnAlloc.dsn"')"
    call adrTso 'alloc dd('dd')' disp subword(spec, wx)
    return dd 'call adrTso "free dd('dd')";'
endProcedure dsnAlloc

readDSN:
parse arg ggDsnSpec, ggSt
    ggAlloc = dsnAlloc(ggDsnSpec, 'SHR', 'readDsN')
    call adrTso 'execio * diskr' word(ggAlloc, 1) '(stem' ggSt' finis)'
    interpret subword(ggAlloc, 2)
    return
endSubroutine readDsn

writeDSN:
parse arg ggDsnSpec, ggSt, ggCnt, ggSay
    if ggCnt == '' then
        ggCnt = value(ggst'0')
    ggAlloc = dsnAlloc(ggDsnSpec, 'OLD', 'readDsN')
    call adrTso 'execio' ggCnt 'diskw' word(ggAlloc, 1) ,
            '(stem' ggSt 'finis)'
    interpret subword(ggAlloc, 2)
    if ggSay == 1 | m.debug == 1 then
       say ggCnt 'records written to' ggDsnSpec
    return
endSubroutine writeDsn

/* copy adrTso end ****************************************************/
/* copy err begin ******************************************************
    messages, errorhandling,help
***********************************************************************/
/* caller should define err as follows ---------------------------------
   end call should define err ----------------------------------------*/

/*--- error routine: abend with message ------------------------------*/
errA:
    parse arg ggTxt, ggHist
    parse source . . ggS3 .                           /* current rexx */
    say 'fatal error in' ggS3':' ggTxt
    if ggHist ^== 1  then
        exit setRc(12)
    say 'divide by zero to show stack history'
    x = 1 / 0
endSubroutine errA

/*--- abend with Message after displaying help -----------------------*/
errHelp: procedure
parse arg ggMsg
    parse source . . ggS3 .                           /* current rexx */
    say 'fatal error in' ggS3':' ggMsg
    call help
    call err ggMsg
endProcedure errHelp

/*--- set rc for ispf: -------------------------------------------------
    if a cmd is run by ispStart, its RC is ignored,
         but ISPF passes the value of the shared varible 3IspfRc
         back as return code
----------------------------------------------------------------------*/
setRc: procedure
parse arg zIspfRc
    if sysVar('sysISPF') = 'ACTIVE' then do
        say 'exitRc setting zIspfRc='zIspfRc
        address ispExec vput 'zIspfRc' shared
        end
    return zIspfRc
endProcedure setRc

/*--- output a trace message if m.trace is set -----------------------*/
trc: procedure expose m.
parse arg msg
    if m.trace == 1 then
        say 'trc:' msg
    return
endProcedure trc

/*--- quote string txt using quoteChar qu ("""" ==> ") ---------------*/
quote: procedure
parse arg txt, qu
    if qu = '' then
        qu = '"'
    res = qu
    ix = 1
    do forever
        qx = pos(qu, txt, ix)
        if qx = 0 then
            return res || substr(txt, ix) || qu
        res = res || substr(txt, ix, qx-ix) || qu || qu
        ix = qx + length(qu)
        end
endProcedure quote

/*--- return current time and cpu usage ------------------------------*/
showtime: procedure
return time() time('E') sysvar('syscpu') /* sysvar('syssrv') */

/--- display the first comment block of the source as help -----------*/
help: procedure
    parse source . . s3 .
    say right(' help for rexx' s3, 79, '*')
    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
    say right(' end help for rexx' s3, 79, '*')
    return 4
endProcedure help
/* copy err end   *****************************************************/