zOs/REXX/TSTALL

/* copy tstAll begin  ************************************************/
tstAll: procedure expose m.
    say 'tstAll' m.myWsh m.myVers
    call tstBase
    call tstComp
    call tstDiv
    if m.err_os = 'TSO' then do
        call tstZos
        call tstTut0
        end
    call tstTimeTot
    return 0
endProcedure tstAll

/*--- with also the slow tests --------------------------------------*/
tstAlLong: procedure expose m.
    call tstIni
    m.tst_long = 1
    return tstAll()
endProcedure tstAll
/****** tstZos *******************************************************/
tstZOs:
    call tstTime
    call tstTime2Tst
    call tstII
    call sqlIni
    call tstSqlRx
    call tstSql
    if m.tst_csmRZ \== '' then do
        call tstSqlCsm
        call tstSqlWsh
        call tstSqlWs2
        end
    call scanReadIni
    call tstSqlCall
    call tstSqlC
    call tstSqlCsv
    call tstSqlRxUpd
    call tstSqlUpd
    call tstSqlUpdPre
    call tstSqlE
    call tstSqlB
    call tstSqlO
    call tstSqlO1
    call tstSqlO2
    call tstSqlStmt
    call tstSqlStmts
    call tstSqlUpdComLoop
    call tstSqlS1
    call tstSqlFTab
    call tstSqlFTab2
    call tstSqlFTab3
    call tstSqlFTab4
    call tstSqlFTab5
    call tstsql4obj
    call tstdb2Ut
    call tstMain
    call tstHookSqlRdr
    call tstCsmExWsh
    call tstTotal
    return
endProcedure tstZOs
/*--- manualTest for csi --------------------------------------------*/
tstCsi: procedure expose m.
    if 0 then do
        call lmd 'A540769.*K'
        call tstCsiCla 'A540769.WK.REXX'
        call tstCsiCla 'A540769.AAA.DATASETS'
        call tstCsiCla 'A540769.RRR.DATASETS'
        end
    if 1 then do
        call tstCsiOpNx 'A540769.WK.*E*'
        call tstCsiOpNx 'A540769.AAA.DATASETS'
        call tstCsiOpNx 'A540769.RRR.DATASETS'
        end
    if 1 then do
        call tstCsiNxCl 'A540769.WK.**'
        call tstCsiNxCl 'DSN.**'
        call tstCsiNxCl 'DP4G.**'
        end
    return

tstCsiOpNx: procedure expose m.
parse arg ds
    m = 'NUE123'
    s = 'res89'
    flds = 'devtyp volser mgmtclas comudsiz NOBYTTRK UDATASIZ HARBA'
    say 'csiOpen' ds
    call csiOpen m, ds, flds
    do while csiNext(m, s)
        say m.s     'dev' c2x(m.s.devTyp) ,
                    'vol' m.s.volSer 'cla' m.s.mgmtclas,
                    'comuDsiz' m.s.comuDsiz 'noBytTrk' m.s.noBytTrk,
                    'udatasiz' c2x(m.s.udatasiz) ,
                    'harba' c2x(m.s.harba)
        end
    return

tstCsiNxCl: procedure expose m.
parse arg ds
    m = 'ABC123'
    s = 'efg89'
    flds = 'devtyp volser mgmtclas'
    say 'csiOpen' ds
    call csiOpen m, ds, flds
    say timing() 'begin'
    do i=1 while csiNext(m, s)
        nn = csiArcTape(m.s.volser, m.s.mgmtClas, m.s.devtyp, m.s)
/*      oo = csiCla(strip(m.s))
        if oo <> nn then
            say nn '<>' oo m.s
 */     if i // 1000 = 0 then
            say timing() i nn m.s
        end
    say timing() (i-1) nn m.s
    return
endProcedure tstCsiNxCl

tstMbrList: procedure expose m.
/*
$=/tstMbrList/
    ### start tst tstMbrList ##########################################
    #noPds: -99 mbrs in A540769.TMP.TST.MBRLIST
    #1: 1 mbrs in A540769.TMP.TST.MBRLIST
    1 EINS
    #0: 0 mbrs in A540769.TMP.TST.MBRLIST
    #4: 4 mbrs in A540769.TMP.TST.MBRLIST
    1 DREI
    2 FUENF
    3 VIER
    4 ZWEI
    #*IE*: 3 mbrs in A540769.TMP.TST.MBRLIST(*IE*)
    1 IE
    2 NNNIE
    3 VIER
    #*_IE*: 2 mbrs in A540769.TMP.TST.MBRLIST(*?IE*)
    1 NNNIE
    2 VIER
$/tstMbrList/
*/
    call tst t, 'tstMbrList'
 /* call tstMbrList1 "RZ2/A540769.WK.REXX(*DA?*)"  */
    pds = tstFileName('MbrList', 'r')
    da.1 = '2ine eins'
    call tstMbrList1 pds, '#noPds'
    call writeDsn pds'(eins) ::f', da., 1
    call tstMbrList1 pds, '#1'
    call adrTso "delete '"pds"(eins)'"
    call tstMbrList1 pds, '#0'
    call writeDsn pds'(zwei) ::f', da., 1
    call writeDsn pds'(drei) ::f', da., 1
    call writeDsn pds'(vier) ::f', da., 1
    call writeDsn pds'(fuenf) ::f', da., 1
    call tstMbrList1 pds, '#4'
    call writeDsn pds'(ie) ::f', da., 1
    call writeDsn pds'(nnnie) ::f', da., 1
    call tstMbrList1 pds"(*IE*)", '#*IE*'
    call tstMbrList1 pds"(*?IE*)", '#*_IE*'
    call adrTso "delete '"pds"'"
    call tstEnd t
    return
endProcedure tstMbrList
tstMbrList1: procedure expose m.
parse arg pds, txt
    call tstOut t, txt':' mbrList(tstMbrList, pds) 'mbrs in' pds
    do mx=1 to m.tstMbrList.0
        call tstOut t, mx m.tstMbrList.mx
        end
    return
endProdecure tstMbrList1
/****** tstDiv *******************************************************/
tstDiv:
    call tstSort
    call tstMat
    call tstMatch
    call tstTotal
    return
endProcedure tstDiv


tstSort: procedure expose m.
    call tstSortComp
    call tstSortComp '<<='
    call tstSortComp 'm.aLe <<= m.aRi'
    call tstSortComp 'if 1 then cmp = m.aLe <<= m.aRi;else call err sd'
    return
endProcedure tstSort

tstSortComp: procedure expose m.
parse arg cmp
/*
$=/tstSort/
    ### start tst tstSort #############################################
    sort 29  c ACHT DREI DREIZEHN EINS ELF FUENF M.I.25 M.I.26 M.I.27 M+
    ..I.29 NEUN SECHS SIEBEN VIER VIERZEHN ZEHN ZWEI ZWOELF 0 1 1 1 2 2+
    . 3 3 4 4
    sort 22  c ACHT DREIZEHN ELF M.I.25 M.I.26 M.I.27 M.I.29 NEUN VIERZ+
    EHN ZEHN ZWOELF 0 1 1 1 2 2 3 3 4 4
    sort 15  c M.I.25 M.I.26 M.I.27 M.I.29 0 1 1 1 2 2 3 3 4 4
    sort 8  c M.I.25 M.I.26 M.I.27 M.I.29 0 1 1
    sort 1  M.I.29
    sortWords(also als a 05 4 1e2, cmp) a als also 05 1e2 4
    sortWords(also als a 05 4, cmp) a als also 05 4
    sortWords(also als a 05, cmp) a als also 05
    sortWords(also als a, cmp) a als also
    sortWords(also als, cmp) als also
    sortWords(also, cmp) also
    sortWords(, cmp) .
    sortWords(also als a 05 4 1e2, <) a als also 4 05 1e2
    sortWords(also als a 05 4 1e2, >) 1e2 05 4 also als a
$/tstSort/ */
/*
$=/tstSortAscii/
    ### start tst tstSortAscii ########################################
    sort 29  0 1 1 1 2 2 3 3 4 4 ACHT DREI DREIZEHN EINS ELF FUENF M.I.+
    25 M.I.26 M.I.27 M.I.29 NEUN SECHS SIEBEN VIER VIERZEHN ZEHN ZWEI Z+
    WOELF c
    sort 22  0 1 1 1 2 2 3 3 4 4 ACHT DREIZEHN ELF M.I.25 M.I.26 M.I.27+
    . M.I.29 NEUN VIERZEHN ZEHN ZWOELF c
    sort 15  0 1 1 1 2 2 3 3 4 4 M.I.25 M.I.26 M.I.27 M.I.29 c
    sort 8  0 1 1 M.I.25 M.I.26 M.I.27 M.I.29 c
    sort 1  M.I.29
$/tstSortAscii/ */
    say '### start with comparator' cmp '###'
    if m.err_os == 'LINUX' then
        call tst t, "tstSortAscii"
    else
        call tst t, "tstSort"
    call mAdd mCut(i, 0), eins, zwei, drei, vier, fuenf, sechs,
        ,sieben, acht, neun, zehn, elf, zwoelf, dreizehn, vierzehn
    call mAdd i, 1, 2, 3, 4, 4, 3, 2, 1, 0, 1,
        , 'M.I.25', 'M.I.26', 'M.I.27', 'c', 'M.I.29'
    do yy = m.i.0 by -1 to 1

        do x = 0 to yy
            m.i.0 = x
            call sort i, o, cmp
            m = ''
            la = ''
            if x <> m.o.0 then
                call err 'size mismatch' x '<>' m.o.0
            do y=1 to m.o.0
                m = m m.o.y
                if \ (la << m.o.y) then
                    call err 'sort mismatch' yy x y '\' la '<<' m.o.y
                end
            end
        if yy // 7 = 1 then
           call tstOut t, 'sort' yy m
        do x = 2 to yy
            x1 = x-1
            m.i.x1 = m.i.x
            end
        end
    wi = 'also als a 05 4 1e2'
    do l=words(wi) by -1 to 0
        call tstOut t, 'sortWords('subWord(wi, 1, l)', cmp)' ,
                        sortWords(subWord(wi, 1, l), cmp)
        end
    call tstOut t, 'sortWords('wi', <)' sortWords(wi, '<')
    call tstOut t, 'sortWords('wi', >)' sortWords(wi, '>')
    call tstEnd t
    return
endProcedure tstSort
tstMatch: procedure expose m.
/*
$=/tstMatch/
    ### start tst tstMatch ############################################
    match(eins, e?n*) 1 1 2,i,s trans(E?N*) EiNs
    match(eins, eins) 1 1 0 trans(EINS) EINS
    match(e1nss, e?n*) 1 1 2,1,ss trans(?*) 1ss
    match(eiinss, e?n*) 0 0 -9 trans(E?N*) .
    match(einss, e?n *) 0 0 -9 trans(E?N *) .
    match(ein s, e?n *) 1 1 2,i,s trans(E?N *) EiN s
    match(ein abss  , ?i*b*) 1 1 3,e,n a,ss   trans(?I*B*) eIn aBss  .
    match(ein abss wie gehtsssxdirx und auch , ) 0 0 -9 trans() .
    match(ies000, *000) 1 1 1,ies trans(*000) ies000
    match(xx0x0000, *000) 1 1 1,xx0x0 trans(*000) xx0x0000
    match(000x00000xx, 000*) 1 1 1,x00000xx trans(000*) 000x00000xx
    match(000xx, *0*) 1 1 2,00,xx trans(ab*cd*ef) ab00cdxxef
    match(abcdef, *abcdef*) 1 1 2,, trans(*ABCDEF*) ABCDEF
    match(abcdef, **abcdef***) 1 1 5,,,,, trans(**ABCDEF***) ABCDEF
    match(abcdef, *cd*) 1 1 2,ab,ef trans(*CD*) abCDef
    match(abcdef, *abc*def*) 1 1 3,,, trans(*ABC*DEF*) ABCDEF
    match(abcdef, *bc*e*) 1 1 3,a,d,f trans(*BC*E*) aBCdEf
    match(abcdef, **bc**ef**) 1 1 6,a,,d,,, trans(**BC**EF**) aBCdEF
$/tstMatch/
*/
    call tst t, "tstMatch"
    call tstOut t, tstMatch1('eins', 'e?n*'                         )
    call tstOut t, tstMatch1('eins', 'eins'                         )
    call tstOut t, tstMatch1('e1nss', 'e?n*', '?*'                  )
    call tstOut t, tstMatch1('eiinss', 'e?n*'                       )
    call tstOut t, tstMatch1('einss', 'e?n *'                       )
    call tstOut t, tstMatch1('ein s', 'e?n *'                       )
    call tstOut t, tstMatch1('ein abss  ', '?i*b*'                  )
    call tstOut t, tstMatch1('ein abss wie gehtsssxdirx und auch ' )
    call tstOut t, tstMatch1('ies000', '*000'                       )
    call tstOut t, tstMatch1('xx0x0000', '*000'                     )
    call tstOut t, tstMatch1('000x00000xx', '000*'                  )
    call tstOut t, tstMatch1('000xx', '*0*', 'ab*cd*ef'             )
    call tstOut t, tstMatch1('abcdef', '*abcdef*'                   )
    call tstOut t, tstMatch1('abcdef', '**abcdef***'                )
    call tstOut t, tstMatch1('abcdef', '*cd*'                       )
    call tstOut t, tstMatch1('abcdef', '*abc*def*'                  )
    call tstOut t, tstMatch1('abcdef', '*bc*e*'                     )
    call tstOut t, tstMatch1('abcdef', '**bc**ef**'                 )
    call tstEnd t
return

tstMatch1:
parse arg w, m, m2
    r = 'match('w',' m')' match(w, m) matchVars(w, m, vv) m.vv.0
    do x=1 to m.vv.0
        r = r','m.vv.x
        end
    if m2 = '' then
        m2 = translate(m)
    r = r 'trans('m2')' matchRep(w, m, m2)
    return r
endProcedure tstMatch1

tstIntRdr: procedure expose m.
    i.1 = "//A540769J JOB (CP00,KE50),'DB2 REO',"
    i.2 = "//         MSGCLASS=T,TIME=1440,"
    i.3 = "//         NOTIFY=&SYSUID,REGION=0M,SCHENV=DB2"
    i.4 = "//*MAIN CLASS=LOG"
    i.5 = "//S1       EXEC PGM=IEFBR14"
    call writeDsn 'RR2/intRdr', i., 5, 1
    return
endProcedure tstIntRdr

tstII: procedure expose m.
/*
$=/tstII/
    ### start tst tstII ###############################################
    iiDs(org)         ORG.U0009.B0106.MLEM43
    iiDs(db2)         DSN.DB2
    iiRz2C(RZ2)       2
    *** err: no key=R?Y in II_RZ2C
    iiRz2C(R?Y)       0
    iiRz2C(RZY)       Y
    iiDbSys2C(de0G)   E
    *** err: no key=D??? in II_DB2C
    iiDbSys2C(d???)   0
    iiDbSys2C(DBOF)   F
    iiSys2RZ(S27)     RZ2
    iiMbr2DbSys(DBP5) DVBP
    ii_rz             RZX RZY RZZ RQ2 RR2 RZ2 RZ4
    ii_rz2db.rzx      DE0G DEVG DX0G DPXG
    rr2/dvbp    RR2 R p=R d=RZ2, db DVBP P 1
    iiixPut 1: RZ2 2 p=B d=RZ2, db DBOF F 0
    iiixPut 1: RZ2 2 p=B d=RZ2, db DVBP P 1
    iiixPut 1: RZ2 2 p=B d=RZ2, db DP2G Q 0
    *** err: no key=M6R in II_MBR2DB
    errHan=======  mbr2DbSys(m6r?) 0
    errHandlerPush Mbr2DbSys(m7r?) ?no?dbSys?
    *** err: no key=M8R in II_MBR2DB
    errHandlerPop  Mbr2DbSys(m8r?) 0
$/tstII/
*/
    call tst t, 'tstII'
    call tstOut t, 'iiDs(org)        '  iiDs('oRg')
    call tstOut t, 'iiDs(db2)        '  iiDs(db2)
    call tstOut t, 'iiRz2C(RZ2)      '  iiRz2C(RZ2)
    call tstOut t, 'iiRz2C(R?Y)      '  iiRz2C(R?Y)
    call tstOut t, 'iiRz2C(RZY)      '  iiRz2C(RZY)
    call tstOut t, 'iiDbSys2C(de0G)  '  iiDbSys2C('de0G')
    call tstOut t, 'iiDbSys2C(d???)  '  iiDbSys2C('d???')
    call tstOut t, 'iiDbSys2C(DBOF)  '  iiDbSys2C('DBOF')
    call tstOut t, 'iiSys2RZ(S27)    '  iiSys2RZ(S27)
    call tstOut t, 'iiMbr2DbSys(DBP5)'  iiMbr2DbSys(DBP5)
    call tstOut t, 'ii_rz            '  m.ii_rz
    call tstOut t, 'ii_rz2db.rzx     '  m.ii_rz2db.rzx
    call pipeIni
    call iiPut 'rr2/ DvBp  '
    call tstOut t, 'rr2/dvbp   ' ,
             vGet('rz') vget('rzC') 'p='vget('rzP') 'd='vget('rzD'),
             || ', db' vGet('dbSys') vGet('dbSysC') vGet('dbSysElar')
    w1 = wordPos('RZ2/DBOF', m.ii_rzDb)
    do wx=w1 to w1+2
        call tstOut t, 'iiixPut' iiIxPut(wx)':' ,
             vGet('rz') vget('rzC') 'p='vget('rzP') 'd='vget('rzD'),
             || ', db' vGet('dbSys') vGet('dbSysC') vGet('dbSysElar')
        end
    call tstOut t, "errHan=======  mbr2DbSys(m6r?)" iiMbr2DbSys('m6r?')
    call errHandlerPushRet "?no?dbSys?"
    call tstOut t, "errHandlerPush Mbr2DbSys(m7r?)" iiMbr2DbSys('m7r?')
    call errHandlerPop
    call tstOut t, "errHandlerPop  Mbr2DbSys(m8r?)" iiMbr2DbSys('m8r?')
    call tstEnd t
    return
endProcedure tstII

tstTime2tst: procedure expose m.
/*
$=/tstTime2tst/
    ### start tst tstTime2tst #########################################
    2015-05-13-23.45.57.987654 ==> 735730.99025448673611 ==> 2015-05-13+
    -23.45.57.987654 1
    1956-04-01-23.59.59.999999 ==> 714139.99999999998843 ==> 1956-04-01+
    -23.59.59.999999 1
    2016-02-29-12.34.56.789087 ==> 736022.52426839221065 ==> 2016-02-29+
    -12.34.56.789087 1
    1567-08-23-19.59.59.999999 ==> 572203.83333333332176 ==> 1567-08-23+
    -19.59.59.999999 1
$/tstTime2tst/
*/
   call tst t, 'tstTime2tst'
   l = '2015-05-13-23.45.57.987654 1956-04-01-23.59.59.999999' ,
       '2016-02-29-12.34.56.789087 1567-08-23-19.59.59.999999'
   do lx=1 to 4
       v = word(l, lx)
       w = timeDays2tst(timestamp2days(v))
       call tstOut t, v '==>' timestamp2days(v) '==>' w (v = w)
       end
   call tstEnd t
   return
endProcedure tstTime2tst

tstTime: procedure
/*         Winterzeit dez 2011
$=/tstTime/
    ### start tst tstTime #############################################
    05-28-00.00 2days  735745
    05-28-04.00 2days  735745.16666666666667
    05-28-21.00 2days  735745.9
    05-29-00.00 2days  735746
    16-05-28-00 2days  736111
    16...12 - 15...06  366.25000000000000
    2016-05-28-12.23.45            .
    2016-05-28-12-23.45            bad timestamp 2016-05-28-12-23
    2016.05-28-12.23.45            bad timestamp 2016.05-28-12.23
    2016-05-28-12.23.45.987654     .
    2016-0b-28-12.23.45            bad timestamp 2016-0b-28-12.23
    2016-05-28-12.23.45.9876543    bad timestamp 2016-05-28-12.23
    2016-05-28-12.23.45.98-654     bad timestamp 2016-05-28-12.23
    2016-00-28-12.23.45            bad month in timestamp 2016-00
    2016-05-28-13.23.45            .
    2016-15-28-12.23.45            bad month in timestamp 2016-15
    2016-05-31-12.23.45            .
    2016-04-31-13.23.45            bad day in timestamp 2016-04-3
    2015-04-30-12.23.45            .
    2016-02-30-12.23.45            bad day in timestamp 2016-02-3
    2016-02-29-13.23.45            .
    2015-02-29-12.23.45            bad day in timestamp 2015-02-2
    2016-07-30-25.00.00            bad hour in timestamp 2016-07-
    2016-04-07-24.00.00.0          .
    2015-02-19-24.00.01            bad hour in timestamp 2015-02-
    Achtung: output haengt von Winter/SommerZ & LeapSecs ab
    stckUnit    = 0.000000000244140625
    timeLeap    = 00000018CBA80000 = 106496000000 =        26.000 secs
    timeZone    = 00000D693A400000 = 14745600000000 =   3600.000 secs
    timeUQZero  = 207090001374976
    timeUQDigis = 35 digits ABCDEFGHIJKLMNOPQRSTUVWXYZ012345678
    2jul(2011-03-31-14.35.01.234567)  11090
    Lrsn2TAI10(00C5E963363741000000) 2010-05-01-10.35.20.789008
    Lrsn2Lzt(00C5E963363741000000) 2010-05-01-11.34.54.789008
    TAI102Lrsn(2011-03-31-14.35.01.234567) 00C78D87B86E38700000
    lzt2Lrsn(2011-03-31-14.35.01.234567) 00C78D7A67FFA0700000
    Lrsn2TAI10(TAI102Lrsn(2011-03-31-14.35.01.234567) +
    2011-03-31-14.35.01.234567
    TAI102Lrsn(Lrsn2TAI10(00C5E963363741000000) 00C5E963363741000000
    Lrsn2LZt(LZt2Lrsn(2011-03-31-14.35.01.234567) 2011-03-31-14.35.01.2+
    34567
    LZt2Stc(Lrsn2LZt(00C5E963363741000000) 00C5E963363741000000
    Lrsn2uniq(00C5E963363741000000) CTNR6S7T back 00C5E963363740000000
    Lrsn2LZt(LZt2Lrsn(2051-10-31-14.35.01.234567) 2051-10-31-14.35.01+
     ..234567
    Lrsn2TAI10(01010000000000000000) 2043-04-09-14.36.53.414912
$/tstTime/
Winterzeit
timeZone    = 00000D693A400000 = 14745600000000 =   3600.000 secs
Lrsn2Lzt(00C5E963363741000000) 2010-05-01-11.34.54.789008
lzt2Lrsn(2011-03-31-14.35.01.234567) 00C78D7A67FFA0700000
Sommerzeit
timeZone    = 00001AD274800000 = 29491200000000 =   7200.000 secs
Lrsn2Lzt(00C5E963363741000000) 2010-05-01-12.34.54.789008
lzt2Lrsn(2011-03-31-14.35.01.234567) 00C78D6CFEC560700000
*/
    call jIni
    call timeIni
    call tst t, 'tstTime'
    call out '05-28-00.00 2days ' timestamp2days('2015-05-28-00.00.00')
    call out '05-28-04.00 2days ' timestamp2days('2015-05-28-04.00.00')
    call out '05-28-21.00 2days ' timestamp2days('2015-05-28-21.36.00')
    call out '05-29-00.00 2days ' timestamp2days('2015-05-29-00.00.00')
    call out '16-05-28-00 2days ' timestamp2days('2016-05-28-00.00.00')
    call out '16...12 - 15...06 ' timestampDiff( '2016-05-28-12.23.45',
                                               , '2015-05-28-06.23.45')
    l = '2016-05-28-12.23.45 2016-05-28-12-23.45 2016.05-28-12.23.45',
       '2016-05-28-12.23.45.987654 2016-0b-28-12.23.45' ,
       '2016-05-28-12.23.45.9876543 2016-05-28-12.23.45.98-654' ,
       '2016-00-28-12.23.45 2016-05-28-13.23.45 2016-15-28-12.23.45',
       '2016-05-31-12.23.45 2016-04-31-13.23.45 2015-04-30-12.23.45',
       '2016-02-30-12.23.45 2016-02-29-13.23.45 2015-02-29-12.23.45',
       '2016-07-30-25.00.00 2016-04-07-24.00.00.0 2015-02-19-24.00.01'
    do lx=1 to words(l)
        call out left(word(l, lx), 30),
            strip(left(timestampCheck(word(l, lx)), 30), 't')
        end
    t1 = '2011-03-31-14.35.01.234567'
    t2 = '2051-10-31-14.35.01.234567'
    s1 = timeLrsnExp('C5E963363741')
    s2 = timeLrsnExp('0101')
    call out 'Achtung: output haengt von Winter/SommerZ & LeapSecs ab'
    numeric digits 15
    call out 'stckUnit    =' m.time_StckUnit
    call out 'timeLeap    =' d2x(m.time_Leap,16) '=' m.time_Leap ,
                   '=' format(m.time_Leap * m.time_StckUnit,9,3) 'secs'
    call out 'timeZone    =' d2x(m.time_Zone,16) '=' m.time_Zone,
                   '=' format(m.time_Zone * m.time_StckUnit,6,3) 'secs'
 /* call out "cvtext2_adr =" d2x(cvtExt2A, 8)  */
    call out 'timeUQZero  =' m.time_UQZero
    call out 'timeUQDigis =' ,
                    length(m.time_UQDigits) 'digits' m.time_UQDigits
    call out '2jul('t1') ' time2jul(t1)
    call out 'Lrsn2TAI10('s1')' timelrsn2TAI10(s1)
    call out 'Lrsn2Lzt('s1')' timeLrsn2Lzt(s1)
    call out 'TAI102Lrsn('t1')' timeTAI102Lrsn(t1)
    call out 'lzt2Lrsn('t1')' timeLzt2Lrsn(t1)
    call out 'Lrsn2TAI10(TAI102Lrsn('t1')' ,
          timeLrsn2TAI10(timeTAI102Lrsn(t1))
    call out 'TAI102Lrsn(Lrsn2TAI10('s1')' ,
        timeTAI102Lrsn(timelrsn2TAI10(s1))
    call out 'Lrsn2LZt(LZt2Lrsn('t1')' timeLrsn2LZt(timeLZt2Lrsn(t1))
    call out 'LZt2Stc(Lrsn2LZt('s1')'  timeLZt2Lrsn(timeLrsn2LZt(s1))
    call out 'Lrsn2uniq('s1')' timeLrsn2Uniq(s1) ,
                        'back' timeUniq2Lrsn(timeLrsn2Uniq(s1))
    call out 'Lrsn2LZt(LZt2Lrsn('t2')' timeLrsn2LZt(timeLZt2Lrsn(t2))
    call out 'Lrsn2TAI10('s2')' timelrsn2TAI10(s2)
    call tstEnd t
    return
endProcedure tstTime

tstMat: procedure expose m.
/*
$=/tstMat/
    ### start tst tstMat ##############################################
    .   0 sqrt  0 isPrime 0 nxPrime    3 permut 1 > 1 2 3 4 5
    .   1 sqrt  1 isPrime 0 nxPrime    3 permut 2 > 2 1 3 4 5
    .   2 sqrt  1 isPrime 1 nxPrime    3 permut 3 > 1 3 2 4 5
    .   3 sqrt  1 isPrime 1 nxPrime    3 permut 3 > 2 3 1 4 5
    .   4 sqrt  2 isPrime 0 nxPrime    5 permut 3 > 3 2 1 4 5
    .   5 sqrt  2 isPrime 1 nxPrime    5 permut 3 > 3 1 2 4 5
    .   6 sqrt  2 isPrime 0 nxPrime    7 permut 4 > 1 2 4 3 5
    .   7 sqrt  2 isPrime 1 nxPrime    7 permut 4 > 2 1 4 3 5
    .   8 sqrt  2 isPrime 0 nxPrime   11 permut 4 > 1 3 4 2 5
    .   9 sqrt  3 isPrime 0 nxPrime   11 permut 4 > 2 3 4 1 5
    .  10 sqrt  3 isPrime 0 nxPrime   11 permut 4 > 3 2 4 1 5
    .  11 sqrt  3 isPrime 1 nxPrime   11 permut 4 > 3 1 4 2 5
    .  12 sqrt  3 isPrime 0 nxPrime   13 permut 4 > 1 4 3 2 5
    .  13 sqrt  3 isPrime 1 nxPrime   13 permut 4 > 2 4 3 1 5
    .  14 sqrt  3 isPrime 0 nxPrime   17 permut 4 > 1 4 2 3 5
    .  15 sqrt  3 isPrime 0 nxPrime   17 permut 4 > 2 4 1 3 5
    .  16 sqrt  4 isPrime 0 nxPrime   17 permut 4 > 3 4 1 2 5
    .  17 sqrt  4 isPrime 1 nxPrime   17 permut 4 > 3 4 2 1 5
    .  18 sqrt  4 isPrime 0 nxPrime   19 permut 4 > 4 2 3 1 5
$/tstMat/
$/tstMat/
*/
    call tst t, 'tstMat'
    q = 'tst_Mat'
    do qx=1 to 20
        m.q.qx = qx
        end
    do i=0 to 18
        call permut q, i
        call tstOut t, right(i,4) 'sqrt' right(sqrt(i), 2) ,
        'isPrime' isPrime(i) 'nxPrime' right(nxPrime(i), 4) ,
            'permut' m.q.0 '>' m.q.1 m.q.2 m.q.3 m.q.4 m.q.5
        end
    call tstEnd t
    return
endProcedure tstMat

tstCsmExWsh: procedure expose m.
/*
new lines: 24
$=/tstCsmExWsh/
    ### start tst tstCsmExWsh #########################################
    --- sending v
    line eins aus <toRZ>
    csm_o1=[fEins=o1Feins =o1Val fZwei=o1   fZwei]
    csm_o2=[fEins=o2Feins =o2Value fZwei=o2,fwei, und  ]
    line vier end
    --- sending e
    line eins aus <toRZ>
    tstR: @tstWriteoV2 isA :TstCsmExWsh*3
    tstR:  .fEins = o1Feins
    tstR:  = o1Val
    tstR:  .fZwei = o1   fZwei
    tstR: @tstWriteoV4 isA :TstCsmExWsh*3
    tstR:  .fEins = o2Feins
    tstR:  = o2Value
    tstR:  .fZwei = o2,fwei, und  .
    line vier end
    --- sending f50
    line eins aus <toRZ>                                 .
    csm_o1=[fEins=o1Feins =o1Val fZwei=o1   fZwei]    .
    csm_o2=[fEins=o2Feins =o2Value fZwei=o2,fwei, ...]
    line vier end                                     .
$/tstCsmExWsh/
*/
    call csmIni
    call pipeIni
    call tst t, "tstCsmExWsh"
    call mAdd t.trans, m.tst_csmRz '<toRZ>'
    bi = jBuf("$$- 'line eins aus' sysvar(sysnode)" ,
     , "cc = classNew('n? TstCsmExWsh u f fEins v, v, f fZwei v')" ,
     , "$$. csv2o('csm_o1',cc, 'o1Feins,o1Val,o1   fZwei')" ,
     , "$$. csv2o('csm_o2',cc, 'o2Feins,o2Value,""o2,fwei, und  ""')" ,
             , "$$ line vier end")
    call out '--- sending v'
    call csmExWsh m.tst_csmRz, bi, 'v'
    ww = oNew(m.class_csmExWsh, m.tst_csmRz, bi, 'e')
    call out '--- sending e'
    call jWriteAll t, ww
    call out '--- sending f50'
    call csmExWsh  m.tst_csmRz, bi, 'f50'
    call tstEnd t
    return
endProcedure tstCsmExWsh

/****** tstSql *******************************************************/
tstSqlRx: procedure expose m.
/*
$=/tstSqlRx/
    ### start tst tstSqlRx ############################################
    *** err: SQLCODE = -204: A540769.SYSDUMMY IS AN UNDEFINED NAME
    .    e 1: sql = select * from sysdummy
    .    e 2: stmt = prepare s7 into :M.SQL.7.D from :src
    .    e 3: with into :M.SQL.7.D = M.SQL.7.D
    fetchA 1 ab=m.abcdef.123.AB=abc ef=efg
    fetchA 0 ab=m.abcdef.123.AB=abc ef=efg
    fetchB 1 ab=a cd=2 ef=--- ind=-1 gh=d ind=0
    fetchB 0 ab=a cd=2 ef=--- ind=-1 gh=d ind=0
    fetchC 1 a=a b=2 c=--- d=d
    fetchC 0 a=a b=2 c=--- d=d
    fetchBT 1 SYSTABLES
    fetchBT 0 SYSTABLES
    fetchBi 1 SYSINDEXES
    fetchBi 0 SYSINDEXES
$/tstSqlRx/ */
    call jIni
    call tst t, "tstSqlRx"
    call sqlConnect , 'e'
    cx = 7
    call sqlQuery cx, 'select * from sysdummy'
    call sqlQuery cx, "select 'abc' , 'efg'",
                         'from sysibm.sysDummy1',':m.dst.ab, :m.dst.ef'
    a = 'abcdef'
    b = 123
    drop m.a.b.ab m.a.b.ef
    do i=1 to 2
        call out 'fetchA' sqlFetch(cx, a || '.' || b) ,
            'ab=m.'a'.'||b'.'ab'='m.a.b.ab 'ef='m.a.b.ef
        end
    call sqlClose cx
    drop m.a.b.ab m.a.ab.ef a b c
    sql = "select 'a' a, 2 b, case when 1=0 then 1 else null end c",
                           ", case when 1=1 then 'd' else null end d",
                 "from sysibm.sysDummy1"
    call sqlQuery cx, sql, 'AB CD EF GH'
    st = 'abc.Def.123'
    drop m.st.ab m.st.cd m.st.ef m.st.ef.sqlInd m.st.gh m.st.gh.sqlInd
    do i=1 to 2
        call out 'fetchB' sqlFetch(cx, st) ,
           'ab='m.st.ab 'cd='m.st.cd 'ef='m.st.ef 'ind='m.st.ef.sqlInd,
                                     'gh='m.st.gh 'ind='m.st.gh.sqlInd
        end
    call sqlClose cx
    drop m.st.ab m.st.bc m.st.df m.st.df.sqlInd
    call sqlQuery cx, sql
    st = 'abc.Def.123'
    drop m.st.a m.st.b m.st.c m.st.d
    do i=1 to 2
        call out 'fetchC' sqlFetch(cx, st) ,
            'a='m.st.a 'b='m.st.b 'c='m.st.c 'd='m.st.d
        end
    drop m.st.a m.st.b m.st.c m.st.d
    call sqlClose cx
    drop m.st.1.a m.st.1.b m.st.1.c m.st.1.d  m.st.0
    call sqlQueryPrepare cx, "select name" ,
                        "from sysibm.sysTables" ,
                        "where creator = 'SYSIBM' and name = ?",':m.nm'
    call sqlQueryExecute cx, 'SYSTABLES'
    call out 'fetchBT' sqlFetch(cx) m.nm
    call out 'fetchBT' sqlFetch(cx) m.nm
    call sqlClose cx
    call sqlQueryExecute cx, 'SYSINDEXES'
    call out 'fetchBi' sqlFetch(cx) m.nm
    call out 'fetchBi' sqlFetch(cx) m.nm
    call tstEnd t
    call sqlDisconnect
    return
endProcedure tstSqlRx

tstSql: procedure expose m.
/*
$=/tstSql/
    ### start tst tstSql ##############################################
    *** err: SQLCODE = -204: A540769.SYSDUMMY IS AN UNDEFINED NAME
    .    e 1: sql = select * from sysdummy
    .    e 2: stmt = prepare s7 into :M.SQL.7.D from :src
    .    e 3: with into :M.SQL.7.D = M.SQL.7.D
    fetchA 1 ab=m.abcdef.123.AB=abc ef=efg
    fetchA 0 ab=m.abcdef.123.AB=abc ef=efg
    fetchB 1 ab=a cd=2 ef=--- ind=-1 gh=d ind=0
    fetchB 0 ab=a cd=2 ef=--- ind=-1 gh=d ind=0
    fetchC 1 a=a b=2 c=--- d=d
    fetchC 0 a=a b=2 c=--- d=d
    sql2St 1 st.0=1
    sql2St:1 a=a b=2 c=--- d=d
    sql2One a
    sql2One a=a b=2 c=--- d=d
    fetchBT 1 SYSTABLES
    fetchBT 0 SYSTABLES
    fetchBi 1 SYSINDEXES
    fetchBi 0 SYSINDEXES
$/tstSql/ */
    call jIni
    call tst t, "tstSql"
    call sqlConnect , 'e'
    cx = 7
    call sqlQuery cx, 'select * from sysdummy'
    call sqlQuery cx, "select 'abc' , 'efg'",
                        'from sysibm.sysDummy1', ':m.dst.ab, :m.dst.ef'
    a = 'abcdef'
    b = 123
    drop m.a.b.ab m.a.b.ef
    do i=1 to 2
        call out 'fetchA' sqlFetch(cx, a || '.' || b) ,
            'ab=m.'a'.'||b'.'ab'='m.a.b.ab 'ef='m.a.b.ef
        end
    call sqlClose cx
    drop m.a.b.ab m.a.ab.ef a b c
    sql = "select 'a' a, 2 b, case when 1=0 then 1 else null end c",
                           ", case when 1=1 then 'd' else null end d",
                 "from sysibm.sysDummy1"
    call sqlQuery cx, sql, 'AB CD EF GH'
    st = 'abc.Def.123'
    drop m.st.ab m.st.cd m.st.ef m.st.ef.sqlInd m.st.gh m.st.gh.sqlInd
    do i=1 to 2
        call out 'fetchB' sqlFetch(cx, st) ,
           'ab='m.st.ab 'cd='m.st.cd 'ef='m.st.ef 'ind='m.st.ef.sqlInd,
                                     'gh='m.st.gh 'ind='m.st.gh.sqlInd
        end
    call sqlClose cx
    drop m.st.ab m.st.bc m.st.df m.st.df.sqlInd
    call sqlQuery cx, sql
    st = 'abc.Def.123'
    drop m.st.a m.st.b m.st.c m.st.d
    do i=1 to 2
        call out 'fetchC' sqlFetch(cx, st) ,
            'a='m.st.a 'b='m.st.b 'c='m.st.c 'd='m.st.d
        end
    drop m.st.a m.st.b m.st.c m.st.d
    call sqlClose cx
    drop m.st.1.a m.st.1.b m.st.1.c m.st.1.d  m.st.0
    call out 'sql2St' sql2St(sql, st) 'st.0='m.st.0
    do i=1 to m.st.0
        call out 'sql2St:'i ,
            'a='m.st.i.a 'b='m.st.i.b 'c='m.st.i.c 'd='m.st.i.d
        end
    drop m.st.1.a m.st.1.b m.st.1.c m.st.1.d  m.st.0
    drop m.st.a m.st.b m.st.c m.st.d m.st.0
    call out 'sql2One' sql2One(sql, st)
    call out 'sql2One' ,
            'a='m.st.a 'b='m.st.b 'c='m.st.c 'd='m.st.d
    drop m.st.a m.st.b m.st.c m.st.d m.st.0
    call sqlQueryPrepare cx, "select name" ,
                        "from sysibm.sysTables" ,
                        "where creator = 'SYSIBM' and name = ?",':m.nm'
    call sqlQueryExecute cx, 'SYSTABLES'
    call out 'fetchBT' sqlFetch(cx) m.nm
    call out 'fetchBT' sqlFetch(cx) m.nm
    call sqlClose cx
    call sqlQueryExecute cx, 'SYSINDEXES'
    call out 'fetchBi' sqlFetch(cx) m.nm
    call out 'fetchBi' sqlFetch(cx) m.nm
    call tstEnd t
    call sqlDisconnect
    return
endProcedure tstSql

tstSqlCall: procedure expose m.
/*
$=/tstSqlCall/
    ### start tst tstSqlCall ##########################################
    set sqlid 0
    drop proc -204
    crea proc 0
    call -2 0
    resultSets 1 vars=3 2=-1 3=call-2 -2
    * resultSet 1  CUR NAME COLTYPE A2
    cur=cur2 name=NAME type=VARCHAR  len= a1= a2=call-2  a3=
    cur=cur2 name=CREATOR type=VARCHAR  len= a1= a2=call-2  a3=
    cur=cur2 name=TYPE type=CHAR     len= a1= a2=call-2  a3=
    call -1 0
    resultSets 1 vars=3 2=0 3=call-1 -1
    * resultSet 1  CUR NAME COLTYPE LENGTH A1
    cur=cur1 name=NAME type=VARCHAR  len=128 a1=call-1  a2= a3=
    call 0 0
    resultSets 0 vars=3 2=1 3=call0 0
    call 1 0
    resultSets 1 vars=3 2=2 3=call1 1
    * resultSet 1  CUR NAME COLTYPE LENGTH A1
    cur=cur1 name=NAME type=VARCHAR  len=128 a1=call1   a2= a3=
    call 2 0
    resultSets 2 vars=3 2=3 3=call2 2
    * resultSet 1  CUR NAME COLTYPE LENGTH A1
    cur=cur1 name=NAME type=VARCHAR  len=128 a1=call2   a2= a3=
    * resultSet 2  CUR NAME COLTYPE A2
    cur=cur2 name=NAME type=VARCHAR  len= a1= a2=call2   a3=
    cur=cur2 name=CREATOR type=VARCHAR  len= a1= a2=call2   a3=
    cur=cur2 name=TYPE type=CHAR     len= a1= a2=call2   a3=
    call 3 0
    resultSets 3 vars=3 2=4 3=call3 3
    * resultSet 1  CUR NAME COLTYPE LENGTH A1
    cur=cur1 name=NAME type=VARCHAR  len=128 a1=call3   a2= a3=
    * resultSet 2  CUR NAME COLTYPE A2
    cur=cur2 name=NAME type=VARCHAR  len= a1= a2=call3   a3=
    cur=cur2 name=CREATOR type=VARCHAR  len= a1= a2=call3   a3=
    cur=cur2 name=TYPE type=CHAR     len= a1= a2=call3   a3=
    * resultSet 3  CUR NAME A3
    rollback  0
$/tstSqlCall/ */
    call tst t, "tstSqlCall"
    prc = 'qz91WshTst1.proc1'
    c1 =  "from sysibm.sysColumns" ,
          "where tbCreator = 'SYSIBM' and tbName = 'SYSTABLES'" ,
          "order by colNo" ,
          "fetch first"
    call sqlConnect , 'e'
    call tstOut t, 'set sqlid' ,
        sqlUpdate(3, "set current sqlid = 'S100447'")
    call tstOut t, 'drop proc' sqlUpdate(3, 'drop procedure' prc)
    call sqlCommit
    call tstOut t, 'crea proc' sqlUpdate(3, 'create procedure' prc ,
          "(in a1 varchar(20), inOut cnt int, out res varchar(20))"  ,
          "version v1 not deterministic reads sql data"              ,
          "dynamic result sets 3"                                    ,
        "begin"                                                      ,
        "declare prC1 cursor with return for"                        ,
          "select 'cur1' cur, name, colType, length, left(a1, 7) a1" ,
          c1 "1 rows only;"                                          ,
        "declare prC2 cursor with return for"                        ,
          "select 'cur2' cur, name, colType, left(a1, 7) a2"         ,
          c1 "3 rows only;"                                          ,
        "declare prC3 cursor with return for"                        ,
          "select 'cur2' cur, name, left(a1, 7) a3"                  ,
          "from sysibm.sysTables where 1 = 0;"                       ,
        "if cnt >= 1 or cnt = -1 then open prC1; end if;"            ,
        "if cnt >= 2 or cnt = -2 then open prC2; end if;"            ,
        "if cnt >= 3 or cnt = -3 then open prC3; end if;"            ,
        "set res = strip(left(a1, 10)) || ' ' || cnt;"               ,
        "set cnt = cnt + 1;"                                         ,
        "end"                                                        )
    d = 'TST_sqlCall'
    do qx= -2 to 3
        call tstOut t, 'call' qx sqlCall(3,
             , "call" prc "(call"qx"," qx", '            ')")
        call tstOut t, 'resultSets' m.sql.3.resultSet.0,
                       'vars='m.sql.3.var.0 ,
                       '2='m.sql.3.var.2 '3='m.sql.3.var.3
        if m.sql.3.resultSet \== '' then
            do qy=1 until \ sqlNextResultSet(3)
                call tstOut t, '* resultSet' qy m.sql.3.fetchFlds
                m.d.length = ''
                m.d.colType = ''
                m.d.a1 = ''
                m.d.a2 = ''
                m.d.a3 = ''
                do while sqlFetch(3, d)
                    call tstOut t, 'cur='m.d.cur 'name='m.d.name ,
                      'type='m.d.colType 'len='m.d.length ,
                      'a1='m.d.a1 'a2='m.d.a2 'a3='m.d.a3
                    end
                call sqlClose 3
                end
        end
    call tstOut t, 'rollback ' sqlUpdate(3, 'rollback')
    call sqlDisconnect
    call tstEnd t
    return
endProcedure tstSqlCall

tstSqlCsm: procedure expose m.
/*
$=/tstSqlCsm/
    ### start tst tstSqlCsm ###########################################
    *** err: SQLCODE = -204: S100447.SYSDUMMY IS AN UNDEFINED NAME
    .    e 1: sql = select * from sysdummy
    .    e 2: sqlCsmExe RZZ/DE0G
    1 jRead .ab=abc, .ef=efg
    2 jRead .AB=a, .CD=2 .EF=---, .GH=d
$/tstSqlCsm/ */
    call pipeIni
    call tst t, "tstSqlCsm"
    call sqlConnect m.tst_csmRzDb, 'c'
    call jOpen sqlRdr('select * from sysdummy'), '<'
    f1 = 'ab'
    f2 = 'er'
    r =  jOpen(sqlRdr("select 'abc' , 'efg'",
                'from sysibm.sysDummy1', f1 f2), '<')
    a = 'abcdef'
    b = 123
    drop m.a.b.ab m.a.b.ef
    do while jRead(r)
        dst = m.r
        call out '1 jRead .ab='m.dst.f1', .ef='m.dst.f2
        end
    drop m.a.b.ab m.a.ab.ef a b c
    sql = "select 'a' a, 2 b, case when 1=0 then 1 else null end c",
                           ", case when 1=1 then 'd' else null end d",
                 "from sysibm.sysDummy1"
    r =  jOpen(sqlRdr(sql, 'AB CD EF GH'), '<')
    do while jRead(r)
        dst = m.r
        call out '2 jRead .AB='m.dst.AB', .CD='m.dst.CD ,
                         '.EF='m.dst.EF', .GH='m.dst.GH
        end
    st = 'abc.Def.123'
    call tstEnd t
    call sqlDisconnect
    return
endProcedure tstsqlCsm

tstSqlCSV: procedure expose m.
/*
$=/tstSqlCSV/
    ### start tst tstSqlCSV ###########################################
    NAME,CREATOR,MITCOM,MITQUO,MITNU,COL6
    SYSTABLES,SYSIBM  ,"a,b","a""b",1,8
    SYSTABLESPACE,SYSIBM  ,"a,b","a""b",---,8
    SYSTABLESPACESTATS,SYSIBM,"a,b","a""b",---,6
$/tstSqlCSV/ */
    call sqlConnect , 'r'
    call tst t, "tstSqlCSV"
    r = csv4ObjRdr(sqlRdr("select name, creator, 'a,b' mitCom",
         ", 'a""b' mitQuo" ,
         ", case when name='SYSTABLES' then 1 else null end mitNu" ,
         ",length(creator)" ,
              "from sysibm.sysTables" ,
              "where creator = 'SYSIBM' and name like 'SYSTABLES%'",
              "fetch first 3 rows only"))
    call pipeWriteAll r
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlCsv

tstSqlB: procedure expose m.
/*
$=/tstSqlB/
    ### start tst tstSqlB #############################################
    #jIn 1# select strip(name) "tb", strip(creator) cr
    #jIn 2# , case when name = 'SYSTABLES' then 1 else null end
    #jIn 3# from sysibm.sysTables
    #jIn 4# where creator = 'SYSIBM' and name like 'SYSTABLES%'
    #jIn 5# .
    #jIn 6# order by name
    #jIn 7# fetch first 3 rows only
    #jIn eof 8#
    dest1.fet: SYSTABLES SYSIBM 1
    dest2.fet: SYSTABLESPACE SYSIBM ---
    dest3.fet: SYSTABLESPACESTATS SYSIBM ---
$/tstSqlB/ */
    call pipeIni
    call tst t, "tstSqlB"
    cx = 9
    call sqlConnect , 'e'
    call jIni
    call mAdd mCut(t'.IN', 0),
      , 'select strip(name) "tb", strip(creator) cr' ,
      ,     ", case when name = 'SYSTABLES' then 1 else null end" ,
      ,   "from sysibm.sysTables" ,
      ,   "where creator = 'SYSIBM' and name like 'SYSTABLES%'", ,
      ,   "order by name",
      ,   "fetch first 3 rows only"
     call sqlQuery cx, in2Str(,' ')
     do qx=1 while sqlFetch(cx, 'dest'qx'.fet')
         dst = 'dest'qx'.fet'
         call out dst':' m.dst.tb m.dst.cr m.dst.col3
         drop m.dst.tb m.dst.cr m.dst.col3
         end
     call sqlClose cx
     call sqlDisconnect
     call tstEnd t
     return
endProcedure tstSqlB

tstSqlFTab: procedure expose m.
/*
$=/tstSqlFTab/
    ### start tst tstSqlFTab ##########################################
    UPDATESTATSTIME----------------NACTIVE------NPAGES-EXTENT-LOADRLAST+
    TIME--------------REORGLASTTIME--------------REORGINSERT-REORGDELET+
    E-REORGUPDATE-REORGUNCLUS-REORGDISORG-REORGMASSDE-REORGNEARIN-REORG+
    FARIND-STATSLASTTIME--------------STATSINSERT-STATSDELETE-STATSUPDA+
    TE-STATSMASSDE-COPYLASTTIME---------------COPYUPDATED-COPYCHANGES-C+
    OPYUPDATE-COPYUPDATETIME-------------I---DBID---PSID-PARTIT-INSTAN-+
    --SPACE-TOTALRO-DATASIZ-UNCOMPR-DBNAME-------NAME---------REORGCL-R+
    EORGSC-REORGHA-HASHLASTUS-DRI-L-STATS01-UPDATES-LASTDATACHANGE-----+
    ----------
    --- modified
    allg vorher                     others vorher
    db-------ts---------part---inst-UPDATESTATSTIME----------------NACT+
    IVE------NPAGES-EXTENT-LOADRLASTTIME--------------REORGLASTTIME----+
    ----------REORGINSERT-REORGDELETE-REORGUPDATE-REORGUNCLUS-REORGDISO+
    RG-REORGMASSDE-REORGNEARIN-REORGFARIND-STATSLASTTIME--------------S+
    TATSINSERT-STATSDELETE-STATSUPDATE-STATSMASSDE-COPYLASTTIME--------+
    -------COPYUPDATED-COPYCHANGES-COPYUPDATE-COPYUPDATETIME-----------+
    --I---DBID---PSID---SPACE-TOTALRO-DATASIZ-UNCOMPR-REORGCL-REORGSC-R+
    EORGHA-HASHLASTUS-DRI-L-STATS01-UPDATES-LASTDATACHANGE-------------+
    --
    db-------ts---------part---inst-UPDATESTATSTIME----------------NACT+
    IVE------NPAGES-EXTENT-LOADRLASTTIME--------------REORGLASTTIME----+
    ----------REORGINSERT-REORGDELETE-REORGUPDATE-REORGUNCLUS-REORGDISO+
    RG-REORGMASSDE-REORGNEARIN-REORGFARIND-STATSLASTTIME--------------S+
    TATSINSERT-STATSDELETE-STATSUPDATE-STATSMASSDE-COPYLASTTIME--------+
    -------COPYUPDATED-COPYCHANGES-COPYUPDATE-COPYUPDATETIME-----------+
    --I---DBID---PSID---SPACE-TOTALRO-DATASIZ-UNCOMPR-REORGCL-REORGSC-R+
    EORGHA-HASHLASTUS-DRI-L-STATS01-UPDATES-LASTDATACHANGE-------------+
    --
    allg nachher                    others nachher
    DBNAME                   INSTANCE                                  +
    .    NPAGES                                        REORGLASTTIME   +
    .                                   REORGUPDATES                   +
    .     REORGMASSDELETE                     STATSLASTTIME            +
    .                          STATSUPDATES                            +
    .           COPYUPDATEDPAGES                   COPYUPDATETIME      +
    .                PSID                   DATASIZE                REO+
    RGSCANACCESS            DRIVETYPE     UPDATESIZE
    .         NAME                   UPDATESTATSTIME                   +
    .                 EXTENTS                                          +
    .            REORGINSERTS                        REORGUNCLUSTINS   +
    .                  REORGNEARINDREF                                 +
    .   STATSINSERTS                        STATSMASSDELETE            +
    .                        COPYCHANGES                               +
    .        IBMREQD         SPACE                   UNCOMPRESSEDDATASI+
    ZE    REORGHASHACCESS        LPFACILITY        LASTDATACHANGE
    .                  PARTITION                                NACTIVE+
    .                        LOADRLASTTIME                             +
    .                        REORGDELETES                        REORGD+
    ISORGLOB                      REORGFARINDREF                       +
    .              STATSDELETES                        COPYLASTTIME    +
    .                                   COPYUPDATELRSN                 +
    .         DBID                  TOTALROWS               REORGCLUSTE+
    RSENS        HASHLASTUSED     STATS01
$/tstSqlFTab/
*/
    call pipeIni
    call tst t, 'tstSqlFTab'
    call sqlConnect , 'r'
    call sqlQuery 17, 'select * from sysibm.sysTablespaceStats' ,
                "where dbName = 'xxxDB06' and name = 'SYSTSTAB'"
    call sqlFTabOpts fTabReset(abc, 1, ,'-'),  12
    call sqlFTabDef      abc, 492, '%7e'
    call sqlfTab abc, 17
    call out '--- modified'
    call sqlQuery 17, 'select * from sysibm.sysTablespaceStats' ,
                "where dbName = 'xxxDB06' and name = 'SYSTSTAB'"
    call sqlFTabOpts fTabReset(abc, 2 1, 1 3 'c', '-'),  12
    call sqlFTabDef      abc, 492, '%7e'
    call ftabAdd         abc, DBNAME, '%-8C', 'db', , 'allg vorher'  ,
                                                  , 'allg nachher'
    call ftabAdd         abc, NAME  , '%-8C', 'ts'
    call ftabAdd         abc, PARTITION , , 'part'
    call ftabAdd         abc, INSTANCE  , , 'inst'
    ox = m.abc.0 + 1
    call sqlFTabOthers abc, 17
    call fTabSetTit      abc, ox, 2,             'others vorher'
    call fTabSetTit      abc, ox, 3,             'others nachher'
    call sqlFTab abc, 17
    call tstEnd t
    call sqlDisConnect
    return
endProcedure tstSqlFTab

tstSqlFTab2: procedure expose m.
/*
$=/tstSqlFTab2/
    ### start tst tstSqlFTab2 #########################################
    Und Eins Oder
    .          zw aber
    Und Eins---------------zw aber---
    . und eins                22223
    . und eins                22224
    Und Eins---------------zw aber---
    Und Eins Oder
    .          zw aber
    a-------------b---
    aaa         222
    a-------------b---
    --- row 1 ---------------------------------------------------------+
    -------------
    .           Und Eins Oder       und eins
    .           zw aber            2.2223000e04              22223
    --- row 2 ---------------------------------------------------------+
    -------------
    .           Und Eins Oder       und eins
    .           zw aber            2.2224000e04              22224
    --- end of 2 rows -------------------------------------------------+
    -------------
$/tstSqlFTab2/
*/
    call pipeIni
    call tst t, 'tstSqlFTab2'
    call sqlConnect , 'r'
    sq1 = 'select '' und eins'' "Und Eins Oder"',
             ', 22222 + row_number() over() "zw aber" ',
            'from sysibm.sysTables fetch first 2 rows only'
    call sqlQuery 17, sq1
    call sqlFTab sqlfTabReset(tstSqlFtab2), 17
    sq2 =             'select ''aaa'' "a", 222 "b"' ,
            'from sysibm.sysTables fetch first 1 rows only'
    call sqlQuery 17, sq2
    call sqlFTab sqlfTabReset(tstSqlFtab2), 17
    call sqlQuery 15, sq1
    call sqlFTab sqlfTabOpts(fTabReset(tstSqlFtab2, , , 'c')), 15
    call tstEnd t
    call sqlDisConnect
    return
endProcedure tstSqlFTab2
tstSqlFTab3: procedure expose m.
/*
$=/tstSqlFTab3/
    ### start tst tstSqlFTab3 #########################################
    Und Eins Oder
    .          zw aber
    Und Eins--z---
    . und eins 1
    . und eins 2
    Und Eins--z---
    Und Eins Oder
    .          zw aber
    a-----b---
    aaa 222
    a-----b---
$/tstSqlFTab3/
*/
    call pipeIni
    call tst t, 'tstSqlFTab3'
    call sqlConnect , 'r'
    sq1 = 'select '' und eins'' "Und Eins Oder"',
             ', row_number() over() "zw aber" ',
            'from sysibm.sysTables fetch first 2 rows only'
    call sqlQuery 7, sq1
    ft = sqlFTabOpts(fTabReset('tstSqFTab3', , ,'-a'))
    call sqlFTab ft, 7
    sq2 =             'select ''aaa'' "a", 222 "b"' ,
            'from sysibm.sysTables fetch first 1 rows only'
    call sqlQuery 17, sq2
    f = sqlfTabReset('tstSqFTab3t')
    st = 'tstSqFTab3st'
    call sqlFetch2St 17, st
    s2 = 'tstSqFTab3s2'
    do sx=1 to m.st.0
        m.s2.sx = st'.'sx
        end
    m.s2.0 = m.st.0
    call sqlFTabComplete f, 17, 1, 0
    call fTabDetect f, s2
    call fTabBegin f
    do sx=1 to m.st.0
        call out f(m.f.fmt, st'.'sx)
        end
    call fTabEnd f
    call tstEnd t
    call sqlDisConnect
    return
endProcedure tstSqlFTab3

tstSqlFTab4: procedure expose m.
/*
$=/tstSqlFTab4/
    ### start tst tstSqlFTab4 #########################################
    a
    1
    1 rows fetched: select 1 "a" from sysibm.sysDummy1
    sqlCode -204: drop table gibt.EsNicht
    a
    2
    1 rows fetched: select 2 "a" from sysibm.sysDummy1
    *** err: SQLCODE = -104: ILLEGAL SYMBOL "Y". SOME SYMBOLS THAT MIGH+
    T
    .    e 1:     BE LEGAL ARE: , FROM INTO
    .    e 2: src select x frm y
    .    e 3:   >              <<<pos 14 of 14<<<
    .    e 4: sql = select x frm y
    .    e 5: stmt = prepare s49 into :M.SQL.49.D from :src
    .    e 6: with into :M.SQL.49.D = M.SQL.49.D
    sqlCode -104: select x frm y
    a
    3
    1 rows fetched: select 3 "a" from sysibm.sysDummy1
    dy  => 1
    a
    1
    1 rows fetched: select 1 "a" from sysibm.sysDummy1
    sqlCode -204: drop table gibt.EsNicht
    a
    2
    1 rows fetched: select 2 "a" from sysibm.sysDummy1
    fatal error in wsM: SQLCODE = -104: ILLEGAL SYMBOL "Y". SOME SYMBO+
    LS THAT MIGHT
    .    BE LEGAL ARE: , FROM INTO
    src select x frm y
    .  >              <<<pos 14 of 14<<<
    sql = select x frm y
    stmt = prepare s49 into :M.SQL.49.D from :src
    with into :M.SQL.49.D = M.SQL.49.D
    sqlCode 0: rollback
    ret => 0
$/tstSqlFTab4/
*/
    call pipeIni
    call tst t, 'tstSqlFTab4'
    eOutOld = m.err_sayOut
    m.err_sayOut = 1
    call sqlConnect
    b = jBuf('select 1 "a" from sysibm.sysDummy1;' ,
         , 'drop table gibt.EsNicht;' ,
         , 'select 2 "a" from sysibm.sysDummy1;',
         , ' select x frm y;',
         , 'select 3 "a" from sysibm.sysDummy1;')
    call tstout t, 'dy  =>' sqlsOut(scanSqlStmtRdr(b, 0))
    call tstout t, 'ret =>' sqlsOut(scanSqlStmtRdr(b, 0), 'rb ret')
    call tstEnd t
    call sqlDisConnect
    m.err_sayOut = eOutOld
    return
endProcedure tstSqlFTab4

tstSqlFTab5: procedure expose m.
/*
$=/tstSqlFTab5/
    ### start tst tstSqlFTab5 #########################################
    -----D6-------D73------D62---------D92---
    .  23456  -123.456    45.00     -123.45
    -----D6-------D73------D62---------D92---
$/tstSqlFTab5/
*/
    call pipeIni
    call tst t, 'tstSqlFTab5'
    call sqlConnect , 'e'
    sq1 = 'select dec(23456, 6) d6, dec(-123.4567, 7, 3) d73',
              ', dec(45, 6, 2) d62, dec(-123.45678, 9, 2) d92',
            'from sysibm.sysDummy1'
    call sqlQuery 17, sq1
    call sqlFTab sqlfTabReset(tstSqlFtab5), 17
    call tstEnd t
    call sqlDisConnect
    return
endProcedure tstSqlFTab5

tstSql4Obj: procedure expose m.
/*
$=/tstSql4Obj/
    ### start tst tstSql4Obj ##########################################
    tstR: @tstWriteoV2 isA :tstClass-1 = -11
    tstR:  .a2i = -11
    tstR:  .b3b = b3
    tstR:  .D4 = D4-11+D4++++.
    tstR:  .fl5 = -111.1
    tstR:  .ex6 = -.111e-11
    insert into cr.insTb -- tstClass-1
    .   ( , a2i, b3b, D4, fl5, ex6
    .   ) values .
    .   ( -11, -11, 'b3', 'D4-11+D4++++', -111.1, -.111e-11
    .   ) ; .
    insert into cr.insTbHex -- tstClass-1
    .   ( , a2i, b3b, D4, fl5, ex6
    .   ) values .
    .   ( -11, -11, 'b3', x'C40760F1F14EC4F44E4E4E4E', -111.1, -.111e-1+
    1
    .   ) ; .
    tstR: @tstWriteoV4 isA :tstClass-2
    tstR:  .c = c83
    tstR:  .a2i = 83
    tstR:  .b3b = b3b8
    tstR:  .D4 = D483+D4++++++++++++++++++++++++++++++++++++++++++++++++
    .++++++++++++++++++++++++++++++.
    tstR:  .fl5 = .183
    tstR:  .ex6 = .11183e-8
    insert into cr.insTb -- tstClass-2
    .   ( c, a2i, b3b, D4, fl5, ex6
    .   ) values .
    .   ( 'c83', 83, 'b3b8'
    .   , 'D483+D4++++++++++++++++++++++++++++++++++++++++++++++++++++++
    '
    .   || '++++++++++++++++++++++++'
    .   , .183, .11183e-8
    .   ) ; .
    insert into cr.insTbHex -- tstClass-2
    .   ( c, a2i, b3b, D4, fl5, ex6
    .   ) values .
    .   ( 'c83', 83, 'b3b8'
    .   , x'C407F8F34EC4F44E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E'
    .   || '++++++++++++++++++++++++++++++++'
    .   || x'314E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E'
    .   , .183, .11183e-8
    .   ) ; .
$/tstSql4Obj/
*/
    call pipeIni
    call tst t, 'tstSql4Obj'
    call pipe '+N'
    call tstDataClassOut '. c3 a2i i b3b c5 D4 c23 fl5 f8n2 ex6 e9n3',
        , -11, -11
    call tstDataClassOut 'c c3 a2i i b3b c5 D4 c93 fl5 f8n2 ex6 e9n3',
        , 83, 83
    call pipe 'P|'
    do cx=1 while in()
        i = m.in
        call mAdd t'.'trans, className(objClass(i)) 'tstClass-'cx
        call out i
        call sql4Obj i, 'cr.insTb'
        m.i.d4 = overlay('07'x, m.i.d4, 2)
        if length(m.i.d4) >= 62 then
            m.i.d4 = overlay('31'x, m.i.d4, 62)
        call sql4Obj i, 'cr.insTbHex'
        end
    call pipe '-'
    call tstEnd t
    return
endProcedure tstSql4Obj
tstSqlC: procedure expose m.
/*
$=/tstSqlCRx/
    ### start tst tstSqlCRx ###########################################
    *** err: SQLCODE = -104: ILLEGAL SYMBOL "?". SOME SYMBOLS THAT MIGH+
    T
    .    e 1:     BE LEGAL ARE: . <IDENTIFIER> JOIN INNER LEFT RIGHT FU+
    LL CROSS ,
    .    e 2:     HAVING GROUP
    .    e 3: src select * from sysibm?sysDummy1
    .    e 4:   >    >>>pos 21 of 30>>>
    .    e 5: sql = select * from sysibm?sysDummy1
    .    e 6: stmt = prepare s10 into :M.SQL.10.D from :src
    .    e 7: with into :M.SQL.10.D = M.SQL.10.D
    *** err: SQLCODE = -204: NONONO.SYSDUMMY1 IS AN UNDEFINED NAME
    .    e 1: sql = select * from nonono.sysDummy1
    .    e 2: stmt = prepare s10 into :M.SQL.10.D from :src
    .    e 3: with into :M.SQL.10.D = M.SQL.10.D
    sys local ==> server CHSKA000DP4G    .
    fetched a1=abc, i2=12, c3=---
    .  I1 C2
    .   1 eins
    2222 zwei
$/tstSqlCRx/
$=/tstSqlCCsm/
    ### start tst tstSqlCCsm ##########################################
    *** err: SQLCODE = -104: ILLEGAL SYMBOL "?". SOME SYMBOLS THAT MIGH+
    T
    .    e 1:     BE LEGAL ARE: . <IDENTIFIER> JOIN INNER LEFT RIGHT FU+
    LL CROSS ,
    .    e 2:     HAVING GROUP
    .    e 3: src select * from sysibm?sysDummy1
    .    e 4:   >    >>>pos 21 of 30>>>
    .    e 5: sql = select * from sysibm?sysDummy1
    .    e 6: sqlCsmExe RZZ/DE0G
    *** err: SQLCODE = -204: NONONO.SYSDUMMY1 IS AN UNDEFINED NAME
    .    e 1: sql = select * from nonono.sysDummy1
    .    e 2: sqlCsmExe RZZ/DE0G
    sys RZZ/DE0G csm ==> server CHROI00ZDE0G    .
    fetched a1=abc, i2=12, c3=---
    .  I1 C2
    .   1 eins
    2222 zwei
$/tstSqlCCsm/
 ### start tst tstSqlCWsh ##########################################
 *** err: sqlWshRdr got fatal error in wsM: SQLCODE = -104: ILLEGAL +
 SYMBOL "?". SOME SYMBOLS THAT MIGHT
 .    e 1:     BE LEGAL ARE: . <IDENTIFIER> JOIN INNER LEFT RIGHT FU+
 LL CROSS ,
 .    e 2:     HAVING GROUP
 .    e 3: src select * from sysibm?sysDummy1
 .    e 4:   >    >>>pos 21 of 30>>>
 .    e 5: sql = select * from sysibm?sysDummy1
 .    e 6: stmt = prepare s10 into :M.SQL.10.D from :src
 .    e 7: with into :M.SQL.10.D = M.SQL.10.D
 *** err: sqlWshRdr got fatal error in wsM: SQLCODE = -204: NONONO.S+
 YSDUMMY1 IS AN UNDEFINED NAME
 .    e 1: sql = select * from nonono.sysDummy1
 .    e 2: stmt = prepare s10 into :M.SQL.10.D from :src
 .    e 3: with into :M.SQL.10.D = M.SQL.10.D
 sys RZZ/DE0G wsh ==> server CHROI00ZDE0G    .
 fetched a1=abc, i2=12, c3=---
 .  I1 C2
 .   1 eins
$=/tstSqlCWsh/
    ### start tst tstSqlCWsh ##########################################
    *** err: sqlWshRdr got fatal error in wsM: SQLCODE = -104: ILLEGAL+
    . SYMBOL "?". SOME SYMBOLS THAT MIGHT
    .    e 1:     BE LEGAL ARE: . <IDENTIFIER> JOIN INNER LEFT RIGHT FU+
    LL CROSS ,
    .    e 2:     HAVING GROUP
    .    e 3: src select * from sysibm?sysDummy1
    .    e 4:   >    >>>pos 21 of 30>>>
    .    e 5: sql = select * from sysibm?sysDummy1
    .    e 6: stmt = prepare s10 into :M.SQL.10.D from :src
    .    e 7: with into :M.SQL.10.D = M.SQL.10.D
    .    e 8: sqlCode 0: rollback
    .    e 9: from RZZ Z24 DE0G
    *** err: sqlWshRdr got fatal error in wsM: SQLCODE = -204: NONONO.+
    SYSDUMMY1 IS AN UNDEFINED NAME
    .    e 1: sql = select * from nonono.sysDummy1
    .    e 2: stmt = prepare s10 into :M.SQL.10.D from :src
    .    e 3: with into :M.SQL.10.D = M.SQL.10.D
    .    e 4: sqlCode 0: rollback
    .    e 5: from RZZ Z24 DE0G
    sys RZZ/DE0G wsh ==> server CHROI00ZDE0G    .
    fetched a1=abc, i2=12, c3=---
    .  I1 C2
    .   1 eins
    2222 zwei
$/tstSqlCWsh/
*/

    call pipeIni
    sql1 = "select 1 i1, 'eins' c2 from sysibm.sysDummy1" ,
        "union all select 2222 i1, 'zwei' c2 from sysibm.sysDummy1"
    do tx=1 to 1 +  (m.tst_CsmRZ \== '') * 2
        if tx = 1 then do
            call tst t, "tstSqlCRx"
            call sqlConnect , 'r'
            sys = 'local'
            end
        else if tx=2 then do
            call tst t, "tstSqlCCsm"
            sys = m.tst_csmRzDb 'csm'
            call sqlConnect m.tst_csmRzDb, 'c'
            end
        else do
            call tst t, "tstSqlCWsh"
            call sqlConnect m.tst_csmRzDb, 'w'
            sys = m.tst_csmRzDb 'wsh'
            end
        cx = 9
        call jOpen sqlRdr('select * from sysibm?sysDummy1'), '<'
        call jOpen sqlRdr('select * from nonono.sysDummy1'), '<'
        rr = jOpen(sqlRdr("select 'abc' a1, 12 i2, current server srv",
                     ", case when 1=0 then 1 else null end c3",
                 "from sysibm.sysDummy1"), '<')
        do while jRead(rr)
           dst = m.rr
           call out 'sys' sys '==> server' m.dst.srv
           call out 'fetched a1='m.dst.a1', i2='m.dst.i2', c3='m.dst.c3
           end
        call jClose rr
        call fTabAuto , sqlRdr(sql1)
        call sqlDisconnect
        call tstEnd t
        end
    return
endProcedure tstSqlC

tstSqlUpd: procedure expose m.
/*
$=/tstSqlUpd/
    ### start tst tstSqlUpd ###########################################
    insert updC 1
    insert select updC 2
    dest4.fet: 1 eins 2012-04-01-06.07.08.000000 1 updC 0
    dest5.fet: 2 zwei 2012-02-29-15.44.33.220000 --- updC 0
    dest6.fet: 11 zehn+eins 2012-04-11-06.07.08.000000 1 updC 0
    dest7.fet: 12 zehn+zwei 2012-03-10-15.44.33.220000 --- updC 0
    SQLCODE = 000,  SUCCESSFUL EXECUTION
    warnings  4=W no where
    sql = select * from final table (update session.dgtt  set c2 = 'u' +
    || c2)
    stmt = prepare s9 into :M.SQL.9.D from :src
    with into :M.SQL.9.D = M.SQL.9.D
    dest9.fet: 1 ueins 2012-04-01-06.07.08.000000 updC 4
    dest10.fet: 2 uzwei 2012-02-29-15.44.33.220000 updC 4
    dest11.fet: 11 uzehn+eins 2012-04-11-06.07.08.000000 updC 4
    dest12.fet: 12 uzehn+zwei 2012-03-10-15.44.33.220000 updC 4
$/tstSqlUpd/ */
    call tst t, "tstSqlUpd"
    cx = 9
    qx = 3
    call sqlConnect , 'e'
    call sqlUpdate,"declare global temporary table session.dgtt",
                           "(i1 int, c2 varchar(20), t3 timestamp)"
    call sqlUpdate,"insert into session.dgtt" ,
                    "values(1, 'eins', '2012-04-01 06.07.08')"
    call sqlUpdate,"insert into session.dgtt" ,
                    "values(2, 'zwei', '2012-02-29 15:44:33.22')"
    call out 'insert updC' m.sql..updateCount
    call sqlUpdate,"insert into session.dgtt" ,
                      "select i1+10, 'zehn+'||strip(c2), t3+10 days",
                           "from session.dgtt"
    call out 'insert select updC' m.sql..updateCount
    call sqlQuery cx, 'select d.*' ,
               ', case when mod(i1,2) = 1 then 1 else null end grad' ,
               'from session.dgtt d'
    do qx=qx+1 while sqlFetch(cx, 'dest'qx'.fet')
        dst = 'dest'qx'.fet'
        call out dst':' m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad ,
           'updC' m.sql.cx.updateCount
        drop m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad
        end
    call sqlClose cx
    call sqlQuery cx, "select * from final table (update session.dgtt",
                   " set c2 = 'u' || c2)"
    do qx=qx+1 while sqlFetch(cx, 'dest'qx'.fet')
        dst = 'dest'qx'.fet'
        call out dst':' m.dst.i1 m.dst.c2 m.dst.t3 ,
           'updC' m.sql.cx.updateCount
        drop m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad
        end
    call sqlDisconnect
    call tstEnd t
    return
endProcedure tstSqlUpd
tstSqlUpdPre: procedure expose m.
/*
$=/tstSqlUpdPre/
    ### start tst tstSqlUpdPre ########################################
    insert updC 1
    insert select updC 2
    dest4.fet: 1 eins 2012-04-01-06.07.08.000000 1 updC 0
    dest5.fet: 2 zwei 2012-02-29-15.44.33.220000 --- updC 0
    dest6.fet: 11 zehn+eins 2012-04-11-06.07.08.000000 1 updC 0
    dest7.fet: 12 zehn+zwei 2012-03-10-15.44.33.220000 --- updC 0
    SQLCODE = 000,  SUCCESSFUL EXECUTION
    warnings  4=W no where
    sql = select * from final table ( update session.dgtt set c2 = ? ||+
    . c2)
    stmt = prepare s5 into :M.SQL.5.D from :src
    with into :M.SQL.5.D = M.SQL.5.D
    dest9.fet: 1 ueins 2012-04-01-06.07.08.000000 updC 4
    dest10.fet: 2 uzwei 2012-02-29-15.44.33.220000 updC 4
    dest11.fet: 11 uzehn+eins 2012-04-11-06.07.08.000000 updC 4
    dest12.fet: 12 uzehn+zwei 2012-03-10-15.44.33.220000 updC 4
$/tstSqlUpdPre/ */
    call tst t, "tstSqlUpdPre"
    cx = 5
    qx = 3
    call sqlConnect , 'e'
    call sqlUpdate,"declare global temporary table session.dgtt",
                           "(i1 int, c2 varchar(20), t3 timestamp)"
    call sqlUpdatePrepare 5, "insert into session.dgtt" ,
                                   "values (?, ?, ?)"
    call sqlUpdateExecute 5, 1, 'eins', '2012-04-01 06.07.08'
    call sqlUpdateExecute 5, 2, 'zwei', '2012-02-29 15:44:33.22'
    call out 'insert updC' m.sql.5.updateCount
    call sqlUpdatePrepare 5,"insert into session.dgtt" ,
                      "select i1+?, 'zehn+'||strip(c2), t3+? days",
                           "from session.dgtt"
    call sqlUpdateExecute 5, 10, 10
    call out 'insert select updC' m.sql.5.updateCount
    call sqlQueryPrepare cx, 'select d.*' ,
               ', case when mod(i1,2) = ? then 0+? else null end grad',
               'from session.dgtt d'
    call sqlQueryExecute cx, 1, 1
    do qx=qx+1 while sqlFetch(cx, 'dest'qx'.fet')
        dst = 'dest'qx'.fet'
        call out dst':' m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad ,
           'updC' m.sql.cx.updateCount
        drop m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad
        end
    call sqlClose cx
    call sqlQueryPrepare cx, "select * from final table (" ,
              "update session.dgtt set c2 = ? || c2)"
    call sqlQueryExecute cx, "u"
    do qx=qx+1 while sqlFetch(cx, 'dest'qx'.fet')
        dst = 'dest'qx'.fet'
        call out dst':' m.dst.i1 m.dst.c2 m.dst.t3 ,
           'updC' m.sql.cx.updateCount
        drop m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad
        end
    call sqlDisconnect
    call tstEnd t
    return
endProcedure tstSqlUpdPre
tstsqlRxUpd: procedure expose m.
/*
$=/tstsqlRxUpd/
    ### start tst tstsqlRxUpd #########################################
    insert updC 1
    insert select updC 2
    dest4.fet: 1 eins 2012-04-01-06.07.08.000000 1 updC 0
    dest5.fet: 2 zwei 2012-02-29-15.44.33.220000 --- updC 0
    dest6.fet: 11 zehn+eins 2012-04-11-06.07.08.000000 1 updC 0
    dest7.fet: 12 zehn+zwei 2012-03-10-15.44.33.220000 --- updC 0
    SQLCODE = 000,  SUCCESSFUL EXECUTION
    warnings  4=W no where
    sql = select * from final table (update session.dgtt set c2 = 'u' +
    || c2)
    stmt = prepare s9 into :M.SQL.9.D from :src
    with into :M.SQL.9.D = M.SQL.9.D
    dest9.fet: 1 ueins 2012-04-01-06.07.08.000000 updC 4
    dest10.fet: 2 uzwei 2012-02-29-15.44.33.220000 updC 4
    dest11.fet: 11 uzehn+eins 2012-04-11-06.07.08.000000 updC 4
    dest12.fet: 12 uzehn+zwei 2012-03-10-15.44.33.220000 updC 4
$/tstsqlRxUpd/ */
    call pipeIni
    call tst t, "tstsqlRxUpd"
    cx = 9
    qx = 3
    call sqlConnect , 'e'
    call sqlUpdate,"declare global temporary table session.dgtt",
                           "(i1 int, c2 varchar(20), t3 timestamp)"
    call sqlUpdate,"insert into session.dgtt" ,
                    "values(1, 'eins', '2012-04-01 06.07.08')"
    call sqlUpdate,"insert into session.dgtt" ,
                    "values(2, 'zwei', '2012-02-29 15:44:33.22')"
    call out 'insert updC' m.sql..updateCount
    call sqlUpdate,"insert into session.dgtt" ,
                      "select i1+10, 'zehn+'||strip(c2), t3+10 days",
                           "from session.dgtt"
    call out 'insert select updC' m.sql..updateCount
    call sqlQuery cx, 'select d.*' ,
               ', case when mod(i1,2) = 1 then 1 else null end grad' ,
               'from session.dgtt d'
    do qx=qx+1 while sqlFetch(cx, 'dest'qx'.fet')
        dst = 'dest'qx'.fet'
        call out dst':' m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad ,
           'updC' m.sql.cx.updateCount
        drop m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad
        end
    call sqlClose cx
    call sqlQuery cx, "select * from final table",
                 "(update session.dgtt set c2 = 'u' || c2)"

    do qx=qx+1 while sqlFetch(cx, 'dest'qx'.fet')
        dst = 'dest'qx'.fet'
        call out dst':' m.dst.i1 m.dst.c2 m.dst.t3 ,
           'updC' m.sql.cx.updateCount
        drop m.dst.i1 m.dst.c2 m.dst.t3 m.dst.grad
        end
    call sqlClose cx
    call sqlDisconnect
    call tstEnd t
    return
endProcedure tstsqlRxUpd

tstSqlE: procedure expose m.
/*
$=/tstSqlE/
    ### start tst tstSqlE #############################################
    *** err: SQLCODE = -713: THE REPLACEMENT VALUE FOR CURRENT SCHEMA I+
    S
    .    e 1:     INVALID
    .    e 2: sql = set current schema = 'sysibm'
    .    e 3: stmt = execute immediate :src
    -713 set schema ''
    0 set schema
    0 select
    fetch=1 SYSIBM
$/tstSqlE/
*/
    call sqlConnect , 'e'
    call tst t, "tstSqlE"
    call tstOut t, sqlExecute(3, "set current schema = 'sysibm'") ,
                                 "set schema ''"
    call tstOut t, sqlExecute(3, " set current schema = sysibm ") ,
                                 "set schema"
    call tstOut t, sqlExecute(3, " select current schema c"      ,
                                      "from sysibm.sysDummy1") 'select'
    call tstOut t, 'fetch='sqlFetch(3, aa) m.aa.c
    call sqlClose 3
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlE
tstSqlO: procedure expose m.
/*
$=/tstSqlO/
    ### start tst tstSqlO #############################################
    sqlCode 0: set current schema = A540769
    *** err: SQLCODE = -204: A540769.SYSDUMMY IS AN UNDEFINED NAME
    .    e 1: sql = select * from sysdummy
    .    e 2: stmt = prepare s49 into :M.SQL.49.D from :src
    .    e 3: with into :M.SQL.49.D = M.SQL.49.D
    sqlCode -204: select * from sysdummy
    REQD=Y col=123 case=--- .sqlInd:-1 col5=anonym geburri=1956-04-01+
    -06.00.00.000000
$/tstSqlO/
*/
    call sqlConnect , 's'
    call tst t, "tstSqlO"
    call sqlStmts 'set current schema = A540769';
    call sqlStmts 'select * from sysdummy';
    r = sqlRdr( ,
          "select d.*, 123, timestamp('01.04.1956','06:00:00')" ,
                             '"geburri walter",',
                    'case when 1=0 then 1 else null end caseNull,',
                    "'anonym'" ,
               'from sysibm.sysdummy1 d')
    call jOpen r, '<'
    do while jRead(r)
        o = m.r
        call out 'REQD='m.o.IBMREQD 'col='m.o.col2,
                  'case='m.o.CASENULL '.sqlInd:'m.o.caseNull.sqlInd,
                  'col5='m.o.col5,
                  'geburri='m.o.GEBURRI
        end
    call jClose r
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlO

tstSqlUpdComLoop: procedure expose m.
/*
$=/tstSqlUpdComLoop/
    ### start tst tstSqlUpdComLoop ####################################
    sqlCode 0: declare global temporary table session.dgtt (i1 int) on +
    commit ....
    sqlCode 0, 123 rows inserted: insert into session.dgtt select row_n+
    umber()....
    CNT
    123
    1 rows fetched: select count(*) cnt from session.dgtt
    123 rows deleted, 10 commits: delete from session.dgtt d where i1 i+
    n (sele....
    C
    0
    1 rows fetched: select count(*) cnt from session.dgtt
$/tstSqlUpdComLoop/ */
    call pipeIni
    call tst t, "tstSqlUpdComLoop"
    call sqlConnect , 's'
    call sqlsOut "declare global temporary table session.dgtt",
                           "(i1 int) on commit preserve rows"
    call sqlsOut "insert into session.dgtt",
       "select row_number() over() from sysibm.sysTables",
           "fetch first 123 rows only"
    call sqlsOut "select count(*) cnt from session.dgtt"
    call out sqlUpdComLoop("delete from session.dgtt d where i1 in",
       "(select i1 from session.dgtt fetch first 13 rows only)")
    call sqlsOut "select count(*) cnt from session.dgtt"
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlUpdComLoop

tstSqlO1: procedure expose m.
/*
$=/tstSqlO1/
    ### start tst tstSqlO1 ############################################
    tstR: @tstWriteoV2 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLEPART
    tstR: @tstWriteoV3 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLEPART_HIST
    tstR: @tstWriteoV4 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLES
    tstR: @tstWriteoV5 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLESPACE
    --- writeAll
    tstR: @tstWriteoV6 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLEPART
    tstR: @tstWriteoV7 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLEPART_HIST
    tstR: @tstWriteoV8 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLES
    tstR: @tstWriteoV9 isA :<tstSqlO1Type>
    tstR:  .CR = SYSIBM
    tstR:  .TB = SYSTABLESPACE
$/tstSqlO1/
*/
    call pipeIni
    call tst t, "tstSqlO1"
    call sqlConnect , 'r'
    qr = sqlRdr("select strip(creator) cr, strip(name) tb",
                     "from sysibm.sysTables",
                     "where creator='SYSIBM' and name like 'SYSTABL%'",
                     "order by 2 fetch first 4 rows only")
    call jOpen qr, m.j.cRead
    call mAdd t.trans, className(m.qr.type) '<tstSqlO1Type>'
    do while jRead(qr)
        call out m.qr
        end
    call jClose qr
    call out '--- writeAll'
    call pipeWriteAll qr
    call sqlDisConnect
    call tstEnd t
    return 0
endProcedure tstSqlO1

tstSqlO2: procedure expose m.
/*
$=/tstSqlO2/
    ### start tst tstSqlO2 ############################################
    CR     TB                RR
    SYSIBM SYSTABLEPART       1
    SYSIBM SYSTABLEPART_HIST  4
    SYSIBM SYSTABLES          9
    SYSIBM SYSTABLESPACE     16
$/tstSqlO2/
*/
    call pipeIni
    call tst t, "tstSqlO2"
    call sqlConnect , 'r'
    call pipe '+N'
    call out    "select strip(creator) cr, strip(name) tb,"
    call out         "(row_number()over())*(row_number()over()) rr"
    call out         "from sysibm.sysTables"
    call out         "where creator='SYSIBM' and name like 'SYSTABL%'"
    call out         "order by 2 fetch first 4 rows only"
    call pipe 'N|'
    call sqlSel
    call pipe 'P|'
    call fTabAuto fTabReset(abc, 1)
    call pipe '-'
    call sqlDisConnect
    call tstEnd t
    return 0
endProcedure tstSqlO2
tstSqlS1: procedure expose m.
/*
$=/tstSqlS1/
    ### start tst tstSqlS1 ############################################
    select c, a from sysibm.sysDummy1
    tstR: @tstWriteoV2 isA :<cla sql c a>
    tstR:  .C = 1
    tstR:  .A = a
    select ... where 1=0
    tstR: @ obj null
$/tstSqlS1/
*/
    call tst t, "tstSqlS1"
    call sqlConnect , 'r'
    s1 = jSingle( ,
        sqlRdr("select count(*) c, 'a' a from sysibm.sysdummy1"))
    call mAdd t.trans, className(objClass(s1)) '<cla sql c a>'
    call out 'select c, a from sysibm.sysDummy1'
    call tstWrite t, s1
    call out 'select ... where 1=0'
    call tstWrite t, jSingle( ,
        sqlRdr("select*from sysibm.sysdummy1 where 1=0"), '')
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlS1

tstSqlWsh: procedure expose m.
/*
$=/tstSqlWsh/
    ### start tst tstSqlWsh ###########################################
    tstR: @tstWriteoV14 isA :Sql*15
    tstR:  .COL1 = <csmServer>
    1 rows fetched: select current server from sysibm.sysDummy1
    tstR: @tstWriteoV16 isA :Sql*17
    tstR:  .ZWEI = second  sel
    tstR:  .DREI = 3333
    tstR:  .VIER = 4444
    1 rows fetched: select 'second sel' zwei, 3333 drei, 4444 vier from+
    . sysibm....
    fatal error in wsM: SQLCODE = -104: ILLEGAL SYMBOL "XYZ". SOME SYM+
    BOLS THAT
    .    MIGHT BE LEGAL ARE: <ERR_STMT> <WNG_STMT> GET SQL SAVEPOINT HO+
    LD
    .    FREE ASSOCIATE
    src xyz
    .  > <<<pos 1 of 3<<<
    sql = xyz
    sqlCode 0: rollback
    from <csmRZ> <csmSys*> <csmDB>
$/tstSqlWsh/
*/
    call pipeIni
    call sqlconClass_w
    call tst t, "tstSqlWsh"
    call tstTransCsm t
    b = jBuf('select current server from' , 'sysibm.sysDummy1',
         , ';;;', "select 'second  sel' zwei, 3333 drei, 4444 vier" ,
                 ,  "from sysibm.sysDummy1",,";;xyz")
    r = scanSqlStmtRdr(b)
    call sqlWshOut r, m.tst_csmRzDb, 0, 'o'
    call tstEnd t
    return
endProcedure tstSqlWsh
tstSqlWs2: procedure expose m.
/*
$=/tstSqlWs2/
    ### start tst tstSqlWs2 ###########################################
    tstR: @tstWriteoV14 isA :Sql*15
    tstR:  .COL1 = <csmServer>    .
    tstR:  .COLNO = 1
    tstR:  .NAME = NAME
    tstR: @tstWriteoV16 isA :Sql*15
    tstR:  .COL1 = <csmServer>    .
    tstR:  .COLNO = 2
    tstR:  .NAME = CREATOR
    tstR: @tstWriteoV17 isA :Sql*15
    tstR:  .COL1 = <csmServer>    .
    tstR:  .COLNO = 3
    tstR:  .NAME = TYPE
    tstR: @tstWriteoV18 isA :Sql*15
    tstR:  .COL1 = <csmServer>    .
    tstR:  .COLNO = 4
    tstR:  .NAME = DBNAME
$/tstSqlWs2/
*/
    call pipeIni
    call sqlconClass_w
    call tst t, "tstSqlWs2"
    call tstTransCsm t
    sql = "select current server, colNo, name" ,
            "from sysibm.sysColumns" ,
            "where tbCreator = 'SYSIBM' and tbName = 'SYSTABLES'",
            "order by colNo fetch first 4 rows only"
    w = oNew(m.class_SqlWshRdr, m.tst_csmRzDb, sql)
    call pipeWriteNow w
    call tstEnd t
    return
endProcedure tstSqlWs2
tstSqlStmt: procedure expose m.
/*
$=/tstSqlStmt/
    ### start tst tstSqlStmt ##########################################
    *** err: SQLCODE = -713: THE REPLACEMENT VALUE FOR CURRENT SCHEMA I+
    S
    .    e 1:     INVALID
    .    e 2: sql = set current schema = 'sysibm'
    .    e 3: stmt = execute immediate :src
    sqlCode -713: set current schema = 'sysibm'
    sqlCode 0: set current schema =  sysibm
    tstR: @tstWriteoV2 isA :<sql?sc>
    tstR:  .C = SYSIBM
    1 rows fetched: select current schema c  from sysDummy1
    tstR: @tstWriteoV3 isA :<sql?sc>
    tstR:  .C = SYSIBM
    1 rows fetched: (select current schema c from sysDummy1)
$/tstSqlStmt/
*/
    call sqlConnect , 's'
    call tst t, "tstSqlStmt"
    cn = className(classNew('n* Sql u f%v  C'))
    call mAdd t.trans, cn '<sql?sc>'
    call sqlStmts "set current schema = 'sysibm'"
    call sqlsOut "    set current schema =  sysibm "
    call sqlsOut "   select current schema c  from sysDummy1", , 'o'
    call sqlsOut "  (select current schema c from sysDummy1)", , 'o'
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlStmt
tstSqlStmts: procedure expose m.
/*
$=/tstSqlStmts/
   ### start tst tstSqlStmts #########################################
   *** err: SQLCODE = -104: ILLEGAL SYMBOL "BLABLA". SOME SYMBOLS THAT
   .    e 1:     MIGHT BE LEGAL ARE: <ERR_STMT> <WNG_STMT> GET SQL SAV+
   EPOINT HOLD
   .    e 2:     FREE ASSOCIATE
   .    e 3: src blabla
   .    e 4:   > <<<pos 1 of 6<<<
   .    e 5: sql = blabla
   sqlCode -104: blabla
   sqlCode 0: set current schema=  sysIbm
   c
   1
   1 rows fetched: select count(*) "c" from sysDummy1 with   ur
   c
   1
   1 rows fetched: select count(*) "c" from sysDummy1 with   ur
   #jIn 1# set current -- sdf
   #jIn 2# schema = s100447;
   #jIn eof 3#
   sqlCode 0: set current schema = s100447
$/tstSqlStmts/ */
    call sqlConnect , 's'
    call tst t, "tstSqlStmts"
    call sqlStmts "blabla ;;set current schema=  sysIbm "
    b = jBuf('select count(*) "c" from sysDummy1 --com' ,
             ,'with  /* comm */ ur;')
    call sqlStmts b
    call sqlStmts b
    call mAdd mCut(t'.IN', 0), 'set current -- sdf','schema = s100447;'
    call sqlStmts
    call sqlDisConnect
    call tstEnd t
    return
endProcedure tstSqlStmts

tstDb2Ut: procedure expose m.
/*
$=/tstDb2Ut/
    ### start tst tstDb2Ut ############################################
    .  TEMPLATE IDSN DSN(DSN.INPUT.UNL)
    #jIn 1#    template old ,
    .   template old ,
    #jIn 2# LOAD DATA INDDN oldDD .
    LOAD DATA LOG NO
    .    INDDN IDSN RESUME NO REPLACE COPYDDN(TCOPYD)
    .    DISCARDDN TDISC
    .    STATISTICS INDEX(ALL) UPDATE ALL
    .    DISCARDS 1
    .    ERRDDN   TERRD
    .    MAPDDN   TMAPD .
    .    WORKDDN  (TSYUTD,TSOUTD) .
    .  SORTDEVT DISK .
    #jIn 3# ( cols  )
    ( cols  )
$/tstDb2Ut/
*/
    call pipeIni
    call tst t, 'tstDb2Ut'
    call mAdd mCut(t'.IN', 0), '   template old ,'    ,
                     , 'LOAD DATA INDDN oldDD ' ,
                     , '( cols  )'
    call db2UtilPunch 'rep iDsn=DSN.INPUT.UNL'
    call tstEnd t
return
endProcedure tstDb2Ut

/*--- manualTest for csi --------------------------------------------*/
tstSqlDisDb: procedure expose m.
    call sqlDsn di, 'DP4G', '-dis db(*) sp(*)' ,
                    'restrict advisory limit(*)', 12
    m.oo.0 = 0
    call sqlDisDb oo, di
    say 'di.0' m.di.0 '==> oo.0' m.oo.0
    trace ?r
    ix = sqlDisDbIndex(oo, QZ01A1P,A006A)
    say 'DB2PDB6.RR2HHAGE  ==>' ix m.oo.ix.sta
    ix = sqlDisDbIndex(oo, QZ01A1P,A006J, 3)
    say 'DB2PDB6.RR2HHAGE.3  ==>' ix m.oo.ix.sta
    ix = sqlDisDbIndex(oo, DB2PDB6,RR2HHAGE,22)
    say 'DB2PDB6.RR2HHAGE.22 ==>' ix m.oo.ix.sta
    return
endProcedure tstSqlDisDb

/****** tst wsh main and hooks ***************************************/
tstMain: procedure expose main
/*
$=/tstMain/
    ### start tst tstMain #############################################
    DREI
    .  ABC
    D ABC
    3 abc
    1 rows fetched: select 1+2 drei, 'abc' abc from sysibm.sysDummy1
$/tstMain/
*/
    call pipeIni
    i = jBuf("select 1+2 drei, 'abc' abc" ,
               "from sysibm.sysDummy1")
    call tst t, 'tstMain'
    w = tstMain1
    m.w.exitCC = 0
    call wshRun w, 'sqlsOut */ a', i
    call tstEnd t
    return
endProcedure tstMain

tstHookSqlRdr: procedure expose m.
/*
$=/tstHookSqlRdr/
### start tst tstHookSqlRdr #######################################
    tstR: @tstWriteoV1 isA :Sql*2
    tstR:  .F5 = 5
    tstR:  .F2 = zwei
    fatal error in wsM: SQLCODE = -104: ILLEGAL SYMBOL "?". SOME SYMBO+
    LS THAT MIGHT
    .    BE LEGAL ARE: AT MICROSECONDS MICROSECOND SECONDS SECOND MINUT+
    ES
    .    MINUTE HOURS
    src select 2?3 f5, 'zwei' f2 from sysibm.sysDummy1
    .  >         <<<pos 9 of 46<<<
    sql = select 2?3 f5, 'zwei' f2 from sysibm.sysDummy1
    stmt = prepare s10 into :M.SQL.10.D from :src
    with into :M.SQL.10.D = M.SQL.10.D
    sqlCode 0: rollback
    from RZ4 S42 DP4G
    fatal error in wsM: SQLCODE = -924: DB2 CONNECTION INTERNAL ERROR, +
    00000002,
    .    0000000C, 00F30006
    sql = connect NODB
    from RZ4 S42 NODB
$/tstHookSqlRdr/
*/
    call pipeIni
    call tst t, 'tstHookSqlRdr'
    w = tst_wsh
    m.w.outLen = 99
    m.w.in = jBuf("select 2+3 f5, 'zwei' f2 from sysibm.sysDummy1")
    call wshHook_sqlRdr w
    m.w.in = jBuf("select 2?3 f5, 'zwei' f2 from sysibm.sysDummy1")
    call wshHook_sqlRdr w
    call wshHook_sqlRdr w, 'noDB'
    call tstEnd t
    return
endProcedure tstHookSqlRdr

/****** tstComp *******************************************************
    test the wsh compiler
**********************************************************************/
tstComp: procedure expose m.
    call compIni
    call tstCompDataConst
    call tstCompDataVars
    call tstCompShell
    call tstCompPrimary
    call tstCompExpr
    call tstCompFile
    call tstCompStmt
    call tstCompDir
    call tstCompObj
    call tstCompORun
    call tstCompORu2
    call tstCompORuRe
    call tstCompDataIO
    call tstCompPipe
    call tstCompPip2
    call tstCompRedir
    call tstCompComp
    call tstCompColon
    call tstCompWithNew
    call tstCompSyntax
    if m.err_os == 'TSO' then
        call tstCompSql
    call tstTotal
    return
endProcedure tstComp

tstComp1: procedure expose m.
parse arg ty nm cnt
    c1 = 0
    if cnt = 0 | cnt = '+' then do
        c1 = cnt
        cnt = ''
        end
    call jIni
    src = jBuf()
    call jOpen src, m.j.cWri
    do sx=2 to arg()
        call jWrite src, arg(sx)
        end
    call tstComp2 nm, ty, jClose(src), , c1, cnt
    return
endProcedure tstComp1

tstComp2: procedure expose m.
parse arg nm, spec, src, compSt
    call compIni
    call tst t, nm, compSt
    if src == '' then do
        src = jBuf()
        call tst4dp src'.BUF', mapInline(nm'Src')
        end
    m.t.moreOutOk = abbrev(strip(arg(5)), '+')
    oldErr = m.err.count
    call out 'compile' spec',' (m.src.buf.0) 'lines:' m.src.buf.1
    r = wshHookComp(tstWWWW, spec, src)
    noSyn = m.err.count = oldErr
    coErr = m.t.err
    if noSyn then
        say "compiled" r ":" objMet(r, 'oRun')
    else
        say "*** syntaxed"

    cnt = 0
    do ax = 5 to max(arg(), 5) while m.t.err = coErr & noSyn
        a1 = strip(arg(ax))
        if a1 == '' & arg() >= 5 then
            iterate
        if abbrev(a1, '+') then do
            m.t.moreOutOk = 1
            a1 = strip(substr(a1, 2))
            end
        if datatype(a1, 'n') then
            cnt = a1
        else if a1 \== '' then
            call err 'tstComp2 bad arg('ax')' arg(ax)
        if cnt = 0 then do
            call mCut 'T.IN', 0
            call out "run without input"
            end
        else  do
            call mAdd mCut('T.IN', 0),
                ,"eins zwei drei", "zehn elf zwoelf?",
                , "zwanzig 21 22 23 24 ... 29|"
            do lx=4 to cnt
                call mAdd 'T.IN', left(lx "line" lx, lx+9, '-')';'
                end
            call out "run with" cnt "inputs"
            end
        m.t.inIx = 0
        call oRun r
        end
    call tstEnd t
    return
endProcedure tstComp2

tstCompDataConst: procedure expose m.
/*
$=/tstCompDataConst/
    ### start tst tstCompDataConst ####################################
    compile =, 8 lines:       Lline one, $** asdf
    run without input
    .      Lline one, .
    line two..
    line threecontinued on 4
    line five  fortsetzung
    line six   fortsetzung
$/tstCompDataConst/ */
    call tstComp1 '= tstCompDataConst',
        , '      Lline one, $** asdf',
        , 'line two.',
        , 'line three$*+ bla bla' ,
        , 'continued on 4',
        , 'line five $*( und so',
        , 'weiter $abc $? $''$*)'' $"$*)" und weiter $*) fortsetzung',
        , 'line six  $*( und $*( $** $*( so',
        , 'weiter $abc $? $*)'' $"$*)" und weiter $*) fortsetzung'

/*
$=/tstCompDataConstBefAftComm1/
    ### start tst tstCompDataConstBefAftComm1 #########################
    compile =, 3 lines:     $*(anfangs com.$*)       $*(plus$*) $** x
    run without input
    the only line;
$/tstCompDataConstBefAftComm1/ */
    call tstComp1 '= tstCompDataConstBefAftComm1',
        , '    $*(anfangs com.$*)       $*(plus$*) $** x',
        , 'the only line;',
        , '      $*(end kommentar$*)              '

/*
$=/tstCompDataConstBefAftComm2/
    ### start tst tstCompDataConstBefAftComm2 #########################
    compile =, 11 lines:     $*(anfangs com.$*)       $*(plus$*) $*+ x
    run without input
    the first non empty line;
    tstR: @ obj null
    befor an empty line with comments;
$/tstCompDataConstBefAftComm2/ */

    call tstComp1 '= tstCompDataConstBefAftComm2',
        , '    $*(anfangs com.$*)       $*(plus$*) $*+ x',
        , '    $*(forts Zeile com.$*)       $*(plus$*) $** x',
        , ' $*(comment 2. Zeile$*) $*(plus$*) $*+ x',
        , ' $*(forts Zeile com.$*) $*(plus$*) $** x',
        , 'the first non empty line;',
        , '      ',
        , 'befor an empty line with comments;',
        , ' $*(comment 4. Zeile$*) $*(plus$*) $*+ x',
        , ' $*(forts 4.Zeile com.$*) $*(plus$*) $** x',
        , '      $*(end kommentar$*)              $*+',
        , ' $*(forts end com.$*) $*(plus$*) $** x'
     return
endProcedure tstCompDataComm

tstCompDataVars: procedure expose m.
/*
$=/tstCompDataVars/
    ### start tst tstCompDataVars #####################################
    compile =, 5 lines:       Lline one, $** asdf
    run without input
    .      Lline one, .
    lline zwei output
    lline 3 .
    variable v1 = valueV1 ${v1}= valueV1;
    .      $-{""$v1} = valueV1;
$/tstCompDataVars/ */
    call tstComp1 '= tstCompDataVars',
        , '      Lline one, $** asdf',
        , '   $$ lline zwei output',
        , 'lline 3 $=v1= valueV1 ' ,
        , 'variable v1 = $v1 $"${v1}=" ${  v1  }; ',
        , '      $"$-{""""$v1} =" $-{$""$"v1"}; '
    return
endProcedure tstCompDataVars

tstCompShell: procedure expose m.
/*
$=/tstCompShell3/
    ### start tst tstCompShell3 #######################################
    compile @, 8 lines: call tstOut "T",  "abc" $-[2*3$] "efg"$-[2*3$]"+
    hij"
    run without input
    abc 6 efg6hij
    insert into A540769x.tqt002 with n(n) as ( select 4 from sysibm.s
    insert into A540769x.tqt002 with n(n) as ( select 4 from sysibm.s  +
    .   union all .
    abc 6 efg6hij
$/tstCompShell3/ */
    call tstComp1 '@ tstCompShell3',
        , 'call tstOut "T",  "abc" $-[2*3$] "efg"$-[2*3$]"hij"',
        , 'ix=3' ,
        , 'call tstOut "T","insert into A540769x.tqt002" ,',
        ,     '"with n(n) as ( select" $-[ix+1$] "from sysibm.s"',
        , 'call tstOut "T","insert into A540769x.tqt002"  ,  ',
        ,    '"with n(n) as ( select" $-[ix+1$] "from sysibm.s" , ' ,
        ,    '"    union all "' ,
        , '$$ abc $-[2*3$] efg$-[2*3$]hij',
/*
$=/tstCompShell/
    ### start tst tstCompShell ########################################
    compile @, 12 lines:   $$  Lline one, $** asdf
    run without input
    Lline one,
    lline zwei output
    v1 = valueV1 ${v1}= valueV1|
    REXX OUT L5 CONTINUED L6 CONTINUED L7
    L8 ONE
    L9 TWO
    valueV1
    valueV1 valueV2
    out  valueV1 valueV2
    SCHLUSS
$/tstCompShell/ */
    call tstComp1 '@ tstCompShell',
        , '  $$  Lline one, $** asdf',
        , '   $$ lline zwei output',
        , '        $=v1= valueV1 ' ,
        , '$$       v1 = $v1 $"${v1}=" ${  v1  }| ' ,
        , 'call out rexx out l5, ' ,
        , '     continued l6 , ' ,
        , '     continued l7   ' ,
        , 'call out l8 one    ' ,
        , 'call out l9 two$=v2=valueV2  ',
        , '$$- $v1  $$- $v1 $v2   ',
        , 'call out   "out "     $v1 $v2   ',
        , '$$-   schluss    '
/*
$=/tstCompShell2/
    ### start tst tstCompShell2 #######################################
    compile @, 13 lines: $@do j=0 to 1 $@[ $$ do j=$j
    run without input
    do j=0
    after if 0 $@[ $]
    after if 0 $=@[ $]
    do j=1
    if 1 then $@[ a
    a2
    if 1 then $@=[ b
    b2
    after if 1 $@[ $]
    after if 1 $=@[ $]
    end
$/tstCompShell2/ */
    call tstComp1 '@ tstCompShell2',
        , '$@do j=0 to 1 $@[ $$ do j=$j' ,
        ,     'if $j then $@[ ',
        ,          '$$ if $j then $"$@[" a $$a2' ,
        ,          '$]',
        ,     'if $j then $@=[ ',
        ,          '$$ if $j then $"$@=[" b $$b2' ,
        ,          '$]',
        ,     'if $j then $@[ $]' ,
        ,     '$$ after if $j $"$@[ $]"' ,
        ,     'if $j then $@=[ $]' ,
        ,     '$$ after if $j $"$=@[ $]"' ,
        ,     '$]',
        , '$$ end'
    return
endProcedure tstCompShell

tstCompPrimary: procedure expose m.
    call compIni
/*
$=/tstCompPrimary/
    ### start tst tstCompPrimary ######################################
    compile =, 16 lines: Strings $"$""$""""$""" $'$''$''''$'''
    run without input
    Strings $"$""$" $'$''$'
    rexx $-[ 3 * 5 $] = 15
    rexx $-[ 5 * 7 $] = 35
    rexx $-// 7 * 11 $// = 77
    rexx $-/abcEf/ 11 * 13 $/abcEf/ = 143
    data  line three line four  bis hier
    shell line five line six bis hier
    var get   v1 value Eins, v1 value Eins
    var isDef v1 1, v2 0
    #jIn eof 1#
    var read  >1 0 rr undefined
    #jIn eof 2#
    var read  >2 0 rr undefined
    no call abc$-[4*5$] $-[efg$-[6*7$] abc20 EFG42
    brackets $-[$-[1+9$]*$-[7+3$]*$-/b/5+5$/b/$] 1000
    run with 3 inputs
    Strings $"$""$" $'$''$'
    rexx $-[ 3 * 5 $] = 15
    rexx $-[ 5 * 7 $] = 35
    rexx $-// 7 * 11 $// = 77
    rexx $-/abcEf/ 11 * 13 $/abcEf/ = 143
    data  line three line four  bis hier
    shell line five line six bis hier
    var get   v1 value Eins, v1 value Eins
    var isDef v1 1, v2 0
    #jIn 1# eins zwei drei
    var read  >1 1 rr eins zwei drei
    #jIn 2# zehn elf zwoelf?
    var read  >2 1 rr zehn elf zwoelf?
    no call abc$-[4*5$] $-[efg$-[6*7$] abc20 EFG42
    brackets $-[$-[1+9$]*$-[7+3$]*$-/b/5+5$/b/$] 1000
$/tstCompPrimary/ */
    call vRemove 'v2'
    call tstComp1 '= tstCompPrimary 3',
        , 'Strings $"$""$""""$"""' "$'$''$''''$'''",
        , 'rexx $"$-[ 3 * 5 $] =" $-[ 3 * 5 $]' ,
        , 'rexx $"$-[ 5 * 7 $] =" $-[ 5 * 7 $]' ,
        , 'rexx $"$-// 7 * 11 $// =" $-// 7 * 11 $//' ,
        , 'rexx $"$-/abcEf/ 11 * 13 $/abcEf/ ="',
            '$-/abcEf/ 11 * 13 $/abcEf/' ,
        , 'data $-=[ line three',
        , 'line four $] bis hier'  ,
        , 'shell $-@[ $$ line five',
        , '$$ line six $] bis hier' ,
        , '$= v1  =   value Eins  $=rr=undefined $= eins = 1 ',
        , 'var get   v1 $v1, v1 ${  v1  } ',
        , 'var isDef v1 ${? v${  eins  }  }, v2 ${?v2 } ',
        , 'var read  >1 ${> rr} rr $rr' ,
        , 'var read  >2 ${> rr} rr $rr',
        , 'no call $"abc$-[4*5$] $-[efg$-[6*7$]"',
            'abc$-[4*5$] $-[efg$-[6*7$]$]',
        , 'brackets $"$-[$-[1+9$]*$-[7+3$]*$-/b/5+5$/b/$]"',
            '$-[$-[1+9$]*$-[7+3$]*$-/b/5+5$/b/$]'
    return
endProcedure tstCompPrimary

tstCompExpr: procedure expose m.
    call compIni
/*
$=/tstCompExprStr/
    ### start tst tstCompExprStr ######################################
    compile -, 3 lines: $=vv=vvStr
    run without input
    vv=vvStr
    o2String($.-vv)=vvStr
$/tstCompExprStr/ */
    call tstComp1 '- tstCompExprStr',
        , '$=vv=vvStr' ,
        , '"vv="$vv' ,
        , '$"o2String($.-vv)="o2String($.-vv)'
/*
$=/tstCompExprObj/
    ### start tst tstCompExprObj ######################################
    compile ., 5 lines: $=vv=vvStr
    run without input
    vv=
    vvStr
    s2o($.vv)=
    vvStr
$/tstCompExprObj/ */
    call tstComp1 '. tstCompExprObj',
        , '$=vv=vvStr' ,
        , '"]vv="', '$.-vv',
        , '$."s2o($.vv)="', 's2o($-vv)'
/*
$=/tstCompExprDat/
    ### start tst tstCompExprDat ######################################
    compile =, 4 lines: $=vv=vvDat
    run without input
    vv=vvDat
    $.-vv= ]vvDat
    $.-["abc"$]=]abc
$/tstCompExprDat/ */
    call tstComp1 '= tstCompExprDat',
        , '$=vv=vvDat' ,
        , 'vv=$vv',
        , '$"$.-vv=" $.-vv',
        , '$"$.-[""abc""$]="$.-["abc"$]'

/*
$=/tstCompExprRun/
    ### start tst tstCompExprRun ######################################
    compile @, 3 lines: $=vv=vvRun
    run without input
    vv=vvRun
    o2string($.-vv)=vvRun
$/tstCompExprRun/ */
    call tstComp1 '@ tstCompExprRun',
        , '$=vv=vvRun' ,
        , 'call out "vv="$vv',
        , 'call out $"o2string($.-vv)="o2string($.-vv)'
/*
$=/tstCompExprCon/
    ### start tst tstCompExprCon ######################################
    compile #, 2 lines: $$ in # drinnen
    run without input
    $$ in # drinnen
    call out "vv="$vv
$/tstCompExprCon/
$=/tstCompExprCo2/
    ### start tst tstCompExprCo2 ######################################
    compile #, 3 lines: $$ in # drinnen
    run without input
    $$ in # drinnen
    call out "vv="$vv
    nacgh $#@
$/tstCompExprCo2/
*/
    call tstComp1 '# tstCompExprCon',
        , '$$ in # drinnen' ,
        , 'call out "vv="$vv'

    call tstComp1 '# tstCompExprCo2',
        , '$$ in # drinnen' ,
        , 'call out "vv="$vv',
        , '$#@ $$ nacgh $"$#@"'

    return
endProcedure tstCompExpr

tstCompStmt: procedure expose m.
/*
$=/tstCompStmt1/
    ### start tst tstCompStmt1 ########################################
    compile @, 8 lines: $= v1 = value eins  $= v2  =- 3*5*7 .
    run without input
    data v1 value eins v2 105
    eins
    zwei
    drei
    vier
    fuenf
    elf
    . zwoelf  dreiZ  .
    . vierZ .
    fuenfZ
    lang v1 value eins v2 945
    oRun ouput 1
$/tstCompStmt1/ */
    call pipeIni
    call compIni
    call vPut 'oRun', oRunner('call out "oRun ouput" (1*1)')
    call vRemove 'v2'
    call tstComp1 '@ tstCompStmt1',
        , '$= v1 = value eins  $= v2  =- 3*5*7 ',
        , '$$ data v1 $v1 v2 ${   v2  }',
        , '$$eins $@[$$ zwei $$ drei  ',
        , '   $@[   $]  $@//   $// $@/q r s /   $/q r s /',
             '       $@/eins/ $@[ $$vier $] $/eins/ $] $$fuenf',
        , '$$elf $@=[$@=[ zwoelf  dreiZ  $]  ',
        , '   $@=[   $] $@=[ $@=[ vierZ $] $] $] $$fuenfZ',
        , '$$- "lang v1" $v1 "v2" ${v2}*9',
        , '$@oRun'
/*
$=/tstCompStmt2/
    ### start tst tstCompStmt2 ########################################
    compile @, 1 lines: $@for qq $$ loop qq $qq
    run without input
    #jIn eof 1#
    run with 3 inputs
    #jIn 1# eins zwei drei
    loop qq eins zwei drei
    #jIn 2# zehn elf zwoelf?
    loop qq zehn elf zwoelf?
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    loop qq zwanzig 21 22 23 24 ... 29|
    #jIn eof 4#
$/tstCompStmt2/ */
    call tstComp1 '@ tstCompStmt2 3',
        , '$@for qq $$ loop qq $qq'

/*
$=/tstCompStmt3/
    ### start tst tstCompStmt3 ########################################
    compile @, 9 lines: $$ 1 begin run 1
    2 ct zwei
    ct 4 mit assign .
    run without input
    1 begin run 1
    3 run 3 ctV = ct 4 assign ctV|
    run 5 procCall $@prCa
    out in proc at 8
    run 6 vor call $@prCa
    out in proc at 8
    9 run end
    run with 3 inputs
    1 begin run 1
    3 run 3 ctV = ct 4 assign ctV|
    run 5 procCall $@prCa
    out in proc at 8
    run 6 vor call $@prCa
    out in proc at 8
    9 run end
$/tstCompStmt3/ */
    call tstComp1 '@ tstCompStmt3 3',
        , '$$ 1 begin run 1',
        , '$@ct $$ 2 ct zwei',
        , '$$ 3 run 3 ctV = $ctV|',
        , '$@ct $@=[ct 4 mit assign $=ctV = ct 4 assign ctV $]',
        , '$$ run 5 procCall $"$@prCa" $@prCa',
        , '$$ run 6 vor call $"$@prCa"',
        , '$@prCa',
        , '$@proc prCa $$out in proc at 8',
        , '$$ 9 run end'

/*
$=/tstCompStmt4/
    ### start tst tstCompStmt4 ########################################
    compile @, 4 lines: $=eins=vorher
    run without input
    eins vorher
    eins aus named block eins .
$/tstCompStmt4/ */
    call tstComp1 '@ tstCompStmt4 0',
        , '$=eins=vorher' ,
        , '$$ eins $eins' ,
        , '$=/eins/aus named block eins $/eins/' ,
        , '$$ eins $eins'
/*
$=/tstCompStmtDo/
    ### start tst tstCompStmtDo #######################################
    compile @, 2 lines: ti=0$@do y=3 to 4 $@do 2 $@[
    run without input
    y=3 ti1 z=7
    y=3 ti1 z=8
    y=3 ti2 z=7
    y=3 ti2 z=8
    y=4 ti3 z=7
    y=4 ti3 z=8
    y=4 ti4 z=7
    y=4 ti4 z=8
$/tstCompStmtDo/ */
    call tstComp1 '@ tstCompStmtDo', 'ti=0$@do y=3 to 4 $@do 2 $@[',
     ,    'ti = ti + 1',
        '$@do $*(sdf$*) z $*(sdf$*) =7 to 8 $$ y=$y ti$-[ti$] z=$z $]'

/*
$=/tstCompStmtDo2/
    ### start tst tstCompStmtDo2 ######################################
    compile @, 7 lines: $$ $-=/sqlSel/
    run without input
    select 1 abc select 2 abc after table .
$/tstCompStmtDo2/ */
    call tstComp1 '@ tstCompStmtDo2',
         , '$$ $-=/sqlSel/',
         ,     '$=ty = abc ',
         ,     '$@do tx=1 to 2 $@=/table/',
         ,          'select $tx $ty',
         , '$/table/',
         ,     '$=ty = abc',
         ,     'after table',
         '$/sqlSel/'
/*
$=/tstCompStmtWith/
    ### start tst tstCompStmtWith #####################################
    compile @, 3 lines: $@with $.vA $$ fEins=$FEINS fZwei=$FZWEI va&fEi+
    ns=${vA&FEINS}
    run without input
    fEins=1Eins fZwei=1Zwei va&fEins=1Eins
    fEins=1Eins fZwei=1Zwei va&fEins=1Eins
    fEins=2Eins fZwei=2Zwei va&fEins=1Eins
    fEins=1Eins fZwei=1Zwei va&fEins=1Eins
$/tstCompStmtWith/
*/
    cl = classNew('n? tstStmtWith u f FEINS v, f FZWEI v')
    v1 = onew(cl)
    m.v1.feins = '1Eins'
    m.v1.fzwei = '1Zwei'
    v2 = oNew(cl)
    m.v2.feins ='2Eins'
    m.v2.fzwei ='2Zwei'
    call vPut 'vA', v1
    call vPut 'vB', v2
    stmt = '$$ fEins=$FEINS fZwei=$FZWEI va&fEins=${vA&FEINS}'
    call tstComp1 '@ tstCompStmtWith',
         , '$@with $.vA' stmt ,
         , '$@with $vA $@[' stmt ,
         , '$@with $vB ' stmt stmt '$]'
/*
$=/tstCompStmtArg/
    ### start tst tstCompStmtArg ######################################
    compile :, 11 lines: v2 = var2
    run without input
    a1=eins a2=zwei, a3=elf b1= b2=
    after op= v2=var2 var2=zwei,
    a1=EINS a2=ZWEI a3= b1=ELF b2=
    after op=- v2=var2 var2=ZWEI
    a1=EINS a2=ZWEI a3= b1=ELF b2=
    after op=. v2=var2 var2=ZWEI
$/tstCompStmtArg/
*/
    call tstComp1 ': tstCompStmtArg',
         , 'v2 = var2',
         , '@% outArg eins zwei, elf',
         , '$$ after op= v2=$v2 var2=$var2',
         , '@% outArg - eins zwei, elf',
         , '$$ after op=- v2=$v2 var2=$var2',
         , '@% outArg . eins zwei, elf',
         , '$$ after op=. v2=$v2 var2=$var2',
         , 'proc $@:/outArg/' ,
         , 'arg a1 {$v2} a3, b1 b2',
         , '$$ a1=$a1 a2=${$v2} a3=$a3 b1=$b1 b2=$b2' ,
         , '$/outArg/'
     cl = classNew('n? tstStmtWith u f FEINS v, f FZWEI v')
     return
endProcedure tstCompStmt

tstCompProc: procedure expose m.
/*
$=/tstCompProc1/
    ### start tst tstCompProc1 ########################################
    compile =, 11 lines: $$ vor1
    run without input
    vor1
    called p1 eins
    vor2
    tstR: @ obj null
    vor3
    .   called p3 drei
    vor4
    . called p2 .
    vor9 endof
$/tstCompProc1/  */
    call pipeIni
    call compIni
    call tstComp1 '= tstCompProc1',
         , "$$ vor1",
         , "$@% p1 eins $$vor2 $@% p2 zwei $$vor3 $@% p3 drei",
         , "$$ vor4 $proc p1 $$- 'called p1' arg(2)",
         , "$proc p2", " ", "$** a", "$*(b$*) called p2 $-[arg(2)$]",
         , "$proc p3    ", "$** a", "  $*(b$*) called p3 $-[arg(2)$]",
         , "$$ vor9 endof"
    return
endProcedure tstCompProc

tstCompSyntax: procedure expose m.
    call pipeIni
    call tstCompSynPrimary
    call tstCompSynAss
    call tstCompSynRun
    return
endProcedure tstCompSyntax

tstCompSynPrimary: procedure expose m.

/*
$=/tstCompSynPri1/
    ### start tst tstCompSynPri1 ######################################
    compile @, 1 lines: a $ =
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $ =
    .    e 2: pos 3 in line 1: a $ =
$/tstCompSynPri1/ */
    call tstComp1 '@ tstCompSynPri1 +', 'a $ ='

/*
$=/tstCompSynPri2/
    ### start tst tstCompSynPri2 ######################################
    compile @, 1 lines: a $. {
    *** err: scanErr primary block or expression expected expected
    .    e 1: last token  scanPosition . {
    .    e 2: pos 4 in line 1: a $. {
    *** err: scanErr primary block or expression expected expected
    .    e 1: last token  scanPosition . {
    .    e 2: pos 4 in line 1: a $. {
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $. {
    .    e 2: pos 3 in line 1: a $. {
$/tstCompSynPri2/ */
    call tstComp1 '@ tstCompSynPri2 +', 'a $. {'

/*
$=/tstCompSynPri3/
    ### start tst tstCompSynPri3 ######################################
    compile @, 1 lines: b $-  [  .
    *** err: scanErr primary block or expression expected expected
    .    e 1: last token  scanPosition -  [
    .    e 2: pos 4 in line 1: b $-  [
    *** err: scanErr primary block or expression expected expected
    .    e 1: last token  scanPosition -  [
    .    e 2: pos 4 in line 1: b $-  [
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $-  [
    .    e 2: pos 3 in line 1: b $-  [
$/tstCompSynPri3/ */
    call tstComp1 '@ tstCompSynPri3 +', 'b $-  [  '

/*
$=/tstCompSynPri4/
    ### start tst tstCompSynPri4 ######################################
    compile @, 1 lines: a ${ $*( sdf$*) } =
    *** err: scanErr var name expected
    .    e 1: last token  scanPosition } =
    .    e 2: pos 17 in line 1: a ${ $*( sdf$*) } =
$/tstCompSynPri4/ */
    call tstComp1 '@ tstCompSynPri4 +', 'a ${ $*( sdf$*) } ='

/*
$=/tstCompSynFile/
    ### start tst tstCompSynFile ######################################
    compile @, 1 lines: $@.<$*( co1 $*) $$abc
    *** err: scanErr primary, block or expression expected
    .    e 1: last token  scanPosition .<$*( co1 $*) $$abc
    .    e 2: pos 3 in line 1: $@.<$*( co1 $*) $$abc
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $@.<$*( co1 $*) $$abc
    .    e 2: pos 1 in line 1: $@.<$*( co1 $*) $$abc
$/tstCompSynFile/ */
    call tstComp1 '@ tstCompSynFile +', '$@.<$*( co1 $*) $$abc'

    return
endProcedure tstCompSynPrimary

tstCompSynAss: procedure expose m.

/*
$=/tstCompSynAss1/
    ### start tst tstCompSynAss1 ######################################
    compile @, 1 lines: $=
    *** err: scanErr block or expression in assignment after $= expecte+
    d
    .    e 1: last token  scanPosition .
    .    e 2: pos 3 in line 1: $=
$/tstCompSynAss1/ */
    call tstComp1 '@ tstCompSynAss1 +', '$='

/*
$=/tstCompSynAss2/
    ### start tst tstCompSynAss2 ######################################
    compile @, 2 lines: $=   .
    *** err: scanErr block or expression in assignment after $= expecte+
    d
    .    e 1: last token  scanPosition .
    .    e 2: pos 3 in line 1: $=
$/tstCompSynAss2/ */
    call tstComp1 '@ tstCompSynAss2 +', '$=   ', 'eins'

/*
$=/tstCompSynAss3/
    ### start tst tstCompSynAss3 ######################################
    compile @, 2 lines: $=   $$
    *** err: scanErr block or expression in assignment after $= expecte+
    d
    .    e 1: last token  scanPosition $$
    .    e 2: pos 6 in line 1: $=   $$
$/tstCompSynAss3/ */
    call tstComp1 '@ tstCompSynAss3 +', '$=   $$', 'eins'

/*
$=/tstCompSynAss4/
    ### start tst tstCompSynAss4 ######################################
    compile @, 1 lines: $=   eins
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $=   eins
    .    e 2: pos 1 in line 1: $=   eins
$/tstCompSynAss4/ */
call tstComp1 '@ tstCompSynAss4 +', '$=   eins'

/*
$=/tstCompSynAss5/
    ### start tst tstCompSynAss5 ######################################
    compile @, 1 lines: $=  abc eins $$ = x
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $=  abc eins $$ = x
    .    e 2: pos 1 in line 1: $=  abc eins $$ = x
$/tstCompSynAss5/
$=/tstCompSynAss5old/
    ### start tst tstCompSynAss5 ######################################
    compile @, 1 lines: $=  abc eins $$ = x
    *** err: scanErr = expected in assignment after $= var
    .    e 1: last token  scanPosition eins $$ = x
    .    e 2: pos 9 in line 1: $=  abc eins $$ = x
$/tstCompSynAss5old/ */
    call tstComp1 '@ tstCompSynAss5 +', '$=  abc eins $$ = x'

/*
$=/tstCompSynAss6/
    ### start tst tstCompSynAss6 ######################################
    compile @, 1 lines: $=  abc =
    *** err: scanErr block or expression in assignment after $= expecte+
    d
    .    e 1: last token  scanPosition .
    .    e 2: pos 10 in line 1: $=  abc =
$/tstCompSynAss6/ */
    call tstComp1 '@ tstCompSynAss6 +', '$=  abc ='

/*
$=/tstCompSynAss7/
    ### start tst tstCompSynAss7 ######################################
    compile @, 1 lines: $=  abc =..
    *** err: scanErr block or expression in assignment after $= expecte+
    d
    .    e 1: last token  scanPosition .
    .    e 2: pos 11 in line 1: $=  abc =..
$/tstCompSynAss7/ */
    call tstComp1 '@ tstCompSynAss7 +', '$=  abc =.'
    return
endProcedure tstCompSynAss

tstCompSynRun: procedure expose m.

/*
$=/tstCompSynRun1/
    ### start tst tstCompSynRun1 ######################################
    compile @, 1 lines: $@
    *** err: scanErr primary, block or expression expected
    .    e 1: last token  scanPosition .
    .    e 2: pos 3 in line 1: $@
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $@
    .    e 2: pos 1 in line 1: $@
$/tstCompSynRun1/ */
    call tstComp1 '@ tstCompSynRun1 +', '$@'

/*
$=/tstCompSynRun2/
    ### start tst tstCompSynRun2 ######################################
    compile @, 1 lines: $@=
    *** err: scanErr primary, block or expression expected
    .    e 1: last token  scanPosition =
    .    e 2: pos 3 in line 1: $@=
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $@=
    .    e 2: pos 1 in line 1: $@=
$/tstCompSynRun2/ */
    call tstComp1 '@ tstCompSynRun2 +', '$@='

/*
$=/tstCompSynRun3/
    ### start tst tstCompSynRun3 ######################################
    compile @, 1 lines: $@: und
    *** err: scanErr bad kind : in compExpr
    .    e 1: last token  scanPosition und
    .    e 2: pos 5 in line 1: $@: und
    fatal error in wsM: compAst2rx bad ops=]) kind=M.0.KIND ast=0
    *** err: bad ast 0
    *** err: compAst2rx bad ops=]) kind=M.0.KIND ast=0
$/tstCompSynRun3/ */
    call tstComp1 '@ tstCompSynRun3 +', '$@: und'

/*
$=/tstCompSynFor4/
    ### start tst tstCompSynFor4 ######################################
    compile @, 1 lines: $@for
    *** err: scanErr var? statement after for expected
    .    e 1: last token  scanPosition .
    .    e 2: atEnd after line 1: $@for
$/tstCompSynFor4/ */
    call tstComp1 '@ tstCompSynFor4 +', '$@for'

/*
$=/tstCompSynFor5/
    ### start tst tstCompSynFor5 ######################################
    compile @, 2 lines: $@for
    *** err: scanErr var? statement after for expected
    .    e 1: last token  scanPosition .
    .    e 2: pos 6 in line 1: $@for
$/tstCompSynFor5/
    call tstComp1 '@ tstCompSynFor5 +', '$@for', a


$=/tstCompSynFor6/
    ### start tst tstCompSynFor6 ######################################
    compile @, 2 lines: a
    *** err: scanErr variable or named block after for
    .    e 1: last token  scanPosition .
    .    e 2: pos 15 in line 2:  b $@for   $$q
$/tstCompSynFor6/
    call tstComp1 '@ tstCompSynFor6 +', 'a', ' b $@for   $$q'
*/
/*
$=/tstCompSynFor7/
    ### start tst tstCompSynFor7 ######################################
    compile @, 3 lines: a
    *** err: scanErr var? statement after for expected
    .    e 1: last token  scanPosition .
    .    e 2: pos 11 in line 2:  b $@for a
$/tstCompSynFor7/
    call tstComp1 '@ tstCompSynFor7 +', 'a', ' b $@for a', '  $$q'

$=/tstCompSynCt8/
    ### start tst tstCompSynCt8 #######################################
    compile @, 3 lines: a
    *** err: scanErr ct statement expected
    .    e 1: last token  scanPosition .
    .    e 2: atEnd after line 3: .
$/tstCompSynCt8/ */
    call tstComp1 '@ tstCompSynCt8 +', 'a', ' b $@ct', '     '

/*
$=/tstCompSynProc9/
    ### start tst tstCompSynProc9 #####################################
    compile @, 3 lines: a
    *** err: scanErr proc statement expected
    .    e 1: last token  scanPosition .
    .    e 2: atEnd after line 3: $**x
$/tstCompSynProc9/ */
    call tstComp1 '@ tstCompSynProc9 +', 'a', ' b $@proc  ' , '$**x'

/*
$=/tstCompSynProcA/
    ### start tst tstCompSynProcA #####################################
    compile @, 2 lines: $@proc p1
    *** err: scanErr proc statement expected
    .    e 1: last token  scanPosition .
    .    e 2: pos 10 in line 1: $@proc p1
$/tstCompSynProcA/
    call tstComp1 '@ tstCompSynProcA +', '$@proc p1', '$$'

$=/tstCompSynCallB/
    ### start tst tstCompSynCallB #####################################
    compile @, 1 lines: $@% [roc p1$]
    *** err: scanErr primary, block or expression expected
    .    e 1: last token  scanPosition % [roc p1$]
    .    e 2: pos 3 in line 1: $@% [roc p1$]
    *** err: scanErr wsh kindExe'@' expected: compile stopped before en+
    d of input
    .    e 1: last token  scanPosition $@% [roc p1$]
    .    e 2: pos 1 in line 1: $@% [roc p1$]
$/tstCompSynCallB/ */
    call tstComp1 '@ tstCompSynCallB +', '$@% [roc p1$]'

/*
$=/tstCompSynCallC/
    ### start tst tstCompSynCallC #####################################
    compile @, 1 lines: $@%[call roc p1 ]
    *** err: scanErr ending $] expected after [
    .    e 1: last token  scanPosition .
    .    e 2: atEnd after line 1: $@%[call roc p1 ]
$/tstCompSynCallC/ */
    call tstComp1 '@ tstCompSynCallC +', '$@%[call roc p1 ]'

/*
$=/tstCompSynCallD/
    ### start tst tstCompSynCallD #####################################
    compile @, 2 lines: $@^[call( $** roc
    *** err: scanErr ending $] expected after [
    .    e 1: last token  scanPosition )
    .    e 2: pos 13 in line 2:  $*( p1 $*) )
$/tstCompSynCallD/ */
    call tstComp1 '@ tstCompSynCallD +',
        ,'$@^[call( $** roc' , ' $*( p1 $*) )'
    return
endProcedure tstCompSynRun

tstCompObj: procedure expose m.
    call tstReset t
    call classIni
    cl = classNew('n? tstCompCla u v, f FEINS v, f FZWEI v')
    do rx=1 to 10
        o = oNew(cl)
        m.tstComp.rx = o
        m.o = 'o'rx
        if rx // 2 = 0 then do
            m.o.fEins = 'o'rx'.1'
            m.o.fZwei = 'o'rx'.fZwei'rx
            end
        else do
            m.o.fEins = 'o'rx'.fEins'
            m.o.fZwei = 'o'rx'.2'
            end
        call mAdd 'T.TRANS', m.tstComp.rx '<o'rx'>'
        end

/*
$=/tstCompObjRef/
    ### start tst tstCompObjRef #######################################
    compile @, 13 lines: o1=m.tstComp.1
    run without input
    out .$"string" o1
    string
    out . o1
    tstR: @<o1> isA :tstCompCla = o1
    tstR:  .FEINS = o1.fEins
    tstR:  .FZWEI = o1.2
    out .{ o2 }
    tstR: @<o2> isA :tstCompCla = o2
    tstR:  .FEINS = o2.1
    tstR:  .FZWEI = o2.fZwei2
    out .[ o3 $]
    tstR: @<o3> isA :tstCompCla = o3
    tstR:  .FEINS = o3.fEins
    tstR:  .FZWEI = o3.2
    out .[ o4 $]
    tstR: @<o4> isA :tstCompCla = o4
    tstR:  .FEINS = o4.1
    tstR:  .FZWEI = o4.fZwei4
    out ./-/ o5 $/-/
    tstR: @<o5> isA :tstCompCla = o5
    tstR:  .FEINS = o5.fEins
    tstR:  .FZWEI = o5.2
$/tstCompObjRef/ */
m.ttt=1
    call tstComp1 '@ tstCompObjRef' ,
        , 'o1=m.tstComp.1',
        , 'o2 = m.tstComp.2' ,
        , '$$ out $".$""string""" o1 $$."string"',
        , '$$ out . o1 $$. o1',
        , '$$ out .{ o2 } $$.[ o2 $]',
        , '$$ out .[ o3 $"$]" $$.[ ', ' m.tstComp.3 ', ' $]',
        , '$$ out .[ o4 $"$]" $$.[ ', ' m.tstComp.4 ', ' $]',
        , '$$ out ./-/ o5 $"$/-/" $$./-/  m.tstComp.5 ', ' $/-/'

/*
$=/tstCompObjRefPri/
    ### start tst tstCompObjRefPri ####################################
    compile @, 9 lines: $$ out .$"$.{o1}" $$.[ m.tstComp.1 $]
    run without input
    out .$.{o1}
    tstR: @<o1> isA :tstCompCla = o1
    tstR:  .FEINS = o1.fEins
    tstR:  .FZWEI = o1.2
    out .$.-{o2}
    <o2>
    out .$.={o3}
    . m.tstComp.3 .
    out .$.@{out o4}
    tstWriteO kindOf ORun oRun begin <<<
    tstR: @<o4> isA :tstCompCla = o4
    tstR:  .FEINS = o4.1
    tstR:  .FZWEI = o4.fZwei4
    tstWriteO kindOf ORun oRun end   >>>
    out .$.@[$$abc $$efg$]
    tstWriteO kindOf ORun oRun begin <<<
    abc
    efg
    tstWriteO kindOf ORun oRun end   >>>
    out .$.@[o5$]
    tstWriteO kindOf ORun oRun begin <<<
    tstR: @<o5> isA :tstCompCla = o5
    tstR:  .FEINS = o5.fEins
    tstR:  .FZWEI = o5.2
    abc
    tstWriteO kindOf ORun oRun end   >>>
$/tstCompObjRefPri/ */
    call tstComp1 '@ tstCompObjRefPri' ,
        , '$$ out .$"$.{o1}" $$.[ m.tstComp.1 $]',
        , '$$ out .$"$.-{o2}" $$.-[ m.tstComp.2 $]',
        , '$$ out .$"$.={o3}" $$.=[ m.tstComp.3 $]',
        , '$$ out .$"$.@{out o4}" $$.@@[ call out m.tstComp.4 $]',
    , '$$ out .$"$.@[$$abc $$efg$]" $$. $.@@[ $$abc ', ' ',' $$efg $]',
        , '$$ out .$"$.@[o5$]" $$. $.@@[ $$. m.tstComp.5', '$$abc $]'

/*
$=/tstCompObjRefFile/
    ### start tst tstCompObjRefFile ###################################
    compile @, 7 lines: $$ out .$".<.[o1]" $$.<.[ m.tstComp.1 $]
    run without input
    out ..<.[o1]
    tstWriteO kindOf JRW jWriteNow begin <<<
    tstR: @<o1> isA :tstCompCla = o1
    tstR:  .FEINS = o1.fEins
    tstR:  .FZWEI = o1.2
    tstWriteO kindOf JRW jWriteNow end   >>>
    out .<$.-{o2}
    tstWriteO kindOf JRW jWriteNow begin <<<
    tstR: @<o2> isA :tstCompCla = o2
    tstR:  .FEINS = o2.1
    tstR:  .FZWEI = o2.fZwei2
    tstWriteO kindOf JRW jWriteNow end   >>>
    out .$.<{o3}
    tstWriteO kindOf JRW jWriteNow begin <<<
    . m.tstComp.3 .
    tstWriteO kindOf JRW jWriteNow end   >>>
    out .$.<@{out o4}
    tstWriteO kindOf JRW jWriteNow begin <<<
    tstR: @<o4> isA :tstCompCla = o4
    tstR:  .FEINS = o4.1
    tstR:  .FZWEI = o4.fZwei4
    tstWriteO kindOf JRW jWriteNow end   >>>
    out .$<@[$$abc $$efg$]
    tstWriteO kindOf JRW jWriteNow begin <<<
    abc
    efg
    tstWriteO kindOf JRW jWriteNow end   >>>
$/tstCompObjRefFile/ */

    call tstComp1 '@ tstCompObjRefFile' ,
        , '$$ out .$".<.[o1]" $$.<.[ m.tstComp.1 $]',
        , '$$ out .$"<$.-{o2}" $$<.[ m.tstComp.2 $]',
        , '$$ out .$"$.<{o3}" $$<=[ m.tstComp.3 $]',
        , '$$ out .$"$.<@{out o4}" $$<@[ call out m.tstComp.4 $]',
    , '$$ out .$"$<@[$$abc $$efg$]" $$<@[ $$abc ', ' ', ' $$efg $]'

/*
$=/tstCompObjFor/
    ### start tst tstCompObjFor #######################################
    compile @, 2 lines: $@do rx=1 to 3 $$. m.tstComp.rx
    run without input
    FEINS=o1.fEins FZWEI=o1.2
    FEINS=o2.1 FZWEI=o2.fZwei2
    FEINS=o3.fEins FZWEI=o3.2
$/tstCompObjFor/
*/
    call tstComp1 '@ tstCompObjFor' ,
        , '$@do rx=1 to 3 $$. m.tstComp.rx' ,
        , '$| $@forWith witx $$ FEINS=$FEINS FZWEI=$FZWEI'

/*
$=/tstCompObjRun/
    ### start tst tstCompObjRun #######################################
    compile @, 4 lines: $$ out .$"$@[o1]" $$@[ $$. m.tstComp.1 $]
    run without input
    out .$@[o1]
    tstWriteO kindOf ORun oRun begin <<<
    tstR: @<o1> isA :tstCompCla = o1
    tstR:  .FEINS = o1.fEins
    tstR:  .FZWEI = o1.2
    tstWriteO kindOf ORun oRun end   >>>
    out .$<@[$$abc $$efg$]
    tstWriteO kindOf JRW jWriteNow begin <<<
    abc
    efg
    tstWriteO kindOf JRW jWriteNow end   >>>
$/tstCompObjRun/ */
    call tstComp1 '@ tstCompObjRun' ,
        , '$$ out .$"$@[o1]" $$@[ $$. m.tstComp.1 $]',
    , '$$ out .$"$<@[$$abc $$efg$]" $$<@[ $$abc ', ' ', ' $$efg $]'

    m.t.trans.0 = 0
/*
$=/tstCompObj/
    ### start tst tstCompObj ##########################################
    compile @, 6 lines: o1=m.tstComp.1
    run without input
    out . o1
    tstR: @tstWriteoV1 isA :tstCompCla = o1
    tstR:  .FEINS = o1.fEins
    tstR:  .FZWEI = o1.2
    out .{ o2 }
    tstR: @tstWriteoV2 isA :tstCompCla = o2
    tstR:  .FEINS = o2.1
    tstR:  .FZWEI = o2.fZwei2
    out .[ o1, o2]
    tstR: @tstWriteoV1 isA :tstCompCla = o1
    tstR:  .FEINS = o1.fEins
    tstR:  .FZWEI = o1.2
    tstR: @tstWriteoV2 isA :tstCompCla = o2
    tstR:  .FEINS = o2.1
    tstR:  .FZWEI = o2.fZwei2
$/tstCompObj/ */
    call tstComp1 '@ tstCompObj' ,
        , 'o1=m.tstComp.1',
        , 'o2 = m.tstComp.2' ,
        , '$$ out . o1 $$. o1',
        , '$$ out .{ o2 } $$.[ o2 $]',
    , '$$ out .[ o1, o2]$; $@.[  m.tstComp.1  ', '  m.tstComp.2  $]'
    return
    m.t.trans.0 = 0
endProcedure tstCompObj

tstCompORun: procedure expose  m.
/*
$=/tstCompORun/
    ### start tst tstCompORun #########################################
    compile @, 6 lines: $@oRun
    run without input
    oRun arg=1, v2=, v3=, v4=
    oRun arg=1, v2=, v3=, v4=
    oRun arg=2, v2=-{1 arg only} oder?, v3=, v4=
    oRun arg=2, v2=].{1 obj only} oder?, v3=, v4=
    oRun arg=3, v2={2 args}, v3=und zwei?, v4=
    oRun arg=4, v2={3 args}, v3=zwei, v4=und drei?
$/tstCompORun/ */
    call compIni
    call vPut 'oRun', oRunner('parse arg , v2, v3, v4;',
        'call tstOut t, "oRun arg="arg()", v2="v2", v3="v3", v4="v4' )
    call tstComp1 '@ tstCompORun',
        , '$@oRun', '$@%[oRun$]' ,
        , '    $@%[oRun $"-{1 arg only}" oder?$]' ,
        , '    $@%[oRun - $.".{1 obj only}" ''oder?''$] $=v2=zwei' ,
        , '    $@%[oRun - $"{2 args}", "und" $v2"?"$]' ,
        , '    $@%[oRun - $"{3 args}", $v2, "und drei?"$]'
    return
endProcedure tstCompORun

tstCompORu2: procedure expose  m.
/*
$=/tstCompORu2/
    ### start tst tstCompORu2 #########################################
    compile @, 6 lines: $@oRun
    run without input
    oRun arg=1, v2=, v3=, v4=
    oRun arg=1, v2=, v3=, v4=
    oRun arg=2, v2=eins, zwei, drei, v3=, v4=
    oRun arg=2, v2=eins, zwei, drei, v3=, v4=
    oRun arg=4, v2=-eins, v3=zwei, v4=DREI
    oRun arg=4, v2=-eins, v3=zwei, v4=DREI
$/tstCompORu2/ */
    call compIni
    call vPut 'oRun', oRunner('parse arg , v2, v3, v4;',
        'call tstOut t, "oRun arg="arg()", v2="v2", v3="v3", v4="v4' )
    call tstComp1 '@ tstCompORu2',
        , '$@oRun', '$@%oRun',
        , '$@% oRun  eins, zwei, drei' ,
        , '$@%[ oRun eins, zwei, drei $]',
        , '$@% oRun  - "-eins", "zwei", drei' ,
        , '$@%[ oRun - "-eins", "zwei", drei $]'
    return
endProcedure tstCompORu2

tstCompORuRe: procedure expose  m.
/*
$=/tstCompORuRe/
    ### start tst tstCompORuRe ########################################
    compile @, 9 lines: $$ primary $-^oRuRe eins, zwei
    run without input
    primary oRuRe(arg=1, v2=, v3=) eins, zwei
    oRuRe(arg=2, v2=expr, zwei, v3=)
    oRuRe(arg=3, v2=-expr, v3=zwei)
    oRuRe(arg=2, v2=block, zwei, v3=)
    oRuRe(arg=3, v2=-block, v3=zwei)
$/tstCompORuRe/ */
    call compIni
    call vPut 'oRuRe', oRunner('parse arg , v2, v3;',
        'return "oRuRe(arg="arg()", v2="v2", v3="v3")"' )
    call tstComp1 '@ tstCompORuRe',
        , '$$ primary $-^oRuRe eins, zwei' ,
        , '$$-^ oRuRe expr, zwei',
        , '$$-^ oRuRe - "-expr", "zwei"',
        , '$$-^[oRuRe block, zwei$]' ,
        , '$$-^[',, 'oRuRe - "-block", "zwei"' , , '$]'
    return
endProcedure tstCompORuRe

tstCompDataIO: procedure expose m.
/*
$=/tstCompDataHereData/
    ### start tst tstCompDataHereData #################################
    compile =, 13 lines:  herdata $@#/stop/    .
    run without input
    . herdata .
    heredata 1 $x
    heredata 2 $y
    nach heredata
    . herdata [ .
    heredata 1 xValue
    heredata 2 yValueY
    nach heredata [
    . herdata { .
    HEREDATA 1 xValue
    heredata 2 yValueY
    nach heredata {
$/tstCompDataHereData/ */
    call tstComp1 '= tstCompDataHereData',
        , ' herdata $@#/stop/    ',
        , 'heredata 1 $x',
        , 'heredata 2 $y',
        , '$/stop/ $$ nach heredata',
        , ' herdata [ $@=/stop/    ',
        , '$=x=xValue$=y=yValueY',
        , 'heredata 1 $x',
        , 'heredata 2 $y',
        , '$/stop/ $$ nach heredata [',
        , ' herdata { $@/st/',
        , '; call out heredata 1 $x',
        , '$$heredata 2 $y',
        , '$/st/ $$ nach heredata {'
/*
$=/tstCompDataIO/
    ### start tst tstCompDataIO #######################################
    compile =, 5 lines:  input 1 $@.<-=[$dsn $*+.
    run without input
    . input 1 .
    readInp line 1                       .
    readInp line 2                       .
    . nach dsn input und nochmals mit &
    readInp line 1                       .
    readInp line 2                       .
    . und schluiss..
$/tstCompDataIO/ */
    dsn = word(tstPdsMbr(tstFilename('lib37', 'r'), 'readInp'), 1)
    dsnFB = strip(dsn tstFB('::F37', 0))
    b = jBuf(tstFB('readInp line 1', 37),
            ,tstFB('readInp line 2', 37))
    extFd = tstFB('&dsn('dsn') dd(xyz)', 0)
    extFd = tstFB(dsn 'dd(xyz) ::f', 0)
    if extFd = '' then
        extFd = dsn
    call jCat file(dsnFB), b
    call vPut 'dsn', dsn
    say 'dsn' dsn 'extFD' extFD'?'
    call tstComp1 '= tstCompDataIO',
        , ' input 1 $@.<-=[$dsn $*+',
        , tstFB('::f', 0) '$]',
        , ' nach dsn input und nochmals mit & ' ,
        , '         $@.<'extFD,
        , ' und schluiss.'
    return
endProcedure tstCompDataIO

tstObjVF: procedure expose m.
parse arg v, f
    obj  = oNew(classNew('n? TstClassVF u v, f FLD1 v'))
    m.obj = if(f=='','val='v, v)
    m.obj.fld1 = if(f=='','FLD1='v, f)
    return obj
endProcedure tstObjVF

tstCompFile: procedure expose m.
/*
$=/tstCompFileBloSrc/
    $=vv=value-of-vv
    ###file from empty # block
    $@<#[
        $]
    ###file from 1 line # block
    $@<#[
    the only $ix+1/0 line $vv
    $]
    ###file from 2 line # block
    $@<#[
        first line /0 $*+ no comment
        second and last line $$ $wie
    $]
    ===file from empty = block
    $@<=[     $*+ comment
        $]
    ===file from 1 line = block
    $@<=[ the only line $]
    ===file from 2 line = block
    $@<=[ first line$** comment
        second and last line  $]
    ---file from empty - block
    $@<-/s/
        $/s/
    ---file from 1 line - block
    $@<-/s/ the only "line" (1*1) $/s/
    ---file from 2 line = block
    $@<-// first "line" (1+0)
        second   and   "last  line" (1+1)  $//
    ...file from empty . block
    $@<.[
        $]
    ...file from 1 line . block
    $@<.[ tstObjVF('v-Eins', '1-Eins') $]
    ...file from 2 line . block
    $@<.[ tstObjVF('v-Elf', '1-Elf')
        tstObjVF('zwoelf')  $]
    ...file from 3 line . block
    $@<.[ tstObjVF('einUndDreissig')
            s2o('zweiUndDreissig' o2String($.-vv))
            tstObjVF('dreiUndDreissig')  $]
    @@@file from empty @ block
    $@<@[
        $]
    $=noOutput=before
    @@@file from nooutput @ block
    $@<@[ nop
        $=noOutput = run in block $]
    @@@nach noOutput=$noOutput
    @@@file from 1 line @ block
    $@<@[ $$. tstObjVF('w-Eins', 'w1-Eins') $]
    @@@file from 2 line @ block
    $@<@[ $$. tstObjVF('w-Elf', 'w1-Elf')
        y='zwoelf' $$- y  $]
    @@@file from 3 line @ block
    $@<@[ $$. tstObjVF('w einUndDreissig')    $$ +
    zweiUndDreissig $$ 33 $vv$]
    {{{ empty [ block
    $@<[     $]
    {{{ empty [ block with comment
    $@<[    $*+ abc
          $]
    {{{ one line [ block
    $@<[ the only $"[...$]" line $*+.
        $vv $]
    {{{ one line -[ block
    $@<-[ the only $"-[...$]"  "line" $vv  $]
    {{{ empty #[ block
    $@<#[
$]
    {{{ one line #[ block
    $@<#[ the only $"-[...$]"  "line" $vv $[vv${x}$]
$]
$/tstCompFileBloSrc/ */
/*
$=/tstCompFileBlo/
    ### start tst tstCompFileBlo ######################################
    compile =, 72 lines: $=vv=value-of-vv
    run without input
    ###file from empty # block
    ###file from 1 line # block
    the only $ix+1/0 line $vv
    ###file from 2 line # block
    first line /0 $*+ no comment
    second and last line $$ $wie
    ===file from empty = block
    ===file from 1 line = block
    . the only line .
    ===file from 2 line = block
    . first line
    second and last line  .
    ---file from empty - block
    ---file from 1 line - block
    THE ONLY line 1
    ---file from 2 line = block
    FIRST line 1
    SECOND AND last  line 2
    ...file from empty . block
    ...file from 1 line . block
    tstR: @tstWriteoV1 isA :TstClassVF = v-Eins
    tstR:  .FLD1 = 1-Eins
    ...file from 2 line . block
    tstR: @tstWriteoV2 isA :TstClassVF = v-Elf
    tstR:  .FLD1 = 1-Elf
    tstR: @tstWriteoV3 isA :TstClassVF = val=zwoelf
    tstR:  .FLD1 = FLD1=zwoelf
    ...file from 3 line . block
    tstR: @tstWriteoV4 isA :TstClassVF = val=einUndDreissig
    tstR:  .FLD1 = FLD1=einUndDreissig
    zweiUndDreissig value-of-vv
    tstR: @tstWriteoV5 isA :TstClassVF = val=dreiUndDreissig
    tstR:  .FLD1 = FLD1=dreiUndDreissig
    @@@file from empty @ block
    @@@file from nooutput @ block
    @@@nach noOutput=run in block
    @@@file from 1 line @ block
    tstR: @tstWriteoV6 isA :TstClassVF = w-Eins
    tstR:  .FLD1 = w1-Eins
    @@@file from 2 line @ block
    tstR: @tstWriteoV7 isA :TstClassVF = w-Elf
    tstR:  .FLD1 = w1-Elf
    zwoelf
    @@@file from 3 line @ block
    tstR: @tstWriteoV8 isA :TstClassVF = val=w einUndDreissig
    tstR:  .FLD1 = FLD1=w einUndDreissig
    zweiUndDreissig
    33 value-of-vv
    {{{ empty [ block
    {{{ empty [ block with comment
    {{{ one line [ block
    . the only [...$] line value-of-vv .
    {{{ one line -[ block
    THE ONLY -[...$] line value-of-vv
    {{{ empty #[ block
    {{{ one line #[ block
    . the only $"-[...$]"  "line" $vv $[vv${x}$]
$/tstCompFileBlo/ */
    call tstComp2 'tstCompFileBlo', '='
    m.t.trans.0 = 0

/*
$=/tstCompFileObjSrc/
    $=vv=value-vv-1
    $=fE=<[ $]
    $=f2=. $.<.[s2o("f2 line 1" o2String($.-vv))
         tstObjVF("f2 line2") $]
    ---empty file $"$@<$fE"
    $@fE
    ---file with 2 lines $"$@<$f2"
    $@.<.f2
    $=vv=value-vv-2
    ---file with 2 lines $"$@<$f2"
    $@.<.f2
    $= dsn =- word(tstPdsMbr(tstFilename('libvb', 'r'), 'fileObj'),1) +
                tstFB('::V', 0)
    $@[
        fi=jOpen(file($dsn),'>')
        call jWrite fi, 'line one on' $"$dsn"
        call jWrite fi, 'line two on' $"$dsn"
        call jClose fi
    $]
    ---file on disk out
    $@<-dsn
$/tstCompFileObjSrc/ */
/*
$=/tstCompFileObj/
    ### start tst tstCompFileObj ######################################
    compile =, 20 lines: $=vv=value-vv-1
    run without input
    ---empty file $@<$fE
    ---file with 2 lines $@<$f2
    f2 line 1 value-vv-1
    tstR: @tstWriteoV1 isA :TstClassVF = val=f2 line2
    tstR:  .FLD1 = FLD1=f2 line2
    ---file with 2 lines $@<$f2
    f2 line 1 value-vv-1
    tstR: @tstWriteoV1 isA :TstClassVF = val=f2 line2
    tstR:  .FLD1 = FLD1=f2 line2
    ---file on disk out
    line one on $dsn
    line two on $dsn
$/tstCompFileObj/ */
    call tstComp2 'tstCompFileObj', '='

    return
endProcedure tstCompFile

tstCompPipe: procedure expose m.
/*
$=/tstCompPipe1/
    ### start tst tstCompPipe1 ########################################
    compile @, 1 lines:  call pipePreSuf "(1 ", " 1)"
    run without input
    #jIn eof 1#
    run with 3 inputs
    #jIn 1# eins zwei drei
    (1 eins zwei drei 1)
    #jIn 2# zehn elf zwoelf?
    (1 zehn elf zwoelf? 1)
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    (1 zwanzig 21 22 23 24 ... 29| 1)
    #jIn eof 4#
$/tstCompPipe1/ */
    call tstComp1 '@ tstCompPipe1 3',
        , ' call pipePreSuf "(1 ", " 1)"'
/*
$=/tstCompPipe2/
    ### start tst tstCompPipe2 ########################################
    compile @, 2 lines:  call pipePreSuf "(1 ", " 1)"
    run without input
    #jIn eof 1#
    run with 3 inputs
    #jIn 1# eins zwei drei
    #jIn 2# zehn elf zwoelf?
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    #jIn eof 4#
    [2 (1 eins zwei drei 1) 2]
    [2 (1 zehn elf zwoelf? 1) 2]
    [2 (1 zwanzig 21 22 23 24 ... 29| 1) 2]
$/tstCompPipe2/ */
    call tstComp1 '@ tstCompPipe2 3',
        , ' call pipePreSuf "(1 ", " 1)"' ,
        , ' $| call pipePreSuf "[2 ", " 2]"'

/*
$=/tstCompPipe3/
    ### start tst tstCompPipe3 ########################################
    compile @, 3 lines:  call pipePreSuf "(1 ", " 1)"
    run without input
    #jIn eof 1#
    run with 3 inputs
    #jIn 1# eins zwei drei
    #jIn 2# zehn elf zwoelf?
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    #jIn eof 4#
    <3 [2 (1 eins zwei drei 1) 2] 3>
    <3 [2 (1 zehn elf zwoelf? 1) 2] 3>
    <3 [2 (1 zwanzig 21 22 23 24 ... 29| 1) 2] 3>
$/tstCompPipe3/ */
    call tstComp1 '@ tstCompPipe3 3',
        , ' call pipePreSuf "(1 ", " 1)"' ,
        , ' $| call pipePreSuf "[2 ", " 2]"',
        , ' $| call pipePreSuf "<3 ", " 3>"'

/*
$=/tstCompPipe4/
    ### start tst tstCompPipe4 ########################################
    compile @, 7 lines:  call pipePreSuf "(1 ", " 1)"
    run without input
    #jIn eof 1#
    run with 3 inputs
    #jIn 1# eins zwei drei
    #jIn 2# zehn elf zwoelf?
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    #jIn eof 4#
    <3 [222 [221 [21 [20 (1 eins zwei drei 1) 20] 21] 221] 222] 3>
    <3 [222 [221 [21 [20 (1 zehn elf zwoelf? 1) 20] 21] 221] 222] 3>
    <3 [222 [221 [21 [20 (1 zwanzig 21 22 23 24 ... 29| 1) 20] 21] 221]+
    . 222] 3>
$/tstCompPipe4/ */
    call tstComp1 '@ tstCompPipe4 3',
        , ' call pipePreSuf "(1 ", " 1)"' ,
        , ' $| $@[    call pipePreSuf "[20 ", " 20]"',
        ,        ' $| call pipePreSuf "[21 ", " 21]"',
        ,        ' $| $@[      call pipePreSuf "[221 ", " 221]"',
        ,                 ' $| call pipePreSuf "[222 ", " 222]"',
        ,     '$]     $] ',
        , ' $| call pipePreSuf "<3 ", " 3>"'
    return
endProcedure tstCompPipe


tstCompPip2: procedure expose m.
/*
$=/tstCompPip21/
    ### start tst tstCompPip21 ########################################
    compile @, 3 lines:  $<[ zeile eins .
    run without input
    (1  zeile eins 1)
    (1    zeile zwei  1)
    run with 3 inputs
    (1  zeile eins 1)
    (1    zeile zwei  1)
$/tstCompPip21/ */
    call tstComp1 '@ tstCompPip21 3',
        , ' $<[ zeile eins ' ,
        , '   zeile zwei $]' ,
        , ' call pipePreSuf "(1 ", " 1)"'
/*
$=/tstCompPip22/
    ### start tst tstCompPip22 ########################################
    compile @, 3 lines: if ${>i1} then $@[
    run without input
    #jIn eof 1#
    nachher
    run with 3 inputs
    #jIn 1# eins zwei drei
    <zeile 1: eins zwei drei>
    <zwei>
    nachher
$/tstCompPip22/ */
    call tstComp1 '@ tstCompPip22 3',
        , 'if ${>i1} then $@['          ,
        , ' $$ zeile 1: $i1 $$ zwei $| call pipePreSuf "<",">" $]',
        , ' $$ nachher '
    return
endProcedure tstCompPip2

tstCompRedir: procedure expose m.
/*
$=/tstCompRedir/
    ### start tst tstCompRedir ########################################
    compile @, 6 lines:  $=eins=<@[ $@for vv $$ <$vv> $] .
    run without input
    #jIn eof 1#
    output eins .
    output piped zwei .
    run with 3 inputs
    #jIn 1# eins zwei drei
    #jIn 2# zehn elf zwoelf?
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    #jIn eof 4#
    output eins <eins zwei drei> <zehn elf zwoelf?> +
    <zwanzig 21 22 23 24 ... 29|>
    output piped zwei ab<eins zwei drei>yz ab<zehn elf zwoelf?>yz a+
    b<zwanzig 21 22 23 24 ... 29|>yz
$/tstCompRedir/ */
    call pipeIni
    call vRemove 'eins'  /* alte Variable loswerden */
    dsn = word(tstPdsMbr(tstFilename('libvb', 'r'), 'redir1'), 1)
    call vPut 'dsn', dsn
    say  'dsn' $dsn
    call tstComp1 '@ tstCompRedir 3' ,
        , ' $=eins=<@[ $@for vv $$ <$vv> $] ',
        , ' $$ output eins $-=[$@.eins$] $; ',
        , ' $@for ww $$b${ww}y ' ,
        , '    $>-= $-[ $dsn $] 'tstFB('::v', 0),
        ,         '$| call pipePreSuf "a", "z" $<.eins' ,
        , ' $; $$ output piped zwei $-=[$@<$-dsn$]'
/*
$=/tstCompRedi2/
    ### start tst tstCompRedi2 ########################################
    compile @, 12 lines: call mAdd t.trans, $var "dsnTestRedi"
    run without input
    >1<dsnTestRedi currTimeRedi
    >2<$"dsnTestRedi" currTimeRedi
    >3<$"dsnTestRedi" ::v currTimeRedi
    >4<$-var" currTimeRedi
    >5<$dsnTestRedi" currTimeRedi
$/tstCompRedi2/
*/
    call vPut 'var', tstFileName('compRedi', 'r')
    call vPut 'tst', translate(date()'+'time()'+testRedi2', '_', ' ')
    call tstComp1 '@ tstCompRedi2 ' ,
        , 'call mAdd t.trans, $var "dsnTestRedi"',
        , 'call mAdd t.trans, $tst "currTimeRedi"',
        , '$<> $>'vGet('var') '::v $$ $">1<'vGet('var')'" $tst',
        , '$<> $<'vGet('var') '    $@ call pipeWriteAll' ,
       , '$<> $>$"'vGet('var')' ::v" $$ $">2<$""'vGet('var')'""" $tst',
        , '$<> $<$"'vGet('var') '"   $@ call pipeWriteAll',
   , '$<> $>$"'vGet('var')'" ::v $$ $">3<$""'vGet('var')'"" ::v" $tst',
        , '$<> $<$"'vGet('var') '"   $@ call pipeWriteAll',
        , '$<> $>-var  $$ $">4<$"-var" $tst',
        , '$<> $<-var  $@ call pipeWriteAll',
        , '$<> $>$var ::v $$ $">5<$"$var" $tst',
        , '$<> $<$var  $@ call pipeWriteAll'
    return
endProcedure tstCompRedir

tstCompComp: procedure expose m.
/*
$=/tstCompCompShell/
    ### start tst tstCompCompShell ####################################
    compile @, 5 lines: $$compiling shell $; $= rrr =. $.^compile $<@#/+
    aaa/
    run without input
    compiling shell
    running einmal
    RUN 1 COMPILED einmal
    #jIn eof 1#
    running zweimal
    RUN 1 COMPILED zweimal
    #jIn eof 2#
    run with 3 inputs
    compiling shell
    running einmal
    RUN 1 COMPILED einmal
    #jIn 1# eins zwei drei
    compRun eins zwei dreieinmal
    #jIn 2# zehn elf zwoelf?
    compRun zehn elf zwoelf?einmal
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    compRun zwanzig 21 22 23 24 ... 29|einmal
    #jIn eof 4#
    running zweimal
    RUN 1 COMPILED zweimal
    #jIn eof 5#
$/tstCompCompShell/ */
    call tstComp1 '@ tstCompCompShell 3',
        ,  "$$compiling shell $; $= rrr =. $.^compile $<@#/aaa/",
        ,  "call out run 1*1*1 compiled $cc;" ,
            "$@for v $$ compRun $v$cc" ,
        ,  "$/aaa/ $;",
        ,  "$=cc=einmal $$ running $cc $@rrr",
        ,  "$=cc=zweimal $$ running $cc $@rrr"
/*
$=/tstCompCompData/
    ### start tst tstCompCompData #####################################
    compile @, 5 lines: $$compiling data $; $= rrr =. $.^[compile = +
    =$]  $<@#/aaa/
    run without input
    compiling data
    running einmal
    call out run 1*1*1 compiled einmal
    running zweimal
    call out run 1*1*1 compiled zweimal
    run with 3 inputs
    compiling data
    running einmal
    call out run 1*1*1 compiled einmal
    running zweimal
    call out run 1*1*1 compiled zweimal
$/tstCompCompData/ */
    call tstComp1 '@ tstCompCompData 3',
        , "$$compiling data $; $= rrr =. $.^[compile = =$]  $<@#/aaa/",
        ,  "call out run 1*1*1 compiled $cc",
        ,  "$/aaa/ $;",
        ,  "$=cc=einmal $$ running $cc $@rrr",
        ,  "$=cc=zweimal $$ running $cc $@rrr"
    return
endProcedure tstCompComp

tstCompDir: procedure expose m.
/*
$=/tstCompDirSrc/
  'in src v1='$v1
  $#@ call out 'src @ out v1='$v1
  $#. $*(komm$*) s2o('src . v1=')
       $.-v1
  $#-
    'src - v1='$v1
  $#=
    src = v1=$v1
$/tstCompDirSrc/

$=/tstCompDir/
    ### start tst tstCompDir ##########################################
    compile @call out 'before v1='$v1 $=v1=eins $#. s2o('. v1='$-v1) $#+
    @ call out '@ v1='$v1 $#= = v1=$v1 $#- '- v1='$v1 $#-, 8 lines: 'in+
    . src v1='$v1
    run without input
    before v1=v1Before
    .. v1=eins
    @ v1=eins
    = v1=eins .
    - v1=eins
    in src v1=eins
    src @ out v1=eins
    src . v1=
    eins
    src - v1=eins
    src = v1=eins
$/tstCompDir/ */
    call compIni
    call vPut 'v1', 'v1Before'
    call tstComp2 'tstCompDir', "@call out 'before v1='$v1 $=v1=eins" ,
        "$#. s2o('. v1='$-v1) $#@ call out '@ v1='$v1" ,
        "$#= = v1=$v1 $#- '- v1='$v1 $#-"
/*
$=/tstCompDirPiSrc/
  zeile 1 v1=$v1
  zweite Zeile vor $"$@$#-"
  $#@  $@proc pi2 $@-[
  $'zeile drei nach $@$#- v1='v1
  vierte und letzte Zeile $]
$/tstCompDirPiSrc/ */
/*
$=/tstCompDirPi/
    ### start tst tstCompDirPi ########################################
    compile @call pipePreSuf '<','>' $=v1=eiPi $<.pi2 $#=, 5 lines: ze+
    ile 1 v1=$v1
    run without input
    <zeile drei nach $@$#- v1=V1>
    <VIERTE UND LETZTE ZEILE>
    zeile 1 v1=eiPi
    zweite Zeile vor $@$#-
$/tstCompDirPi/ */
    call tstComp2 'tstCompDirPi',
            , "@call pipePreSuf '<','>' $=v1=eiPi $<.pi2 $#="
    return
endProcedure tstCompDir

tstCompColon: procedure expose m.
/*
$=/tstCompColon1/
    ### start tst tstCompColon1 #######################################
    compile :, 12 lines: vA = valueVonA
    run without input
    vA = valueVonA
    vA=valueVonA vB=valueVonB vC=valueVonC
    vC=valueVonC vD=valueVonD vE=valueVonvE
    vF=6
$/tstCompColon1/ */
    call tstComp1 ': tstCompColon1',
        , 'vA = valueVonA' ,
        , ' $$ vA = $vA' ,
        , '        * kommentar ' ,
        , '=vB=- "valueVonB"' ,
        , '=/vC/valueVonC$/vC/' ,
        , ' $$ vA=$vA vB=$vB vC=$vC' ,
        , '$=/vD/valueVonD' ,
        , '$/vD/ vE=valueVonvE' ,
        , '        * kommentar ' ,
        , ' $$ vC=$vC vD=$vD vE=$vE',
        , 'vF=- 2*3 $=vG=@@[ $$ vF=$vF$]' ,
        , '@vG'

/*
$=/tstCompColon2/
    ### start tst tstCompColon2 #######################################
    compile :, 7 lines: ix=0
    run without input
    #jIn eof 1#
    proc p1 arg(2) total 0 im argumentchen
    run with 3 inputs
    #jIn 1# eins zwei drei
    #jIn 2# zehn elf zwoelf?
    #jIn 3# zwanzig 21 22 23 24 ... 29|
    #jIn eof 4#
    <<for 1 -> eins zwei drei>>
    <<for 2 -> zehn elf zwoelf?>>
    <<for 3 -> zwanzig 21 22 23 24 ... 29|>>
    proc p1 arg(2) total 3 im argumentchen
$/tstCompColon2/

*/
    call tstComp1 ': tstCompColon2 3',
        , 'ix=0' ,
        , 'for v @:[ix=- $ix+1',
        , ' $$ for $ix -> $v' ,
        , '] | @[call pipePreSuf "<<",">>"',
        , '$] @%[p1 total $ix im argumentchen$]',
        , 'proc @:/p1/$$- "proc p1 arg(2)" arg(2)' ,
        , '/p1/'
/*
$=/tstCompColon3/
    ### start tst tstCompColon3 #######################################
    compile :, 11 lines: tc3Eins=freeVar1
    run without input
    tc3Eins=freeVar1 o2&tc3Eins= o2&tc3Zwei=
    tc3Eins=freeVar1 o2&tc3Eins=with3Eins o2&tc3Zwei=with3Zwei
    tc3Eins=freeVar1 o2&tc3Eins=ass4Eins o2&tc3Zwei=with5Zwei
    o3&tc3Eins=ass4Eins o3&tc3Zwei=with5 o3 Zwei
    tc3Eins=freeVar1 o2&tc3Eins=ass4Eins o2&tc3Zwei=with5Zwei
$/tstCompColon3/
*/
    call classNew 'n? TstCompColon3 u f tc3Eins v, f tc3Zwei v'
    showO2 = 'tc3Eins=$tc3Eins' ,
            'o2&tc3Eins=${o2&tc3Eins} o2&tc3Zwei=${o2&tc3Zwei}'
    showO3 = 'o3&tc3Eins=${o3&tc3Eins} o3&tc3Zwei=${o3&tc3Zwei}'
    call tstComp1 ': tstCompColon3',
        , 'tc3Eins=freeVar1' ,
     , 'o2 =. oNew("TstCompColon3")' ,
        , '$$' showO2 ,
        , 'with $o2 $@:[tc3Eins = with3Eins',
        ,     'tc3Zwei = with3Zwei',
        ,    '] $$' showO2 ,
        , '{o2&tc3Eins} = ass4Eins',
        , 'with $o2 $=tc3Zwei = with5Zwei',
        , '$$' showO2 ,
        , 'with o3 =. oCopy($o2) $=tc3Zwei = with5 o3 Zwei',
        , '$$' showO3 '$$' showO2
    return
endProcedure tstCompColon

tstCompWithNew: procedure expose m.
/*
$=/tstCompWithNew/
    ### start tst tstCompWithNew ######################################
    compile :, 12 lines: withNew $@:[
    run without input
    tstR: @tstWriteoV2 isA :<TstCT1Class>
    tstR:  .fEins = withNewValue fEins
    tstR:  .fZwei = withNewValue fZwei
    tstR:  .fDrei = withNewValuel drei
    tstR: @tstWriteoV3 isA :<TstCT1Class>
    tstR:  .fEins = withNewValue fEinsB
    tstR:  .fZwei = withNewValue fZweiB
    tstR:  .fDrei = withNewValue fDreiB
    tstR: @tstWriteoV5 isA :<TstCT2Class>
    tstR:  .fEins = withValue fEinsC
    tstR:  .fDrei = withValue fDreiC
$/tstCompWithNew/
*/
    call wshIni
    cl = classNew('n* CompTable u f fEins v, f fZwei v, f fDrei v')
    c2 = classNew('n* CompTable u f fEins v, f fDrei v')
    call tstComp1 ': tstCompWithNew',
        , 'withNew $@:[' ,
        , 'fEins = withNewValue fEins' ,
        , 'fZwei = withNewValue fZwei' ,
        , '$@[call mAdd t.trans, className("'cl'") "<TstCT1Class>"',
        , '$@:[   fDrei = withNewValuel drei $] $] ' ,
        , '$] withNew $@:[' ,
        , 'fEins = withNewValue fEinsB' ,
        , 'fZwei = withNewValue fZweiB',
        , 'fDrei = withNewValue fDreiB',
        , '$] withNew $@:[ fEins = withValue fEinsC' ,
        , '$@[call mAdd t.trans, className("'c2'") "<TstCT2Class>"',
        , '$@[$=fDrei = withValue fDreiC$] $] $] '
/*
$=/tstCompWithNeRe/
    ### start tst tstCompWithNeRe #####################################
    compile :, 11 lines: withNew $@:[
    run without input
    tstR: @tstWriteoV2 isA :<TstClassR2>
    tstR:  .rA = value rA
    tstR:  .rB refTo @]value rB isA :w
    tstR: @tstWriteoV4 isA :<TstClassR2>
    tstR:  .rA = val33 rA
    tstR:  .rB refTo @]VAL33 RB isA :w
    tstR: @tstWriteoV5 isA :<TstClassR2>
    tstR:  .rA = val22 rA
    tstR:  .rB refTo @]VAL22 RB isA :w
    tstR: @tstWriteoV6 isA :<TstCT1Class>
    tstR:  .fEins = withNewValue fEins
    tstR:  .fZwei = withNewValue fZwei
    tstR:  .fDrei = withNewValuel drei
    vOth=value vOth fZwei=fZwei Wert vorher ?fDrei=0
$/tstCompWithNeRe/
*/
    cR = classNew("n* CompTable u f rA v, f rB r")
    call vRemove 'fDrei'
    call vPut 'fZwei', 'fZwei Wert vorher'
    call tstComp1 ': tstCompWithNeRe',
        , 'withNew $@:[' ,
        , 'fEins = withNewValue fEins' ,
        , '@:[withNew $@:[rA=value rA $=rB=. "]value rB" ' ,
        , '$@ call mAdd t.trans, className("'cR'") "<TstClassR2>"$]$]',
        , 'fZwei = withNewValue fZwei' ,
        , '$@[call mAdd t.trans, className("'cl'") "<TstCT1Class>"',
        , '$@:[withNew $@:[ rA =val22 rA $=rB=. ]val22 rB ' ,
        , '{vOth} = value vOth',
        , '$@:[withNew @:[rA =val33 rA $=rB=. ]val33 rB $] $] $] $]' ,
        , '$@:[   fDrei = withNewValuel drei $] $] $]',
        , '$<> $$ vOth=$vOth fZwei=$fZwei ?fDrei=${?fDrei}'
    return
endProcedure tstCompWithNew

tstCompSql: procedure expose m.
/*
$=/tstCompSqlSrc/
$@=[
   select strip(creator) cr, strip(name) tb,
            (row_number()over())*(row_number()over()) rr
       from sysibm.sysTables
       where creator='SYSIBM' and name like 'SYSTABL%'
       order by 2 fetch first 4 rows only
$]
$| call sqlSel
$| call fTabAuto
$/tstCompSqlSrc/
$=/tstCompSql/
    ### start tst tstCompSql ##########################################
    compile @, 9 lines: $@=[
    run without input
    CR     TB                RR
    SYSIBM SYSTABLEPART       1
    SYSIBM SYSTABLEPART_HIST  4
    SYSIBM SYSTABLES          9
    SYSIBM SYSTABLESPACE     16
$/tstCompSql/
$=/tstCompSqlFTabSrc/
$$ select 'ahaaaax' ahaCol, 'buuuuh' buhhhh from sysibm.sysDummy1
$| call sql2tab , , sqlFTabOpts(fTabReset(tstCompS1, '1', '1', '-'))
$<>
$= s1 = select 'aOh' ahaOhne, 'buuVar' buhVar from sysibm.sysDummy1
call sqlQuery 7, $s1
t2 = sqlFTabOpts(fTabReset(tstCompS2, '2 1', '2 c', '-'))
ox = m.t2.0 + 1
call sqlFTabOthers t2, 7
call sqlFTab fTabSetTit(t2, ox, 2, '-----'), 7
$<>
$$ select 'aOh' aDrei, 'buuDre' buhDrei from sysibm.sysDummy1
$| call sql2Tab
$/tstCompSqlFTabSrc/
$=/tstCompSqlFTab/
    ### start tst tstCompSqlFTab ######################################
    compile @, 12 lines: $$ select 'ahaaaax' ahaCol, 'buuuuh' buhhhh fr+
    om sysibm.sysDummy1
    run without input
    AHACOL--BUHHHH---
    ahaaaax buuuuh
    AHACOL--BUHHHH---
    -----
    AHA-BUHVAR---
    aOh buuVar
    -----
    AHAOHNE
    .    BUHVAR
    ADREI
    .    BUHDREI
    ADR-BUHDRE---
    aOh buuDre
    ADR-BUHDRE---
    ADREI
    .    BUHDREI
$/tstCompSqlFTab/
*/
    call sqlConnect , 's'
    call tstComp2 'tstCompSql', '@'
    call tstComp2 'tstCompSqlFTab', '@'
    call sqlDisConnect
    return
endProcedure tstCompSql
/* ?????rework tstTut ?????????????????*/
tstTut0: procedure expose m.
/*
$=/tstTut01Src/
$#=
$*+>.fSub()                               Kommentar
$*+>~tmp.jcl(t)                           Kommentar
$*+@=[                                    Kommentar
$=subsys=DP4G
$=db=DA540769
$=ts=A977A
$*+@<~wk.jcl(jc)                          Kommentar
??* ?-[sysvar(sysnode) date() time()?]ts=$ts 10*len=$-[length($ts)*10$]
//P02     EXEC PGM=DSNUTILB,
//             PARM='$subsys,A540769C.FULCOPL'
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSUDUMP  DD SYSOUT=*
//SYSTEMPL  DD DSN=$subsys.DBAA.LISTDEF(TEMPL),DISP=SHR
//SYSIN     DD *
LISTDEF C#LIST
  INCLUDE TABLESPACE $db.$ts*   PARTLEVEL
OPTIONS EVENT(ITEMERROR, SKIP)
COPY LIST C#LIST COPYDDN(TCOPYD)
  $@[if right($ts, 2) == '7A' then $@=[
    FULL YES
  $] else
    $$ $''    FULL NO
  $]
    SHRLEVEL CHANGE
$*+]                                      Kommentar
$#out original/src
$/tstTut01Src/
$=/tstTut01/
    ### start tst tstTut01 ############################################
    compile , 28 lines: $#=
    run without input
    ??* ?-[sysvar(sysnode) date() time()?]ts=A977A 10*len=50
    //P02     EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A540769C.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DA540769.A977A*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    FULL YES
    SHRLEVEL CHANGE
$/tstTut01/
$=/tstTut02Src/
$#@
$**>.fSub()
$**@[
$=subsys=DP4G
$=db=DA540769
$=jx=0
$@do tx = 976 to 977 $@=[
    $=ts=A$tx
    $=jx=- $jx+1
//A540769$jx JOB (CP00,KE50),'DB2 REO',
//         MSGCLASS=T,TIME=1440,
//         NOTIFY=&SYSUID,REGION=0M
//C$ts    EXEC PGM=DSNUTILB,
//             PARM='$subsys,A540769$jx.FULCOPL'
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSUDUMP  DD SYSOUT=*
//SYSTEMPL  DD DSN=$subsys.DBAA.LISTDEF(TEMPL),DISP=SHR
//SYSIN     DD *
LISTDEF C#LIST
  INCLUDE TABLESPACE $db.$ts*   PARTLEVEL
OPTIONS EVENT(ITEMERROR, SKIP)
COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$]
$**]
$#out original/src
$/tstTut02Src/
$=/tstTut02/
    ### start tst tstTut02 ############################################
    compile , 28 lines: $#@
    run without input
    //A5407691 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA976    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407691.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DA540769.A976*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
    //A5407692 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA977    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407692.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DA540769.A977*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$/tstTut02/
$=/tstTut03Src/
$#@
$=subsys=DP4G
$<>
$<#[
      db         ts
      DGDB9998   A976
      DA540769   A977
$]
$@. csvColRdr()
$** $| call fTabAuto
$**    $#end
$|
$=jx=0
$@forWith o $@=[
    $=jx=- $jx+1
//A540769$jx JOB (CP00,KE50),'DB2 REO',
//         MSGCLASS=T,TIME=1440,
//         NOTIFY=&SYSUID,REGION=0M
//C$ts    EXEC PGM=DSNUTILB,
//             PARM='$subsys,A540769$jx.FULCOPL'
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSUDUMP  DD SYSOUT=*
//SYSTEMPL  DD DSN=$subsys.DBAA.LISTDEF(TEMPL),DISP=SHR
//SYSIN     DD *
LISTDEF C#LIST
  INCLUDE TABLESPACE $db.$ts*   PARTLEVEL
OPTIONS EVENT(ITEMERROR, SKIP)
COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$]
$#out original/src
$/tstTut03Src/
$=/tstTut03/
    ### start tst tstTut03 ############################################
    compile , 33 lines: $#@
    run without input
    //A5407691 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA976    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407691.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DGDB9998.A976*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
    //A5407692 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA977    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407692.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DA540769.A977*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$/tstTut03/
$=/tstTut04Src/
$#@
$=subsys=DP4G
$=db=DA540769
call sqlConnect $subsys
$@=[  select dbName  db , tsName  ts
          from sysibm.sysTables
          where creator = 'SYSIBM' and name like 'SYSINDEXPAR%'
          order by name desc
$]
$| call sqlSel
$** $| call fTabAuto
$** $#end
$|
$=jx=0
$@forWith o $@=[
    $=jx=- $jx+1
//A540769$jx JOB (CP00,KE50),'DB2 REO',
//         MSGCLASS=T,TIME=1440,
//         NOTIFY=&SYSUID,REGION=0M
//C$TS    EXEC PGM=DSNUTILB,
//             PARM='$subsys,A540769$jx.FULCOPL'
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSUDUMP  DD SYSOUT=*
//SYSTEMPL  DD DSN=$subsys.DBAA.LISTDEF(TEMPL),DISP=SHR
//SYSIN     DD *
LISTDEF C#LIST
  INCLUDE TABLESPACE $DB.$TS*   PARTLEVEL
OPTIONS EVENT(ITEMERROR, SKIP)
COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$]
call sqlDisConnect
$#out original/src
$/tstTut04Src/
$=/tstTut04/
    ### start tst tstTut04 ############################################
    compile , 35 lines: $#@
    run without input
    //A5407691 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CSYSHIST     EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407691.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DSNDB06 .SYSHIST *   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
    //A5407692 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CSYSTSIPT    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407692.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DSNDB06 .SYSTSIPT*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$/tstTut04/
$=/tstTut05Src/
$#:
subsys = DP4G
lst =<:[withNew out :[
    db = DGDB9998
    ts =<:[table
             ts
             A976
             A977
    $]
    db = DA540769
    <|/ts/
             ts
             A976
             A975
    /ts/
]
$** $$. $lst
$** $@ct $@[$=tool =. $.compile@ $<~.wk.rexx(wshtut06)$]
$** $@$tool
$@do sx=1 to ${lst.0} $@[
    $=db = ${lst.$sx.db}
    $** $$. ${lst.$sx}
    $@do tx=1 to ${lst.$sx.ts.0} $@=[
        $*+ $$. ${lst.$sx.ts.$tx}
        $=ts= ${lst.$sx.ts.$tx.ts}
        $@[ say $-=[subsys $subsys db $db ts $ts $] $]
        $@copy()
        $]
    $]
$@ct $@[
cl = classNew('n? DbTsList u s' ,
     classNew('n? DbTs u f db v, f ts s' ,
     classNew('n? Ts u f ts v')))
$=lst=. oNew(cl)
$]
$@proc copy $@=[
$@ct $=jx=0
$=jx=- $jx+1
//A540769$jx JOB (CP00,KE50),'DB2 REO',
//         MSGCLASS=T,TIME=1440,
//         NOTIFY=&SYSUID,REGION=0M
//C$ts    EXEC PGM=DSNUTILB,
//             PARM='$subsys,A540769$jx.FULCOPL'
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSUDUMP  DD SYSOUT=*
//SYSTEMPL  DD DSN=$subsys.DBAA.LISTDEF(TEMPL),DISP=SHR
//SYSIN     DD *
LISTDEF C#LIST
  INCLUDE TABLESPACE $db.$ts*   PARTLEVEL
OPTIONS EVENT(ITEMERROR, SKIP)
COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$]
$#out original/src
$/tstTut05Src/
$=/tstTut05/
    ### start tst tstTut05 ############################################
    compile , 56 lines: $#@
    run without input
    //A5407691 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA976    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407691.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DGDB9998.A976*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
    //A5407692 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA977    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407692.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DGDB9998.A977*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
    //A5407693 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA976    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407693.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DA540769.A976*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
    //A5407694 JOB (CP00,KE50),'DB2 REO',
    //         MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //CA975    EXEC PGM=DSNUTILB,
    //             PARM='DP4G,A5407694.FULCOPL'
    //SYSPRINT  DD SYSOUT=*
    //UTPRINT   DD SYSOUT=*
    //SYSUDUMP  DD SYSOUT=*
    //SYSTEMPL  DD DSN=DP4G.DBAA.LISTDEF(TEMPL),DISP=SHR
    //SYSIN     DD *
    LISTDEF C#LIST
    INCLUDE TABLESPACE DA540769.A975*   PARTLEVEL
    OPTIONS EVENT(ITEMERROR, SKIP)
    COPY LIST C#LIST COPYDDN(TCOPYD)
    PARALLEL
    SHRLEVEL CHANGE
$/tstTut05/
   tstTut06   ==> platz für copy aus tut05
$=/tstTut07Src/
$**$>.fEdit()
call sqlConnect dp4g
$@:[table
   ts
VTCASHFLOW
VTCASHFLOWAMOUNT
VTINSTRFLATDATA
$]
$| $@=[
    select name, statstime, strip(dbName) || '.' || strip(tsName) dbts
       from sysibm.sysTables
       where creator = 'VDPS2' and name in
  $=co=(
  $@forWith t $@=[
                                           $co '$ts'
      $=co=,
  $]
                                           )
$]
$| call sqlSel
$** $| call fTabAuto
$|
$=jx=0
$@forWith t $@=[
$=jx=- $jx+1
//A540769$jx JOB (CP00,KE50),
//       'CATALOG',MSGCLASS=T,TIME=1440,
//         NOTIFY=&SYSUID,REGION=0M
//STEP$jx EXEC PGM=DSNUTILB,TIME=1440,
//   PARM=(DP4G,'A540769$jx.RUNSTA'),
//   REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//UTPRINT  DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//RNPRIN01 DD SYSOUT=*
//SYSIN DD *
  LISTDEF LST#STA   INCLUDE TABLESPACE $DBTS
   OPTIONS EVENT (ITEMERROR, SKIP)

   RUNSTATS TABLESPACE LIST LST#STA
         SHRLEVEL CHANGE
           INDEX(ALL KEYCARD)
           REPORT YES UPDATE ALL
$]
call sqlDisconnect
$#out original/src
$/tstTut07Src/
$=/tstTut07/
$=/tstTut07/
    ### start tst tstTut07 ############################################
    compile , 47 lines: $**$>.fEdit()
    run without input
    //A5407691 JOB (CP00,KE50),
    //       'CATALOG',MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //STEP1 EXEC PGM=DSNUTILB,TIME=1440,
    //   PARM=(DP4G,'A5407691.RUNSTA'),
    //   REGION=0M
    //SYSPRINT DD SYSOUT=*
    //SYSUDUMP DD SYSOUT=*
    //UTPRINT  DD SYSOUT=*
    //SYSOUT   DD SYSOUT=*
    //RNPRIN01 DD SYSOUT=*
    //SYSIN DD *
    LISTDEF LST#STA   INCLUDE TABLESPACE VV27A1T.VDPS329
    OPTIONS EVENT (ITEMERROR, SKIP)
    ..
    RUNSTATS TABLESPACE LIST LST#STA
    SHRLEVEL CHANGE
    INDEX(ALL KEYCARD)
    REPORT YES UPDATE ALL
    //A5407692 JOB (CP00,KE50),
    //       'CATALOG',MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //STEP2 EXEC PGM=DSNUTILB,TIME=1440,
    //   PARM=(DP4G,'A5407692.RUNSTA'),
    //   REGION=0M
    //SYSPRINT DD SYSOUT=*
    //SYSUDUMP DD SYSOUT=*
    //UTPRINT  DD SYSOUT=*
    //SYSOUT   DD SYSOUT=*
    //RNPRIN01 DD SYSOUT=*
    //SYSIN DD *
    LISTDEF LST#STA   INCLUDE TABLESPACE VV28A1T.VDPS390
    OPTIONS EVENT (ITEMERROR, SKIP)
    ..
    RUNSTATS TABLESPACE LIST LST#STA
    SHRLEVEL CHANGE
    INDEX(ALL KEYCARD)
    REPORT YES UPDATE ALL
    //A5407693 JOB (CP00,KE50),
    //       'CATALOG',MSGCLASS=T,TIME=1440,
    //         NOTIFY=&SYSUID,REGION=0M
    //STEP3 EXEC PGM=DSNUTILB,TIME=1440,
    //   PARM=(DP4G,'A5407693.RUNSTA'),
    //   REGION=0M
    //SYSPRINT DD SYSOUT=*
    //SYSUDUMP DD SYSOUT=*
    //UTPRINT  DD SYSOUT=*
    //SYSOUT   DD SYSOUT=*
    //RNPRIN01 DD SYSOUT=*
    //SYSIN DD *
    LISTDEF LST#STA   INCLUDE TABLESPACE VV21A1T.VDPS004
    OPTIONS EVENT (ITEMERROR, SKIP)
    ..
    RUNSTATS TABLESPACE LIST LST#STA
    SHRLEVEL CHANGE
    INDEX(ALL KEYCARD)
    REPORT YES UPDATE ALL
$/tstTut07/
$=/tstTut08Src/
$/tstTut08Src/
$=/tstTut08/
$/tstTut08/
*/
    call sqlIni
    call sqlDisconnect '*'
    call tstComp2 'tstTut01'
    call tstComp2 'tstTut02'
    call tstComp2 'tstTut03'
    if m.err_os == 'TSO' then do
        call tstComp2 'tstTut04'
        /* call tstComp2 'tstTut05' */
     /* call tstComp2 'tstTut07'  ???? anderes Beispiel ???? */
        end
    call tstTotal
    return
endProcedure tstTut0
/****** tstBase *******************************************************
     test the basic classes
**********************************************************************/
tstBase: procedure expose m.
    call tstTstSay
    call tstM
    call tstUtc2d
    call tstMap
    call tstMapVia
    call classIni
    call tstClass
    call tstClass2
    call tstClass3
    call tstClass4
    call tstO
    call tstOStr
    call tstOEins
    call tstO2Text
    call tstF
    call tstFWords
    call tstFtst
    call tstFCat
    call jIni
    call tstJSay
    call tstJ
    call tstJ2
    call tstScanSqlStmt
    call catIni
    call tstCat
    call pipeIni
    CALL TstEnv
    CALL TstEnvLong
    CALL TstEnvCat
    call tstPipe
    call tstPipeS
    call tstEnvVars
    call tstvWith
    call tstTotal
    call tstPipeLazy
    call tstEnvClass
    call tstDsn
    call tstDsn2
    if m.tst_csmRZ \== '' then
        call tstDsnEx
    call tstFile
    call tstFileList
    call tstMbrList
    call tstFE
    call tstFTab
    call tstFmt
    call tstFUnit
    call tstfUnit2
    call tstCsv
    call tstCsv2
    call tstCsvExt
    call tstCsvInt
    call tstCsvV2F
    call tstTotal
    call tstSb
    call tstSb2
    call tstScan
    call ScanReadIni
    call tstScanRead
    call tstScanUtilInto
    call tstScanWin
    call tstScanSQL
    call tstTotal
    return
endProcedure tstBase

/*--- test the tst Module, check the output visually  ---------------*/
tstTstSay: procedure expose m.
    call tstIni
    oldErr = m.tst.err
    oldNames = m.tst.errNames
    say '+++ tstTstSay start with' oldErr 'totErrs and',
            m.tst.tests 'tests'
/*
$=/tstTstSayEins/
    ### start tst tstTstSayEins #######################################
    test eins einzige testZeile
$/tstTstSayEins/
$=/tstTstSayZwei/
    ### start tst tstTstSayZwei #######################################
    zwei 1. testZeile
    zwei 2. und letzte testZeile
$/tstTstSayZwei/
$=/tstTstSayDrei/
    ### start tst tstTstSayDrei #######################################
    drei 1. testZeile vor empty Zeile
    ..
    drei 3. testZeile vor 10 space
    .          .
    drei 5. testZeile ziemlich lang 66                                 +
    .                                77  5   10   15++++++++++++++++++++
    .+++++++++++++++++++++++++++++++++++++++++++.
$/tstTstSayDrei/
*/
    call tst x, 'tstTstSayEins'
    call tstOut x, "test eins einzige testZeile"
    call tstEnd x, 'err 0'


    call tst x, 'tstTstSayZwei'
    call tstOut x, "zwei 1. testZeile"
    call tstOut x, "zwei 2. und letzte testZeile"
    call tstEnd x, 'err 0'

    call tst x, 'tstTstSayZwei'
    call tstOut x, "zwei 1. testZeile "    /* ein space zuviel */
    call tstOut x, "zwei 2. und letzte testZeile"
    call tstOut x, "zwei 3. zuviel"
    call tstEnd x, 'err 3'

    call tst y, 'tstTstSayDrei'
    call tstOut y, 'drei 1. testZeile vor empty Zeile'
    call tstOut y, ''
    call tstOut y, 'drei 3. testZeile vor 10 space'
    call tstOut y, left('', 10)
    call tstOut y, 'drei 5. testZeile ziemlich lang',
                left(66, 66) left('77  5   10   15', 77, '+')
    call tstEnd y, 'err 0'
    if m.y.err <> 0 then
        call err '+++ tstTstSay errs' m.x.err 'expected' 0
    if m.tst.err <> oldErr + 3 then
        call err '+++ tstTstSay totErrs' m.tst.err 'expected' 3
    say '+++ tstTstSay end Ok with' m.tst.err 'totErrs and' ,
        m.tst.tests 'tests'
    m.tst.err = oldErr
    m.tst.errNames = oldNames
    return
endProcedure tstTstSay

tstMark: procedure expose m.
parse arg m, msg
    if symbol('m.m') == 'VAR' then
        m.m = msg';' m.m
    else
        m.m = msg 'new'
    return m
endProcedure tstMark
tstM: procedure expose m.
/*
$=/tstMa/
    ### start tst tstMa ###############################################
    mNew() 1=newM1 2=newM2
    mNew(tst...) 2=2 new 3=4; 3; 1 new 4=5 new
    iter 4; 3; 1 new
    iter 2 new
    iter 5 new
$/tstMa/
*/
    call tst t, 'tstMa'
    m1 = mNew()
    m2 = mNew()
    m.m1 = 'newM1'
    m.m2 = 'newM2'
    call tstOut t, 'mNew() 1='m.m1 '2='m.m2
    call mNewArea 'tst'm1
    t1 = tstMark(mNew('tst'm1), '1')
    t2 = tstMark(mNew('tst'm1), '2')
    call mFree tstMark(t1, '3')
    t3 = tstMark(mNew('tst'm1), '4')
    t4 = tstMark(mNew('tst'm1), '5')
    call tstOut t, 'mNew(tst...) 2='m.t2 '3='m.t3 '4='m.t4
    i = mIterBegin('tst'm1)
    do forever
         i = mIter(i)
         if i == '' then
             leave
        call tstOut t, 'iter' m.i
        end
    call tstEnd t
/*
$=/tstM/
    ### start tst tstM ################################################
    symbol m.b LIT
    symbol m.a LIT
    mAdd a A.2
    mAdd a A.3
    m.a: 3: 1=eins 2=zwei 3=drei 4=M.A.4
    m.c: 5: 1=c vorAddSt a 2=eins 3=zwei 4=drei 5=c nacAddSt a 6=M.C.6
$/tstM/ */


    drop m.b m.a m.a.0 m.a.1 m.a.2
    call tst t, 'tstM'
    call tstOut t, 'symbol m.b' symbol('m.b')
    m.b = 1
    call tstOut t, 'symbol m.a' symbol('m.a')
    call tstOut t, 'mAdd a' mAdd(mCut(a, 0), 'eins', 'zwei')
    call tstOut t, 'mAdd a' mAdd(a, 'drei')
    call tstOut t,'m.a:' m.a.0': 1='m.a.1 '2='m.a.2 '3='m.a.3 '4='m.a.4
    call mAdd mCut(c, 0), 'c vorAddSt a'
    call mAddSt c, a
    call mAdd c, 'c nacAddSt a'
    call tstOut t, 'm.c:' m.c.0': 1='m.c.1 '2='m.c.2 '3='m.c.3,
                    '4='m.c.4 '5='m.c.5 '6='m.c.6
    call tstEnd t
    return
endProcedure tstM

tstFCat: procedure expose m.
/*
$=/tstFCat/
    ### start tst tstFCat #############################################
    fCat(                     ,0) =;
    fCat(1                    ,0) =;
    fCat(112222               ,0) =;
    fCat(3#a1%c2              ,0) =;
    fCat(4#a1%c2@%c333        ,0) =;
    fCat(5#a1%c2@%c3@%c4      ,0) =;
    fCat(                     ,1) =eins;
    fCat(1                    ,1) =eins;
    fCat(112222               ,1) =eins;
    fCat(3#a1%c2              ,1) =1eins2;
    fCat(4#a1%c2@%c333        ,1) =1eins2eins333;
    fCat(5#a1%c2@%c3@%c4      ,1) =1eins2eins3eins4;
    fCat(                     ,2) =einszwei;
    fCat(1                    ,2) =eins1zwei;
    fCat(112222               ,2) =eins112222zwei;
    fCat(3#a1%c2              ,2) =1eins231zwei2;
    fCat(4#a1%c2@%c333        ,2) =1eins2eins33341zwei2zwei333;
    fCat(5#a1%c2@%c3@%c4      ,2) =1eins2eins3eins451zwei2zwei3zwei4;
    fCat(                     ,3) =einszweidrei;
    fCat(1                    ,3) =eins1zwei1drei;
    fCat(112222               ,3) =eins112222zwei112222drei;
    fCat(3#a1%c2              ,3) =1eins231zwei231drei2;
    fCat(4#a1%c2@%c333        ,3) =1eins2eins33341zwei2zwei33341drei2dr+
    ei333;
    fCat(5#a1%c2@%c3@%c4      ,3) =1eins2eins3eins451zwei2zwei3zwei451d+
    rei2drei3drei4;
$/tstFCat/ */
    call pipeIni
    call tst t, "tstFCat"
     m.qq.1 = "eins"
     m.qq.2 = "zwei"
     m.qq.3 = "drei"
     do qx = 0 to 3
         m.qq.0 = qx
         call tstFCat1 qx
         call tstFCat1 qx, '1'
         call tstFCat1 qx, '112222'
         call tstFCat1 qx, '3#a1%c2'
         call tstFCat1 qx, '4#a1%c2@%c333'
         call tstFCat1 qx, '5#a1%c2@%c3@%c4'
         end
     call tstEnd t
     return
endProcedure tstFCat

tstFCat1: procedure expose m.
parse arg m.qq.0, fmt
    call out left("fCat("fmt, 26)","m.qq.0") ="fCat(fmt, qq)";"
return
endProcedure tstFCat1

tstMap: procedure expose m.
/*
$=/tstMap/
    ### start tst tstMap ##############################################
    mapNew m keys m-keys 0
    map m zwei --> 2
    map m Zwei is not defined
    map stem m-keys 4
    map m eins --> 1
    map m zwei --> 2
    map m drei --> 3
    map m vier --> 4
    *** err: duplicate in mapAdd(m, eins, 1)
    map m zwei is not defined
    q 2 zw dr
    map stem Q 2
    map Q zw --> 2Q
    map Q dr --> 3Q
    map stem m 3
    map m eins --> 1
    map m zwei --> 2PUT
    map m vier --> 4PUT
    *** err: duplicate in mapAdd(m, zwei, 2ADDDUP)
    tstMapLong eins keys 3
    tstMapLong zweiMal keys 48
    tstMapLong dreiMal keys 93
    tstMapLong vier    keys 138
    tstMapLong <fuenf> keys 188
    tstMap clear keys 0
    inline1 3
    inline1 1 ==    inline1 eins==
    inline1 2 ====
    inline1 3 ==    inline1 drei==
    inline2 1 1 ==    inline2 eins==
    inline3 ?
$/tstMap/ */
/*
$=/tstMapInline1/
    inline1 eins

    inline1 drei
$/tstMapInline1/ */
/*
$=/tstMapInline2/
    inline2 eins
$/tstMapInline2/ */

    call tst t, 'tstMap'
    m = mapNew('K')
    ky = mapKeys(m)
    call mAdd t'.TRANS', m 'm', ky 'm-keys'
    call tstOut t, 'mapNew' m 'keys' ky m.ky.0
    call mapAdd m, 'eins', 1
    call mapAdd m, 'zwei', 2
    call mapAdd m, 'drei', 3
    call mapAdd m, 'vier', 4
    call tstMapShow m, 'zwei'
    call tstMapShow m, 'Zwei'
    call tstMapShowSt m, mapKeys(m)
    call mapAdd m, 'eins', 1
    call mapReset m, '='
    call tstMapShow m, 'zwei'
    call mapAdd m, 'eins', 1
    call mapAdd m, 'zwei', 2
    call mapPut m, 'zwei', 2Put
    call mapPut m, 'vier', 4Put
    call mapReset q, '='
    call mapAdd q, 'zw', 2q
    call mapAdd q, 'dr', 3q
    call tstOut t, 'q' m.q.0 m.q.1 m.q.2
    call tstMapShowSt q, mapKeys(q)
    call tstMapShowSt m, mapKeys(m)
    call mapAdd m, 'zwei', 2addDup
    call tstMapLong m, 'eins'      ,201, 2000, -2, 2
    call tstMapLong m, 'zweiMal'   ,201, 2000, -2, 2
    call tstMapLong m, 'dreiMal'   ,201, 2000,  2,-2
    call tstMapLong m, 'vier   '   ,2010, 201, -2, 2
    call tstMapLong m, '<fuenf>'   ,2010, 201,  2,-2
    call mapClear m
    keys = mapKeys(m)
    call tstOut t, 'tstMap clear keys' m.keys.0
    i = mapInline('tstMapInline1')
    call tstOut t, 'inline1' m.i.0
    do x=1 to m.i.0
        call tstOut t, 'inline1' x '=='m.i.x'=='
        end
    i = mapInline('tstMapInline2')
    call tstOut t, 'inline2' m.i.0 '1 =='m.i.1'=='
    call tstOut t, 'inline3' mapInline('tstMapInline3', 'r')'?'
    call tstEnd t
    return
endProcedure tstMap

tstMapLong: procedure expose m.
parse arg m, w, f1, t1, f2, t2
    if f1 < t1 then
        b1 = 201
    else
        b1 = -201
    if f2 < t2 then
        b2 = 1
    else
        b2 = -1
    lo = copies(w, 2100 % length(w))
    keys = mapKeys(m)
    keyCn = m.keys.0
    call tstOut t, 'tstMapLong' w 'keys' keyCn
    do x = f1 by b1 to t1
        do y = x+f2 by b2 to x+t2
            k = left(lo, y)
            if mapHasKey(m, k) then
                call err 'mapLong hasKey before' w y
            call mapAdd m, k, w y
            if \ mapHasKey(m, k) then
                call err 'mapLong \ hasKey after' w y
            if mapGet(m, k) \== w y then
                call err 'mapLong \ get <> ' w y
            keys = mapKeys(m)
            if keyCn + 1 \= m.keys.0 then
                call err 'mapLong keys .0 <> ' w y
            keyCn = m.keys.0
            if k \== m.keys.keyCn then
                call err 'mapLong keys . ' keyCn '<>' w y
            end
        end
    return
endProcedure tstMapLong

tstMapVia: procedure expose m.
/*
$=/tstMapVia/
    ### start tst tstMapVia ###########################################
    map M K --> A
    mapVia(m, K)      A
    *** err: missing m.A at 3 in mapVia(M, K|)
    mapVia(m, K|)     M.A
    mapVia(m, K|)     valAt m.a
    mapVia(m, K|)     valAt m.a
    *** err: missing m.A.aB at 5 in mapVia(M, K|aB)
    mapVia(m, K|aB)   M.A.aB
    mapVia(m, K|aB)   valAt m.A.aB
    *** err: missing m.valAt m.a at 4 in mapVia(M, K||)
    mapVia(m, K||)    M.valAt m.a
    mapVia(m, K||)    valAt m.valAt m.a
    mapVia(m, K||F)   valAt m.valAt m.a.F
$/tstMapVia/ */
    call tst t, 'tstMapVia'
    u = 'A.aB'
    v = 'valAt m.a'
    drop m.a m.u m.v m.v.f
    call mapReset m, 'K'
    call mapAdd m, k, a
    call tstMapShow m, k
    call tstOut t, 'mapVia(m, K)     ' mapVia(m, 'K')
    call tstOut t, 'mapVia(m, K|)    ' mapVia(m, 'K|')
    m.a = v
    call tstOut t, 'mapVia(m, K|)    ' mapVia(m, 'K|')
    call tstOut t, 'mapVia(m, K|)    ' mapVia(m, 'K|')
    call tstOut t, 'mapVia(m, K|aB)  ' mapVia(m, 'K|aB')
    m.u = 'valAt m.'u
    call tstOut t, 'mapVia(m, K|aB)  ' mapVia(m, 'K|aB')
    call tstOut t, 'mapVia(m, K||)   ' mapVia(m, 'K||')
    v = m.a
    m.v = 'valAt m.'v
    m.v.f = 'valAt m.'v'.F'
    call tstOut t, 'mapVia(m, K||)   ' mapVia(m, 'K||')
    call tstOut t, 'mapVia(m, K||F)  ' mapVia(m, 'K||F')
    call tstEnd t
    return
endProcedure tstMapVia

tstMapShow: procedure expose m.
parse arg a, key
    if mapHasKey(a, key) then
        call tstOut t, 'map' a key '-->' mapGet(a, key)
    else
        call tstOut t, 'map' a key 'is not defined'
    return
endProcedure tstMapShow

tstMapShowSt: procedure expose m.
parse arg a, st
    call tstOut t, 'map stem' st m.st.0
    do wx=1 to m.st.0
        call tstMapShow a, m.st.wx
        end
    return
endProcedure tstMapShow

tstClass2: procedure expose m.
/*
$=/tstClass2/
    ### start tst tstClass2 ###########################################
    @CLASS.8 :class = u
    . choice u union
    .  .NAME = class
    . stem 8
    .  .1 refTo @CLASS.3 :class = u
    .   choice u union
    .    .NAME = v
    .   stem 2
    .    .1 refTo @CLASS.1 :class = m
    .     choice m union
    .      .NAME = asString
    .      .MET = return m.m
    .     stem 0
    .    .2 refTo @CLASS.2 :class = m
    .     choice m union
    .      .NAME = o2File
    .      .MET = return file(m.m)
    .     stem 0
    .  .2 refTo @CLASS.11 :class = c
    .   choice c union
    .    .NAME = u
    .   stem 1
    .    .1 refTo @CLASS.10 :class = u
    .     choice u union
    .      .NAME = .
    .     stem 1
    .      .1 refTo @CLASS.9 :class = f
    .       choice f union
    .        .NAME = NAME
    .       stem 1
    .        .1 refTo @CLASS.3 done :class @CLASS.3
    .  .3 refTo @CLASS.12 :class = c
    .   choice c union
    .    .NAME = f
    .   stem 1
    .    .1 refTo @CLASS.10 done :class @CLASS.10
    .  .4 refTo @CLASS.14 :class = c
    .   choice c union
    .    .NAME = s
    .   stem 1
    .    .1 refTo @CLASS.13 :class = u
    .     choice u union
    .      .NAME = .
    .     stem 0
    .  .5 refTo @CLASS.15 :class = c
    .   choice c union
    .    .NAME = c
    .   stem 1
    .    .1 refTo @CLASS.10 done :class @CLASS.10
    .  .6 refTo @CLASS.16 :class = c
    .   choice c union
    .    .NAME = r
    .   stem 1
    .    .1 refTo @CLASS.13 done :class @CLASS.13
    .  .7 refTo @CLASS.19 :class = c
    .   choice c union
    .    .NAME = m
    .   stem 1
    .    .1 refTo @CLASS.18 :class = u
    .     choice u union
    .      .NAME = .
    .     stem 2
    .      .1 refTo @CLASS.9 done :class @CLASS.9
    .      .2 refTo @CLASS.17 :class = f
    .       choice f union
    .        .NAME = MET
    .       stem 1
    .        .1 refTo @CLASS.3 done :class @CLASS.3
    .  .8 refTo @CLASS.21 :class = s
    .   choice s union
    .   stem 1
    .    .1 refTo @CLASS.20 :class = r
    .     choice r union
    .     stem 1
    .      .1 refTo @CLASS.8 done :class @CLASS.8
$/tstClass2/
*/

    call classIni
    call tst t, 'tstClass2'
    call classOut m.class_C, m.class_C
    call tstEnd t
    return
endProcedure tstClass2

tstClass3: procedure expose m.
/*
$=/tstClass3/
    ### start tst tstClass3 ###########################################
    met v#o2String return m.m
    met w#o2String return substr(m, 2)
    met w#o2String return substr(m, 2)
    *** err: no method nonono in class w
    met w#nonono 0
    t1 4 fldD .FV, .FR
    clear q1 FV= FR= FW= FO=
    orig R1 FV=valFV FR=refFR FW=]valFW FO=obj.FO
    copy <s1> FV=valFV FR=refFR FW=]valFW FO=obj.FO
    t2 2 fldD .EINS.ZWEI, .
    clear q2 EINS.ZWEI= val=
    orig R2 EINS.ZWEI=valR2.eins.zwei val=valR2Self
    copy <s2> EINS.ZWEI=valR2.eins.zwei val=valR2Self
    t3 0 fldD M.<class tst...Tf33>.FLDD.1, M.<class tst...Tf33>.FLDD.2
    clear q3 s1.0=0
    orig R3 s1.0=1 s1.1=M.R3.S1.1 s1.1.f1=M.R3.S1.1.F1 s1.1.s2.0=2 s1.1+
    ..s2.1.f2=M.R3.S1.1.S2.1.F2 s1.1.s2.2.f2=M.R3.S1.1.S2.2.F2
    copy <s3> s1.0=1 s1.1=M.R3.S1.1 s1.1.f1=M.R3.S1.1.F1 s1.1.s2.0=2 s1+
    ..1.s2.1.f2=M.R3.S1.1.S2.1.F2 s1.1.s2.2.f2=M.R3.S1.1.S2.2.F2
$/tstClass3/ */

    call classIni
    call tst t, 'tstClass3'
    call mAdd t.trans, m.class_C '<class class>'
    call tstOut t, 'met v#o2String' classMet(m.class_V, 'o2String')
    call tstOut t, 'met w#o2String' classMet(m.class_W, 'o2String')
    call tstOut t, 'met w#o2String' classMet(m.class_W, 'o2String')
    call tstOut t, 'met w#nonono' classMet(m.class_W, 'nonono')
    all = classNew('n? tstClassTf31 u f FV v, f FR r, f FW w,f FO o'),
          classNew('n? tstClassTf32 u f EINS f ZWEI v, v') ,
          classNew('n? tstClassTf33 u f S1' classNew('s u v, f F1 v,',
                          'f S2 s f F2 v'))
    call mAdd t.trans, word(all, 3) '<class tst...Tf33>'
    m.r1.fv = 'valFV'
    m.r1.fr = 'refFR'
    m.r1.fw = ']valFW'
    m.r1.fo = 'obj.FO'
    m.r2    = 'valR2Self'
    m.r2.eins.zwei  = 'valR2.eins.zwei'
    m.r3.s1.0 = 1
    m.r3.s1.1.s2.0 = 2
    o.1 = "q 'FV='m.q.FV 'FR='m.q.fr 'FW='m.q.fw 'FO='m.q.fo"
    o.2 = "q 'EINS.ZWEI='m.q.EINS.zwei 'val='m.q"
    o.3 = "q 's1.0='m.q.s1.0"
    p.1 = o.1
    p.2 = o.2
    p.3 = "q 's1.0='m.q.s1.0 's1.1='m.q.s1.1 's1.1.f1='m.q.s1.1.f1" ,
          "'s1.1.s2.0='m.q.s1.1.s2.0 's1.1.s2.1.f2='m.q.s1.1.s2.1.f2",
                                    "'s1.1.s2.2.f2='m.q.s1.1.s2.2.f2"
    do tx=1 to words(all)
        t1 = word(all, tx)
        u1 = classFldD(t1)
        q = 'q'tx
        call tstOut t, 't'tx m.u1.0 'fldD' m.u1.1',' m.u1.2
        call utInter("m='"q"';" classMet(t1, 'oClear'))
        interpret "call tstOut t, 'clear'" o.tx
        q = 'R'tx
        interpret "call tstOut t, 'orig'" p.tx
        q = utInter("m='"q"';t='';" classMet(t1, 'oCopy'))
        call mAdd t.trans, q '<s'tx'>'
        interpret "call tstOut t, 'copy'" p.tx
        end
    call tstEnd t
    return
endProcedure tstClass3

tstClass: procedure expose m.
/*
$=/tstClass/
    ### start tst tstClass ############################################
    Q u =className= tstClassTf12
    Q.eins.zwei v ==> M.Q.eins.zwei
    *** err: bad type v: classNew(v tstClassTf12)
    R u =className= uststClassTf12
    R u =className= uststClassTf12in
    R u =className= tstClassTf12
    R.eins.zwei v ==> M.R.eins.zwei
    R s =stem.0= 2
    R.1 r ==> M.R.1 :CLASS.7
    R.1 u =className= tstClassTf12
    R.1.eins.zwei v ==> M.R.1.eins.zwei
    R.2 r ==> M.R.2 :CLASS.7
    R.2 u =className= tstClassTf12
    R.2.eins.zwei v ==> M.R.2.eins.zwei
    S u =className= TstClass7
    S s =stem.0= 2
    S.1 u =className= TstClass7s
    S.1.eins v ==> M.S.1.eins
    S.1 m =met-metA--> say "metA"
    S.1 m =met-metB--> say "metB"
    S.2 u =className= TstClass7s
    S.2.zwei v ==> M.S.2.zwei
    S.2 m =met-metA--> say "metA"
    S.2 m =met-metB--> say "metB"
    class of mutate qq tstClassTf12
$/tstClass/ */

    f = 'eins.zwei'
    e = 'eins'
    z = 'zwei'
    drop m.q.f m.r.f m.r.0 m.r.1 m.r.1.f m.r.2 m.r.2.f
    drop m.s.0 m.s.1 m.s.1.e m.s.2 m.s.2.z
    call classIni
    call tst t, 'tstClass'
    t1  =  classNew('n? tstClassTf12 u f eins f zwei v')
    call tstClassOut t, t1, q
    z = m.class.0
    if class4name('tstClassB', '') == '' then
        t2 = classNew('n tstClassB u n tstClassC u tstClassTf12,',
            's u v tstClassTf12')
    else /*  the second time we would get a duplicate error */
        call tstOut t, '*** err: bad type v: classNew(v tstClassTf12)'
    t2 = classNew('n? uststClassTf12 u' ,
           'n? uststClassTf12in u tstClassTf12',
        , classNew('s u r, tstClassTf12'))
    m.r.0 = 2
    call tstClassOut t, t2, r
    t3 = classNew('n? TstClass7 u s',
         classNew('n? TstClass7s u c 1 f eins v, c 2 f zwei v',
            ,'m', 'metA say "metA"', 'metB say "metB"'))
    m.s.0 = 2
    m.s.1 = 1
    m.s.2 = 2
    call tstClassOut t, t3, s
    call oMutatName qq, 'tstClassTf12'
    tt = objClass(qq)
    call tstOut t, 'class of mutate qq' className(tt)
    call tstEnd t
    return
endProcedure tstClass

tstClassOut: procedure expose m.
parse arg o, t, a
    if wordPos(t, m.class_V m.class_W m.class_O) > 0 then
        return tstOut(o, a m.t.name '==>' m.a)
    if m.t == 'r' then
        return tstOut(o, a m.t '==>' m.a ':'if(m.t.0==0,'',m.t.1))
    if m.t == 'u' & m.t.name \== '' then
        call tstOut o, a m.t '=className=' m.t.name
    if m.t == 'f' then
        return tstClassOut(o, m.t.1, a'.'m.t.name)
    if m.t = 'u' then do
        do ux=1 to m.t.0
            call tstClassOut o, m.t.ux, a
            end
        return 0
        end
    if m.t = 's' then do
        call tstOut o, a m.t '=stem.0=' m.a.0
        do ux=1 to m.a.0
            call tstClassOut o, m.t.1, a'.'ux
            end
        return 0
        end
    if m.t = 'c' then do
        if m.t.name = m.a then
            call tstClassOut o, m.t.1, a
         return 0
        end
    if m.t = 'm' then
        return tstOut(o, a m.t '=met-'m.t.name'-->' m.t.met)
    call err 'bad class type' m.t
endProcedure tstClassOut

tstClass4: procedure expose m.
parse arg
/*
$=/tstClass4/
    ### start tst tstClass4 ###########################################
    f 1 eins
    f 2 zwei
    f 3 drei
    f 4 vier
    f 5 acht
    s 1 fuenf
    s 2 sechs
    s 3 sie
$/tstClass4/
*/
    call classIni
    call tst t, 'tstClass4'
    x = classNew('n* TstClass4a u f eins v, f%v zwei drei, f vier v',
                             ', f%s-v fuenf sechs sie, f acht v')
    ff = classFlds(x)
    do fx=1 to m.ff.0
        call tstOut t, 'f' fx m.ff.fx
        end
    st = classMet(x, 'stms')
    do sx=1 to m.st.0
        call tstOut t, 's' sx m.st.sx
        end
    call tstEnd t
    return
endProcedure tstClass4

tstO: procedure expose m.
/*
$=/tstO/
    ### start tst tstO ################################################
    o1.class <class_S>
    o1.class <class T..1>
    o1#met1 metEins
    o1#met2 metZwei
    o1#new m = mNew('<class T..1>'); call oMutate m, '<class T..1>'; ca+
    ll classClear '<class T..1>', m;
$/tstO/
*/
    call classIni
    call tst t, 'tstO'
    call mAdd t.trans, m.class_s '<class_S>'
    c1 = classNew('n? TstOCla1 u', 'm', 'met1 metEins', 'met2 metZwei')
    call mAdd t.trans, c1 '<class T..1>'
    o1 = 'tst_o1'
    call tstOut t, 'o1.class' objClass(o1)
    o1 = oMutate('o1', c1)
    call tstOut t, 'o1.class' objClass(o1)
    call tstOut t, 'o1#met1' objMet(o1, 'met1')
    call tstOut t, 'o1#met2' objMet(o1, 'met2')
    call tstOut t, 'o1#new' objMet(o1, 'new')
    call tstEnd t
    return
endProcedure tstO


tstOEins: procedure expose m.
/*
$=/tstOEins/
    ### start tst tstOEins ############################################
    class method calls of TstOEins
    .  met Eins.eins M
     flds of <obj e of TstOEins> FEINS, FZWEI
     methodcalls of object e of TstOEins
    .  met Eins.eins <obj e of TstOEins>
    .  met Eins.zwei <obj e2 of TstOEins>
    *** err: no method nein in class TstOEins
    *** err: no method nein in class String
    class method calls of TstOEins
    .  met Elf.zwei M
    flds of <obj f of TstOElf> FEINS, FZWEI, FELF
    methodcalls of object f of TstOElf
    .  met Eins.eins <obj f of TstOElf>
    .  met Elf.zwei <obj f of TstOElf>
    .  met Elf.drei <obj f of TstOElf>
    oCopy c1 of class TstOEins, c2
    C1 u =className= TstOEins
    C1.FEINS v ==> M.C1.FEINS
    C1.FZWEI v ==> M.C1.FZWEI
    C1 m =met-eins--> call tstOut t, "  met Eins.eins" m
    C1 m =met-zwei--> call tstOut t, "  met Eins.zwei" m
    C2 u =className= TstOEins
    C2.FEINS v ==> M.C1.FEINS
    C2.FZWEI v ==> M.C1.FZWEI
    C2 m =met-eins--> call tstOut t, "  met Eins.eins" m
    C2 m =met-zwei--> call tstOut t, "  met Eins.zwei" m
    oCopy c3 of class TstOElf, c4
    C4 u =className= TstOElf
    C4 u =className= TstOEins
    C4.FEINS v ==> M.C3.FEINS
    C4.FZWEI v ==> M.C3.FZWEI
    C4 m =met-eins--> call tstOut t, "  met Eins.eins" m
    C4 m =met-zwei--> call tstOut t, "  met Eins.zwei" m
    C4.FELF r ==> M.C3.FELF :<class O>
    C4 m =met-zwei--> call tstOut t, "  met Elf.zwei" m
    C4 m =met-drei--> call tstOut t, "  met Elf.drei" m
    tEinsDop <class TstOEins>
    oRun 7*3 21
    oRun 12*12 144
$/tstOEins/ */
    call classIni
    call tst t, 'tstOEins'
    tEins = classNew('n? TstOEins u f FEINS v,f FZWEI v', 'm',
           , 'eins call tstOut t, "  met Eins.eins" m',
           , 'zwei call tstOut t, "  met Eins.zwei" m')
    call mAdd t.trans, tEins '<class TstOEins>' ,
                   , m.class_o '<class O>'
    call tstOut t, 'class method calls of TstOEins'
    interpret classMet('TstOEins', 'eins')
    e = oNew('TstOEins')
    e2 = oNew('TstOEins')
    call mAdd t.trans, e '<obj e of TstOEins>'
    call mAdd t.trans, e2 '<obj e2 of TstOEins>'
    call tstOut t, 'flds of' e mCat(oFlds(e), ', ')
    call tstOut t, 'methodcalls of object e of TstOEins'
    call tstOmet e, 'eins'
    call tstOmet e2, 'zwei'
    call tstOmet e, 'nein'
    call tstOmet 'noObj', 'nein'
    tElf = classNew('n? TstOElf u TstOEins, f FELF r', 'm',
        , 'zwei call tstOut t, "  met Elf.zwei" m',
        , 'drei call tstOut t, "  met Elf.drei" m')
    call tstOut t, 'class method calls of TstOEins'
    interpret classMet('TstOElf', 'zwei')
    f = oNew('TstOElf')
    call mAdd t.trans, f '<obj f of TstOElf>'
    call tstOut t, 'flds of' f mCat(oFlds(f), ', ')
    call tstOut t, 'methodcalls of object f of TstOElf'
    call tstOmet f, 'eins'
    call tstOmet f, 'zwei'
    call tstOmet f, 'drei'
    call oMutatName c1, 'TstOEins'
    call tstOut t, 'oCopy c1 of class TstOEins, c2'
    call tstClassOut t, tEins, c1
    call oCopy c1, c2
    call tstClassOut t, tEins, c2
    call tstOut t, 'oCopy c3 of class TstOElf, c4'
    call oMutatName c3, 'TstOElf'
    call oCopy c3, c4
    call tstClassOut t, tElf, c4

/*    tEinsDop = classNew('n TstOEins u f FEINS v,f FZWEI v', 'm',
           , 'eins call tstOut t, "  met Eins.eins" m',
           , 'zwei call tstOut t, "  met Eins.zwei" m')
*/ tEinsDop = tEins
    call tstOut t, 'tEinsDop' tEinsDop
    e3 = oNew('TstOEins')
    if e3 <<= e | e3 <<= e2 then
        call err 'doppelt reinitialised objects'
    rr = oRunner('return 7 * 3')
    call tstOut t, 'oRun 7*3' oRun(rr)
    r12 = oRunner('return 12 * 12')
    call tstOut t, 'oRun 12*12' oRun(r12)
    call tstEnd t
    return
endProcedure tstOEins

tstOmet: procedure expose m.
parse arg m, met
    interpret objMet(m, met)
    return
endProcedure tstOmet

tstOStr: procedure expose m.
/*
$=/tstOStr/
    ### start tst tstOStr #############################################
    . kindOfStri 1
    . asString   .
    . asString - .
    . o2String   .
    abc kindOfStri 1
    abc asString   abc
    abc asString - abc
    abc o2String   abc
    ]defg kindOfStri 1
    ]defg asString   defg
    ]defg asString - defg
    ]defg o2String   defg
    TST_STR kindOfStri 0
    *** err: TST_STR is not a kind of string but has class TstStr
    TST_STR asString   0
    TST_STR asString - -
    *** err: no method o2String in class TstStr
    *** err: o2String did not return
    TST_STR o2String   0
    lllllll... kindOfStri 1
    lllllll... asString   llllllllll
    lllllll... asString - llllllllll
    lllllll... o2String   llllllllll
$/tstOStr/
*/
    call classIni
    o = oMutate(tst_str, classNew('n? TstStr u'))
    call mAdd mCut(tstStr, 0), '', 'abc', ']defg', o, left('',500,'l')
    call tst t, 'tstOStr'
    do ix=1 to m.tstStr.0
        e = m.tstStr.ix
        f = e
        if length(e) > 10 then
            f = left(e, 7)'...'
        call tstOut t, f 'kindOfStri' oKindOfString(e)
        call tstOut t, f 'asString  ' strip(left(oAsString(e),10))
        call tstOut t, f 'asString -' strip(left(oAsString(e,'-'),10))
        call tstOut t, f 'o2String  ' strip(left(o2String(e),10))
        end
    call tstEnd t
    return
endProcedure tstOStr

tstO2Text: procedure expose m.
/*
$=/o2Text/
    ### start tst o2Text ##############################################
    .             > .
    und _s abc   > und so
    und _s lang  > und so und so und so und so und so und so und so und+
    . so und so ....
    ]und _w abc  > und so
    o1           > tstO2T1=[fEins=v_o1_fEins fZwei=v_o1_fZwei fDrei=v_o+
    1_fDrei]
    o1 lang      > tstO2T1=[fEins=v_o1_fEins fZwei=v_o1_fZweiv_o1_fZwei+
    v_o1_fZwei...]
    o2           > tstO2T2=[f2f=v_o2_f2f =value_o2]
    runner       > <tstRunObj>=[<tstRunCla>]
    file         > <tstFileObj>=[File]
$/o2Text/
*/
    call catIni
    cl = classNew('n* TstO2Text1 u f fEins v, f fZwei v, f fDrei v')
    o1 = oMutate('tstO2T1', cl)
    o1 = oMutate('tstO2T1', cl)
    call oMutate o1, cl
    call mPut o1'.fEins', 'v_o1_fEins'
    call mPut o1'.fZwei', 'v_o1_fZwei'
    call mPut o1'.fDrei', 'v_o1_fDrei'
    call tst t, 'o2Text'
    c2 = classNew('n? TstO2Text2 u f f2f v, v')
    o2 = oMutate('tstO2T2', c2)
    call mPut o2'.f2f', 'v_o2_f2f'
    call mPut o2      , 'value_o2'
    maxL = 66
    call tstOut t, '             >' o2Text('         ', maxL)
    call tstOut t, 'und _s abc   >' o2Text('und so   ', maxL)
    call tstOut t, 'und _s lang  >' o2Text(copies('und so ',33), maxL)
    call tstOut t, ']und _w abc  >' o2Text('und so   ', maxL)
    call tstOut t, 'o1           >' o2Text(o1         , maxL)
    call mPut o1'.fZwei', copies('v_o1_fZwei',33)
    call tstOut t, 'o1 lang      >' o2Text(o1         , maxL)
    call tstOut t, 'o2           >' o2Text(o2         , maxL)
    f = file('abc.efg')
    r = oRunner('say o2Text test')
    call mAdd t.trans, r '<tstRunObj>',
                     , className(objClass(r)) '<tstRunCla>' ,
                     , f '<tstFileObj>'
    call tstOut t, 'runner       >' o2Text(r          , maxL)
    call tstOut t, 'file         >' o2Text(f          , maxL)
    call mAdd t.trans, r '<tstRunnerObj>',
                     , className(objClass(r)) '<tstRunnerCla>'
    call tstEnd t
    return
endProcedure tstO2Text

tstJSay: procedure expose m.
/*
$=/tstJSay/
    ### start tst tstJSay #############################################
    *** err: bad option openArg in jOpen(<obj j of JRW>, openArg)
    *** err: jWrite(<obj j of JRW>) but not open+
    ed w
    *** err: can only write JSay#jOpen(<obj s of JSay>, <)
    *** err: jWrite(<obj s of JSay>) but not op+
    ened w
    *** err: JRWEof#open(<obj e of JRWEof>, >)
    *** err: jRead(<obj e of JRWEof>) but not opened r
    read e vor open 0 m.xx valueBefore
    read e nach open 0 m.xx valueBefore
    out eins
    #jIn 1# tst in line 1 eins ,
    out zwei in 1 vv=readAdrVV
    #jIn 2# tst in line 2 zwei ;   .
    out drei in 1 vv=readAdrVV Schluss
$/tstJSay/ */

    call jIni
    call tst t, 'tstJSay'
    jrw = oNew('JRW')
    call mAdd t'.TRANS', jrw '<obj j of JRW>'
    call jOpen jrw, 'openArg'
    call jWrite jrw, 'writeArg'
    s = oNew('JSay')
    call mAdd t'.TRANS', s '<obj s of JSay>'
    call jOpen s, m.j.cRead
    s = oNew('JSay')
    call mAdd t'.TRANS', s '<obj s of JSay>'
    call jWrite s, 'write s vor open'
    call jOpen s, '>'
    call jWrite s, 'write s nach open'
    e = oNew('JRWEof')
    call mAdd t'.TRANS', e '<obj e of JRWEof>'
    call jOpen e, '>'
    e = oNew('JRWEof')
    call mAdd t'.TRANS', e '<obj e of JRWEof>'
    m.xx = 'valueBefore'
    call tstOut t, 'read e vor open' jReadVar(e, xx) 'm.xx' m.xx
    call jOpen e, m.j.cRead
    call tstOut t, 'read e nach open' jReadVar(e, xx) 'm.xx' m.xx
    call out 'out eins'
    vv = 'readAdrVV'
    m.vv = 'readAdrVVValueBefore'
    call out 'out zwei in' in() 'vv='vv
    m.vv = 'readAdrVVValueBefore'
    call out 'out drei in' inVar(vv) 'vv='vv 'Schluss'
    call tstEnd t
    return
endProcedure tstJSay

tstJ: procedure expose m.
/*
$=/tstJ/
    ### start tst tstJ ################################################
    out eins
    #jIn 1# tst in line 1 eins ,
    1 in() tst in line 1 eins ,
    #jIn 2# tst in line 2 zwei ;   .
    2 in() tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    3 in() tst in line 3 drei .schluss..
    #jIn eof 4#
    in() 3 reads vv VV
    line buf line one
    line buf line two
    line buf line three
    line buf line four
    *** err: jWrite(<buf b>) but not opened w
$/tstJ/ */

    call jIni
    call tst t, "tstJ"
    b = jOpen(jBuf(), '>')
    call mAdd t'.TRANS', b '<buf b>'
    call out 'out eins'
    do lx=1 by 1 while in()
        call out lx 'in()' m.in
        end
    call out 'in()' (lx-1) 'reads vv' vv
    call jOpen b, '>'
    call jWrite b, 'buf line one'
    call jClose b
    call mAdd b'.BUF', 'buf line two', 'buf line three'
    call jWrite b, 'buf line four'
    call jClose b
    call jOpen b, m.j.cRead
    do while jRead(b)
        call out 'line' m.b
        end
    call jWrite b, 'buf line five while reading'
    call jClose b
    call tstEnd t
    return
endProcedure tstJ

tstJ2: procedure expose m.
/*
$=/tstJ2/
    ### start tst tstJ2 ###############################################
    class1 <Tst?1 class> <Tst?1 name>
    class2 <Tst?1 class> <Tst?1 name>
    class3 <Tst?1 class> <Tst?1 name>
    b read EINS feld eins, ZWEI feld zwei, DREI feld drei
    b read EINS feld eins, ZWEI feld zwei 2, DREI feld drei
    c read EINS feld eins, ZWEI feld zwei, DREI drei cat 1
    tstR: @tstWriteoV3 isA :<Tst?1 name>
    tstR:  .EINS = feld eins
    tstR:  .ZWEI = feld zwei
    tstR:  .DREI = drei cat 1
    c read EINS feld eins, ZWEI feld zwei 2, DREI drei cat 2
    tstR: @tstWriteoV4 isA :<Tst?1 name>
    tstR:  .EINS = feld eins
    tstR:  .ZWEI = feld zwei 2
    tstR:  .DREI = drei cat 2
$/tstJ2/ */

    call jIni
    call tst t, "tstJ2"
    ty = classNew('n* Tst u f EINS v, f ZWEI v, f DREI v')
    call mAdd t'.TRANS', ty '<Tst?1 class>'
    call mAdd t'.TRANS', m.ty.name '<Tst?1 name>'
    call tstOut t, 'class1' ty m.ty.name
    ty = classNew('n* Tst u f EINS v, f ZWEI v, f DREI v')
    call tstOut t, 'class2' ty m.ty.name
    ty = classNew('n* Tst u f EINS v, f ZWEI v, f DREI v')
    call tstOut t, 'class3' ty m.ty.name
    call oMutate qq, ty
    m.qq.eins = 'feld eins'
    m.qq.zwei = 'feld zwei'
    m.qq.drei = 'feld drei'
    b = jBuf()
    call jOpen b, '>'
    call jWrite b, oCopy(qq)
    m.qq.zwei = 'feld zwei 2'
    call jWrite b, qq
    call jOpen jClose(b), m.j.cRead
    c = jOpen(jBuf(), '>')
    do xx=1 while jRead(b)
        res = m.b
        call out 'b read EINS' m.res.eins', ZWEI' m.res.zwei,
                                     || ', DREI' m.res.drei
        m.res.drei = 'drei cat' xx
        call jWrite c, res
        end
    call jOpen jClose(c), m.j.cRead
    do while jRead(c)
        ccc = m.c
        call out 'c read EINS' m.ccc.eins', ZWEI' m.ccc.zwei,
                                     || ', DREI' m.ccc.drei
        call out ccc
        end
    call tstEnd t
    return
endProcedure tstJ2

tstCat: procedure expose m.
/*
$=/tstCat/
    ### start tst tstCat ##############################################
    catRead 1 line 1
    catRead 2 line 2
    catRead 3 line 3
    appRead 1 line 1
    appRead 2 line 2
    appRead 3 line 3
    appRead 4 append 4
    appRead 5 append 5
$/tstCat/ */
    call catIni
    call tst t, "tstCat"
    i = cat(jBuf('line 1', 'line 2'), jBuf('line 3'))
    call jOpen i, m.j.cRead
    do lx=1 by 1 while jRead(i)
        call tstOut t, 'catRead' lx m.i
        end
    call jOpen jClose(i), m.j.cApp
    call jWrite i, 'append 4'
    call jWrite i, 'append 5'
    call jOpen jClose(i), m.j.cRead
    do lx=1 by 1 while jRead(i)
        call tstOut t, 'appRead' lx m.i
        end
    call tstEnd t
    return
endProcedure tstCat

tstEnv: procedure expose m.
    call pipeIni
/*
$=/tstEnv/
    ### start tst tstEnv ##############################################
    before pipeBeLa
    after pipeEnd
    #jIn 1# tst in line 1 eins ,
    #jIn 2# tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    #jIn eof 4#
    before writeNow 2 c --> std
    before writeNow 1 b --> c
    b line eins
    b zwei |
    nach writeNow 1 b --> c
    add nach pop
    after push c only
    tst in line 1 eins ,
    tst in line 2 zwei ;   .
    tst in line 3 drei .schluss..
    nach writeNow 2 c --> std
    *** err: jWrite(<jBuf c>) but not opened w
$/tstEnv/ */

    call tst t, "tstEnv"
    c = jBuf()
    call mAdd t'.TRANS', c '<jBuf c>'
    call out 'before pipeBeLa'
    b = jBuf("b line eins", "b zwei |")
    call pipe '+Ff', c, b
    call out 'before writeNow 1 b --> c'
    call pipeWriteNow
    call out 'nach writeNow 1 b --> c'
    call pipe '-'
    call out 'after pipeEnd'
    call mAdd c'.BUF', 'add nach pop'
    call pipe '+A', c
    call out 'after push c only'
    call pipeWriteNow
    call pipe '-'
    call pipe '+f', , c
    call out 'before writeNow 2 c --> std'
    call pipeWriteNow
    call out 'nach writeNow 2 c --> std'
    call pipe '-'
    call jWrite c
    call tstEnd t
    return
endProcedure tstEnv

tstEnvLong: procedure expose m.
    call pipeIni
/*
$=/tstEnvLong/
    ### start tst tstEnvLong ##########################################
    before pipeWriteAll
    after  pipeWriteAll
    file out 1010 = comp 1010
$/tstEnvLong/
*/

    call tst t, "tstEnvLong"
    o = tstFileName('envLong', 'r')
    q = time() date()
    b = jBuf()
    do ix=1 to 100
        m.b.buf.ix = ix q
        end
    m.b.buf.0 = 100
    i = jOpen(cat(), '>')
    c = 'tstEnvLongC'
    m.c.0 = 0
    do ix=1 to 10
        call jWrite i, 'vor loop' ix
        call mAdd c, 'vor loop' ix
        call jWriteAll i, b
        call maddSt c, b'.BUF'
        end
    call pipe '+Ff', file(o '::f'), jClose(i)
    call tstOut t, 'before pipeWriteAll'
    call pipeWriteAll
    call tstOut t, 'after  pipeWriteAll'
    call pipe '-'
    p = jOpen(file(o), '<')
    do ix = 1 while jRead(p)
        if m.c.ix <> m.p then
           call tstOut t,  ix '<>' m.c.ix '<>' m.p
           end
    call jClose p
    call tstOut t, 'file out' (ix-1) '= comp' m.c.0
    call tstEnd t
    return
endProcedure tstEndLong

tstEnvCat: procedure expose m.
    call pipeIni
/*
$=/tstEnvCat/
    ### start tst tstEnvCat ###########################################
    c1 contents
    c1 line eins |
    before writeNow 1 b* --> c*
    b1 line eins|
    b2 line eins
    b2 zwei |
    c2 line eins |
    after writeNow 1 b* --> c*
    c2 contents
    c2 line eins |
$/tstEnvCat/ */

    call tst t, "tstEnvCat"

    b0= jBuf()
    b0= jBuf()
    b1= jBuf("b1 line eins|")
    b2 = jBuf("b2 line eins", "b2 zwei |")
    c1 = jBuf("c1 line eins |")
    c2 = jBuf("c2 line eins |")
    call pipe '+Affff', c1, b0, b1, b2, c2
    call out 'before writeNow 1 b* --> c*'
    call pipeWriteNow
    call out 'after writeNow 1 b* --> c*'
    call pipe '-'
    call out 'c1 contents'
    call pipe '+f' , , c1
    call pipeWriteNow
    call pipe '-'
    call pipe '+f' , , c2
    call out 'c2 contents'
    call pipeWriteNow
    call pipe '-'
    call tstEnd t
    return
endProcedure tstEnvCat

tstPipe: procedure expose m.
    call pipeIni
/*
$=/tstPipe/
    ### start tst tstPipe #############################################
    .+0 vor pipeBegin
    #jIn 1# tst in line 1 eins ,
    #jIn 2# tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    #jIn eof 4#
    .+7 nach pipeLast
    [7 +6 nach pipe 7]
    [7 +2 nach pipe 7]
    [7 +4 nach nested pipeLast 7]
    [7 (4 +3 nach nested pipeBegin 4) 7]
    [7 (4 (3 +1 nach pipeBegin 3) 4) 7]
    [7 (4 (3 tst in line 1 eins , 3) 4) 7]
    [7 (4 (3 tst in line 2 zwei ;    3) 4) 7]
    [7 (4 (3 tst in line 3 drei .schluss. 3) 4) 7]
    [7 (4 (3 +1 nach writeNow vor pipe 3) 4) 7]
    [7 (4 +3 nach preSuf vor nested pipeLast 4) 7]
    [7 +4 nach preSuf vor nested pipeEnd 7]
    [7 +5 nach nested pipeEnd vor pipe 7]
    [7 +6 nach writeNow vor pipeLast 7]
    .+7 nach writeNow vor pipeEnd
    .+8 nach pipeEnd
$/tstPipe/ */

    say 'x0' m.pipe.0
    call tst t, 'tstPipe'
    call out '+0 vor pipeBegin'
    say 'x1' m.pipe.0
    call pipe '+N'
    call out '+1 nach pipeBegin'
    call pipeWriteNow
    call out '+1 nach writeNow vor pipe'
    call pipe 'N|'
    call out '+2 nach pipe'
    call pipe '+N'
    call out '+3 nach nested pipeBegin'
    call pipePreSuf '(3 ', ' 3)'
    call out '+3 nach preSuf vor nested pipeLast'
    call pipe 'P|'
    call out '+4 nach nested pipeLast'
    call pipePreSuf '(4 ', ' 4)'
    call out '+4 nach preSuf vor nested pipeEnd'
    call pipe '-'
    call out '+5 nach nested pipeEnd vor pipe'
    call pipe 'N|'
    call out '+6 nach pipe'
    call pipeWriteNow
    say 'out +6 nach writeNow vor pipeLast'
    call out '+6 nach writeNow vor pipeLast'
    call pipe 'P|'
    call out '+7 nach pipeLast'
    call pipePreSuf '[7 ', ' 7]'
    call out '+7 nach writeNow vor pipeEnd'
    call pipe '-'
    call out '+8 nach pipeEnd'
    say 'xx' m.pipe.0
    call tstEnd t
    return
endProcedure tstPipe

tstPipeS: procedure expose m.
/*
$=/tstPipeS/
    ### start tst tstPipeS ############################################
    eine einzige zeile
    nach all einzige Zeile
    select strip(creator) cr, strip(name) tb,
    (row_number()over())*(row_number()over()) rr
    from sysibm.sysTables
$/tstPipeS/
*/
    call pipeIni
    call tst t, "tstPipeS"
    call pipe '+s',, 'eine einzige zeile'
    call pipeWriteAll
    call out 'nach all einzige Zeile'
    call pipe 'sss',,
              , "select strip(creator) cr, strip(name) tb," ,
              ,      "(row_number()over())*(row_number()over()) rr" ,
              ,      "from sysibm.sysTables"
    call pipeWriteAll
    call pipe '-'
    call tstEnd t
    return
endProcedure tstPipeS

tstEnvVars: procedure expose m.
    call pipeIni
/*
$=/tstEnvVars/
    ### start tst tstEnvVars ##########################################
    put v1 value eins
    v1 hasKey 1 get TST.ADR1
    v2 hasKey 0
    one to theBur
    two to theBuf
    v1=TST.ADR1 o=TST.ADR1
    v3=v3WieGehts? o=v3WieGehts?
    v4=]v4WieGehts? o=]v4WieGehts?
    o o0=<o0>
    s o0=<o0>
    o o0=<o0>
    s o0=<o0>
    o0&fSt0=rexx o0.fSt0 o=rexx o0.fSt0
    o0&fRe0=]rexx o0.fRe0 o=]rexx o0.fRe0
    o0&=rexx o0-value o=rexx o0-value
    o o0=<o0>
    s o0=<o0>
    o0&fSt0=put o0.fSt0 o=put o0.fSt0
    o0&fRe0=]putO o0.fRe0 o=]putO o0.fRe0
    o0&=put o0-value o=put o0-value
$/tstEnvVars/
$=/tstEnvVars1/
    ### start tst tstEnvVars1 #########################################
    m.o1=put-o1-value m.o1.fStr=put-o1.fStr m.o1.fRef=<o0>
    o o1=<o1> s o1=<o1>
    o1&fStr=put-o1.fStr o=put-o1.fStr
    o1&=put-o1-value o=put-o1-value
    o1&fRef=<o0> o=<o0>
    o1&fRef>fSt0=put o0.fSt0 o=put o0.fSt0
    o1&fRef>fRe0=]putO o0.fRe0 o=]putO o0.fRe0
    m.o1&fNest.fSt0= put-o1.fNest.fSt0 m.o1&fNest.fRe0= ]put-o1&fNest.f+
    Re0
    o1&fNest.fSt0=put-o1.fNest.fSt0 o=put-o1.fNest.fSt0
    o1&fNest&fRe0=]put-o1&fNest.fRe0 o=]put-o1&fNest.fRe0
$/tstEnvVars1/
$=/tstEnvVars2/
    ### start tst tstEnvVars2 #########################################
    o2=<o2> getO(o2)=<o2> getO(o2&fRef)=<o1>
    o2&fRef>fStr=put-o1.fStr o=put-o1.fStr
    o2&fRef>=put-o1-value o=put-o1-value
    o2&fRef>fRef=<o0> o=<o0>
    o2&fRef>fRef>fSt0=put o0.fSt0 o=put o0.fSt0
    o2&fRef>fRef>fRe0=]putO o0.fRe0 o=]putO o0.fRe0
    o2&fRef>fNest.fSt0=put-o1.fNest.fSt0 o=put-o1.fNest.fSt0
    o2&fRef>fNest&fRe0=]put-o1&fNest.fRe0 o=]put-o1&fNest.fRe0
$/tstEnvVars2/
$=/tstEnvVarsS/
    ### start tst tstEnvVarsS #########################################
    oS=<oS> oS&fStS=<put oS.fStS>
    oS&fStV.0=1 oS&fStV.1=<put oS.fStV.1>
    m.oS.fStR.0=2 .2=]<put oS.fStR.2>
    oS&fStR.0=2 .1=]<put oS.fStR.1> .2=]<put oS.fStR.2>
    m.oS.0=9876 .1234=<put oS.1234>
    *** err: undefined var oS&12
    oS&0=9876 .12=M. .1234=<put oS.1234>
$/tstEnvVarsS/
$=/tstEnvVars3/
    ### start tst tstEnvVars3 #########################################
    m.<o0>=*o0*val vGet(<o0>>)=*o0*val
    m.<o0>.fSt0=*o0.fSt0*val vGet(<o0>>fSt0)=*o0.fSt0*val
    m.<o0>.fRe0=<o1> vGet(<o0>>fRe0)=<o1>
    m.<o1>=*o1*val vGet(<o0>>fRe0>)=*o1*val
    m.<o1>.fStr=*o1.fStr*val vGet(<o0>>fRe0>fStr)=*o1.fStr*val
    m.V.tstEnvVar0=<o0> vGet(tstEnvVar0)=<o0>
    m.V.tstEnvVar0=<o0> vGet(tstEnvVar0&)=<o0>
    m.<o0>=*o0*val vGet(tstEnvVar0&>)=*o0*val
    m.<o0>.fSt0=*o0.fSt0*val vGet(tstEnvVar0&fSt0)=*o0.fSt0*val
    m.<o0>.fRe0=<o1> vGet(tstEnvVar0&fRe0)=<o1>
    m.<o1>=*o1*val vGet(tstEnvVar0&fRe0>)=*o1*val
    m.<o1>.fStr=*o1.fStr*val vGet(tstEnvVar0&fRe0>fStr)=*o1.fStr*val
    m.<o1>.fVar=tstEnvVar2 vGet(tstEnvVar0&fRe0>fVar)=tstEnvVar2
    m.<o2>=*o2*val vGet(tstEnvVar0&fRe0>fVar&)=<o2>
    m.<o2>=*o2*val vGet(tstEnvVar0&fRe0>fVar&>)=*o2*val
    m.<o2>.fStr=*o2.fStr*val vGet(tstEnvVar0&fRe0>fVar&fStr)=*o2.fStr*v+
    al
    m.<o0>=*o0*put2 vGet(<o0>>)=*o0*put2
    m.<o0>.fSt0=*o0.fSt0*put2 vGet(<o0>>fSt0)=*o0.fSt0*put2
    m.<o1>=*o0>fRe0>put2 vGet(<o0>>fRe0>)=*o0>fRe0>put2
    m.<o1>.fStr=*o0>fRe0>fStr*put2 vGet(<o0>>fRe0>fStr)=*o0>fRe0>fStr*p+
    ut2
    m.<o0>=*v0&>*put3 vGet(tstEnvVar0&>)=*v0&>*put3
    m.<o0>.fSt0=*v0&fSt0*put3 vGet(tstEnvVar0&fSt0)=*v0&fSt0*put3
    m.<o1>=*v0&fRe0>*put3 vGet(tstEnvVar0&fRe0>)=*v0&fRe0>*put3
    m.<o1>.fStr=*v0&fRe0>fStr*put3 vGet(tstEnvVar0&fRe0>fStr)=*v0&fRe0>+
    fStr*put3
    m.<o2>=*v0&fRe0>fVar&>*put3 vGet(tstEnvVar0&fRe0>fVar&>)=*v0&fRe0>f+
    Var&>*put3
    m.<o2>.fStr=*v0&fRe0>fVar&fStr*put3 vGet(tstEnvVar0&fRe0>fVar&fStr)+
    =*v0&fRe0>fVar&fStr*put3
$/tstEnvVars3/
 */
    c0 = classNew('n? TstEnvVars0 u f fSt0 v, f = v, f fRe0 r')
    c1 = classNew('n? TstEnvVars1 u f fStr v,f fRef r' ,
              ', f fNest TstEnvVars0, f = v, f fVar v')
    o0 = oNew(c0)
    o1 = oNew(c1)
    o2 = oNew(c1)
    call tst t, "tstEnvVars3"
    call mAdd t.trans, o0 '<o0>', o1 '<o1>', o2 '<o2>'
    fSt0 = 'fSt0'
    fRe0 = 'fRe0'
    fStr = 'fStr'
    fRef = 'fRef'
    fVar = 'fVar'
    v0 = 'tstEnvVar0'
    v2 = 'tstEnvVar2'
    m.o0 = '*o0*val'
    m.o0.fSt0 = '*o0.fSt0*val'
    m.o0.fRe0 = o1
    m.o1 = '*o1*val'
    m.o1.fStr = '*o1.fStr*val'
    m.o1.fRef = o2
    m.o1.fVar = v2
    m.o2 = '*o2*val'
    m.o2.fStr = '*o2.fStr*val'
    m.v.v0 = o0
    m.v.v2 = o2
    call tstEnvVarsMG o0, o0'>'
    call tstEnvVarsMG o0'.'fSt0, o0'>'fSt0
    call tstEnvVarsMG o0'.'fRe0, o0'>'fRe0
    call tstEnvVarsMG o1, o0'>'fRe0'>'
    call tstEnvVarsMG o1'.'fStr, o0'>'fRe0'>'fStr
    call tstEnvVarsMG v'.'v0, v0
    call tstEnvVarsMG v'.'v0, v0'&'
    call tstEnvVarsMG o0, v0'&>'
    call tstEnvVarsMG o0'.'fSt0, v0'&'fSt0
    call tstEnvVarsMG o0'.'fRe0, v0'&'fRe0
    call tstEnvVarsMG o1, v0'&'fRe0'>'
    call tstEnvVarsMG o1'.'fStr, v0'&'fRe0'>'fStr
    call tstEnvVarsMG o1'.'fVar, v0'&'fRe0'>'fVar
    call tstEnvVarsMG o2, v0'&'fRe0'>'fVar'&'
    call tstEnvVarsMG o2, v0'&'fRe0'>'fVar'&>'
    call tstEnvVarsMG o2'.'fStr, v0'&'fRe0'>'fVar'&fStr'
    call vPut o0'>', '*o0*put2'
    call tstEnvVarsMG o0, o0'>'
    call vPut o0'>'fSt0, '*o0.fSt0*put2'
    call tstEnvVarsMG o0'.'fSt0, o0'>'fSt0
    call vPut o0'>'fRe0'>', '*o0>fRe0>put2'
    call tstEnvVarsMG o1, o0'>'fRe0'>'
    call vPut o0'>'fRe0'>'fStr, '*o0>fRe0>fStr*put2'
    call tstEnvVarsMG o1'.'fStr, o0'>'fRe0'>'fStr
    call vPut v0'&>', '*v0&>*put3'
    call tstEnvVarsMG o0, v0'&>'
    call vPut v0'&'fSt0, '*v0&fSt0*put3'
    call tstEnvVarsMG o0'.'fSt0, v0'&'fSt0
    call vPut v0'&'fRe0'>', '*v0&fRe0>*put3'
    call tstEnvVarsMG o1, v0'&'fRe0'>'
    call vPut v0'&'fRe0'>'fStr, '*v0&fRe0>fStr*put3'
    call tstEnvVarsMG o1'.'fStr, v0'&'fRe0'>'fStr
    call vPut v0'&'fRe0'>'fVar'&>', '*v0&fRe0>fVar&>*put3'
    call tstEnvVarsMG o2, v0'&'fRe0'>'fVar'&>'
    call vPut v0'&'fRe0'>'fVar'&fStr', '*v0&fRe0>fVar&fStr*put3'
    call tstEnvVarsMG o2'.'fStr, v0'&'fRe0'>'fVar'&fStr'
    call tstEnd t, "tstEnvVars"
    call tst t, "tstEnvVars"
    call mAdd t.trans, o0 '<o0>', o1 '<o1>', o2 '<o2>'
    call vRemove 'v2'
    m.tst.adr1 = 'value eins'
    put1 = vPut('v1', oMutate(tst'.'adr1, m.class_V))
    call tstOut t, 'put v1' m.put1
    call tstOut t, 'v1 hasKey' vHasKey('v1') 'get' vGet('v1')
    call tstOut t, 'v2 hasKey' vHasKey('v2')
    if 0 then
        call tstOut t, 'v2 get'    vGet('v2')
    call vPut 'theBuf', jBuf()
    call pipe '+F' , vGet('theBuf')
    call out 'one to theBur'
    call out 'two to theBuf'
    call pipe '-'
    call pipe '+f',, vGet('theBuf')
    call pipeWriteNow
    call pipe '-'
    call tstOut t, 'v1='vGet('v1') 'o='vGet('v1')
    call vPut 'v3', 'v3WieGehts?'
    call tstOut t, 'v3='vGet('v3') 'o='vGet('v3')
    call vPut 'v4', s2o('v4WieGehts?')
    call tstOut t, 'v4='vGet('v4') 'o='vGet('v4')

    call vPut 'o0', o0
    call tstOut t, 'o o0='vGet('o0')
    call tstOut t, 's o0='vGet('o0')
    fSt0 = 'fSt0'
    fRe0 = 'fRe0'
    m.o0 = 'rexx o0-value'
    m.o0.fSt0 = 'rexx o0.fSt0'
    m.o0.fRe0 = s2o('rexx o0.fRe0')
    call tstOut t, 'o o0='vGet('o0')
    call tstOut t, 's o0='vGet('o0')
    call tstOut t, 'o0&fSt0='vGet('o0&fSt0') 'o='vGet('o0&fSt0')
    call tstOut t, 'o0&fRe0='vGet('o0&fRe0') 'o='vGet('o0&fRe0')
    call tstOut t, 'o0&='vGet('o0&>') 'o='vGet('o0&>')
    call vPut 'o0&>', 'put o0-value'
    call vPut 'o0&fSt0', 'put o0.fSt0'
    call vPut 'o0&fRe0', s2o('putO o0.fRe0')
    call tstOut t, 'o o0='vGet('o0')
    call tstOut t, 's o0='vGet('o0')
    call tstOut t, 'o0&fSt0='vGet('o0&fSt0') 'o='vGet('o0&fSt0')
    call tstOut t, 'o0&fRe0='vGet('o0&fRe0') 'o='vGet('o0&fRe0')
    call tstOut t, 'o0&='vGet('o0&>') 'o='vGet('o0&>')

    call tstEnd t
    call tst t, "tstEnvVars1"
    call mAdd t.trans, o0 '<o0>', o1 '<o1>', o2 '<o2>'

    call vPut 'o1', o1
    call vPut 'o1&>', 'put-o1-value'
    call vPut 'o1&fStr', 'put-o1.fStr'
    call vPut 'o1&fRef', vGet('o0')
    call tstOut t, 'm.o1='m.o1 'm.o1.fStr='mGet(o1'.fStr'),
         'm.o1.fRef='mGet(o1'.fRef')
    call tstOut t, 'o o1='vGet('o1') 's o1='vGet('o1')
    call tstOut t, 'o1&fStr='vGet('o1&fStr') 'o='vGet('o1&fStr')
    call tstOut t, 'o1&='vGet('o1&>') 'o='vGet('o1&>')
    call tstOut t, 'o1&fRef='vGet('o1&fRef') 'o='vGet('o1&fRef')
    call tstOut t, 'o1&fRef>fSt0='vGet('o1&fRef>fSt0') ,
        'o='vGet('o1&fRef>fSt0')
    call tstOut t, 'o1&fRef>fRe0='vGet('o1&fRef>fRe0'),
         'o='vGet('o1&fRef>fRe0')

    call vPut 'o1&fNest.fSt0', 'put-o1.fNest.fSt0'
    call vPut 'o1&fNest.fRe0', s2o('put-o1&fNest.fRe0')
    call tstOut t, 'm.o1&fNest.fSt0=' mGet(o1'.fNest.fSt0') ,
            'm.o1&fNest.fRe0=' mGet(o1'.fNest.fRe0')
    call tstOut t, 'o1&fNest.fSt0='vGet('o1&fNest.fSt0'),
         'o='vGet('o1&fNest.fSt0')
    call tstOut t, 'o1&fNest&fRe0='vGet('o1&fNest.fRe0'),
         'o='vGet('o1&fNest.fRe0')
    call tstEnd t

    call tst t, "tstEnvVars2"
    call mAdd t.trans, o0 '<o0>', o1 '<o1>', o2 '<o2>'
    call vPut 'o2', o2
    call vPut 'o2&fRef', vGet('o1')
    call tstOut t, 'o2='o2 'getO(o2)='vGet('o2'),
        'getO(o2&fRef)='vGet('o2&fRef')

    call tstOut t, 'o2&fRef>fStr='vGet('o2&fRef>fStr'),
         'o='vGet('o2&fRef>fStr')
    call tstOut t, 'o2&fRef>='vGet('o2&fRef>'),
     'o='vGet('o2&fRef>')

    call tstOut t, 'o2&fRef>fRef='vGet('o2&fRef>fRef') ,
        'o='vGet('o2&fRef>fRef')
    call tstOut t, 'o2&fRef>fRef>fSt0='vGet('o2&fRef>fRef>fSt0') ,
        'o='vGet('o2&fRef>fRef>fSt0')
    call tstOut t, 'o2&fRef>fRef>fRe0='vGet('o2&fRef>fRef>fRe0'),
         'o='vGet('o2&fRef>fRef>fRe0')
    call tstOut t, 'o2&fRef>fNest.fSt0='vGet('o2&fRef>fNest.fSt0'),
         'o='vGet('o2&fRef>fNest.fSt0')
    call tstOut t, 'o2&fRef>fNest&fRe0='vGet('o2&fRef>fNest.fRe0'),
         'o='vGet('o1&fNest.fRe0')
    call tstEnd t

    cS = classNew('n? TstEnvVarsS u f fStS v,f fStV s v, f fStR s r',
        ', f fNeS s TstEnvVars0, f = s v')
    oS = oNew(cS)
    call vPut 'oS', oS
    oT = oNew(cS)
    call tst t, "tstEnvVarsS"
    call mAdd t.trans, o0 '<o0>', o1 '<o1>', o2 '<o2>',
        , oS '<oS>', oT '<oT>'
    call mPut oS'.fStS', '<put oS.fStS>'
    call tstOut t, 'oS='vGet('oS') 'oS&fStS='vGet('oS&fStS')
    call mPut oS'.fStV.1', '<put oS.fStV.1>'
    call mPut oS'.fStV.0', 1
    call tstOut t, 'oS&fStV.0='vGet('oS&fStV.0'),
         'oS&fStV.1='vGet('oS&fStV.1')
    call mPut oS'.fStR.1', s2o('<put oS.fStR.1>')
    call mPut oS'.fStR.2', s2o('<put oS.fStR.2>')
    call mPut oS'.fStR.0', 2
    call tstOut t, 'm.oS.fStR.0='mGet(oS'.fStR.0'),
     '.2='mGet(oS'.fStR.2')
    call tstOut t, 'oS&fStR.0='vGet('oS&fStR.0'),
         '.1='vGet('oS&fStR.1') '.2='vGet('oS&fStR.2')
    call mPut oS'.1234', '<put oS.1234>'
    call mPut oS'.0', 9876
    call mPut oS'.fStR.0', 2
    call tstOut t, 'm.oS.0='mGet(oS'.0'),
     '.1234='mGet(oS'.1234')
    call tstOut t, 'oS&0='vGet('oS&0'),
         '.12='vGet('oS&12') '.1234='vGet('oS&1234')
    call tstEnd t
    return
endProcedure tstEnvVars
tstEnvVarsMG: procedure expose m.
parse arg m, g
     call tstOut t, 'm.'m'='m.m 'vGet('g')='vGet(g)
     return

tstvWith: procedure expose m.
/*
$=/tstEW2/
    ### start tst tstEW2 ##############################################
    tstK1             TSTEW1
    tstK1&            ]get1 w
    tstK1&f1          get1.f1 v
    tstK1&f2          ]get1.f2 w
    tstK1&F3          get1.f3 v
    ttstK1&F3.FEINS   get1.f3.fEins v
    tstK1&F3.FZWEI    ]get1.f3.fZwei w
    tstK1&F3.FDREI o  ]get1.f3.fDrei w
    tstK1&F3.FDREI    ]get1.f3.fDrei w
    tstK1&F3.1        ]get1.f3.1 w
    tstK1&F3.2        TSTEW1
    tstK1&F3.2>F1     get1.f1 v
    tstK1&F3.2>F3.2>F2 ]get1.f2 w
    *** err: undefined var F1
    F1          M..
    F1          get1.f1 v
    f2          ]get1.f2 w
    F3          get1.f3 v
    F3.FEINS    get1.f3.fEins v
    F3.FZWEI    ]get1.f3.fZwei w
    F3.FDREI o  ]get1.f3.fDrei w
    F3.1        ]get1.f3.1 w
    pu1 F1      get1.f1 v
    pu2 F1      get2.f1 v
    po-2 F1     get1.f1 v
    *** err: undefined var F1
    po-1 F1     M..
$/tstEW2/  */
    call pipeIni
    c0 = classNew('n? TstEW0 u f FEINS v,f FZWEI w, f FDREI r,v,s r')
    call classMet c0, 'oFlds' /* new would do it, but we donot use it*/
    cl = classNew('n? TstEW u r TstEW0, f F1 v, f F2 r, f F3 TstEW0')
    call classMet cl, 'oFlds' /* new would do it, but we donot use it*/
    call oMutate tstEW1, cl
    m.tstEW1    = s2o('get1 w')
    m.tstEW1.f1 = 'get1.f1 v'
    m.tstEW1.f2 = s2o('get1.f2 w')
    m.tstEW1.f3 = 'get1.f3 v'
    m.tstEW1.f3.fEins = 'get1.f3.fEins v'
    m.tstEW1.f3.fZwei = s2o('get1.f3.fZwei w')
    m.tstEW1.f3.fDrei = s2o('get1.f3.fDrei w')
    m.tstEW1.f3.0 = 3
    m.tstEW1.f3.1 = s2o('get1.f3.1 w')
    m.tstEW1.f3.2 = tstEW1
    m.tstEW1.f3.3 = s2o('get1.f3.3 w')
    call oMutate tstEW2, cl
    m.tstEW2    = s2o('get2 w')
    m.tstEW2.f1 = 'get2.f1 v'
    m.tstEW2.f2 = s2o('get2.f2 w')
    call vPut 'tstK1', tstEW1

    call tst t, 'tstEW2'
    call tstOut t, 'tstK1            ' vGet('tstK1')
    call tstOut t, 'tstK1&           ' vGet('tstK1&>')
    call tstOut t, 'tstK1&f1         ' vGet('tstK1&F1')
    call tstOut t, 'tstK1&f2         ' vGet('tstK1&F2')
    call tstOut t, 'tstK1&F3         ' vGet('tstK1&F3')
    call tstOut t, 'ttstK1&F3.FEINS  ' vGet('tstK1&F3.FEINS')
    call tstOut t, 'tstK1&F3.FZWEI   ' vGet('tstK1&F3.FZWEI')
    call tstOut t, 'tstK1&F3.FDREI o ' vGet('tstK1&F3.FDREI')
    call tstOut t, 'tstK1&F3.FDREI   ' vGet('tstK1&F3.FDREI')
    call tstOut t, 'tstK1&F3.1       ' vGet('tstK1&F3.1')
    call tstOut t, 'tstK1&F3.2       ' vGet('tstK1&F3.2')
    call tstOut t, 'tstK1&F3.2>F1    ' vGet('tstK1&F3.2>F1')
    call tstOut t, 'tstK1&F3.2>F3.2>F2' ,
                                vGet('tstK1&F3.2>F3.2>F2')
    call tstOut t, 'F1         ' vGet('F1')
    call vWith '+', tstEW1
    call tstOut t, 'F1         ' vGet('F1')
    call tstOut t, 'f2         ' vGet('F2')
    call tstOut t, 'F3         ' vGet('F3')
    call tstOut t, 'F3.FEINS   ' vGet('F3.FEINS')
    call tstOut t, 'F3.FZWEI   ' vGet('F3.FZWEI')
    call tstOut t, 'F3.FDREI o ' vGet('F3.FDREI')
    call tstOut t, 'F3.1       ' vGet('F3.1')
    call tstOut t, 'pu1 F1     ' vGet('F1')
    call vWith '+', tstEW2
    call tstOut t, 'pu2 F1     ' vGet('F1')
    call vWith '-'
    call tstOut t, 'po-2 F1    ' vGet('F1')

    call vWith '-'
    call tstOut t, 'po-1 F1    ' vGet('F1')
    call tstEnd t
/*
$=/tstEW3/
    ### start tst tstEW3 ##############################################
    .          s c3&F1          = v(c3&f1)
    *** err: null address at &FEINS in c3&F1&FEINS
    *** err: undefined var c3&F1&FEINS
    .          s c3&F1&FEINS    = M..
    *** err: null address at &FEINS in c3&F3&FEINS
    *** err: null address at &FEINS in c3&F3&FEINS
    *** err: undefined var c3&F3&FEINS
    .          s c3&F3&FEINS    = M..
    .          s c3&F3.FEINS    = val(c3&F3.FEINS)
    *** err: undefined var c3&FEINS
    .          s c3&FEINS       = M..
    getO c3&
    aft Put   s c3&>FEINS      = v&&fEins
    Push c3   s F3.FEINS       = val(c3&F3.FEINS)
    aftPut=   s F3.FEINS       = pushPut(F3.FEINS)
    push c4   s F1             = v(c4&f1)
    put f2    s F2             = put(f2)
    put ..    s F3.FEINS       = put(f3.fEins)
    popW c4   s F1             = v(c3&f1)
    *** err: undefined var F1
    popW c3   s F1             = M..
    .          s F222           = f222 pop stop
$/tstEW3/
*/
    call tst t, 'tstEW3'
    c3 = oNew('TstEW')
    call mAdd t.trans, c3 '<c3>'
    m.c3.f1 = 'v(c3&f1)'
    call vPut 'c3', c3
    call tstEnvSG , 'c3&F1'
    call tstEnvSG , 'c3&F1&FEINS'
    call tstEnvSG , 'c3&F3&FEINS'
    call vPut 'c3&F3.FEINS', 'val(c3&F3.FEINS)'
    call tstEnvSG , 'c3&F3.FEINS'
    call tstEnvSG , 'c3&FEINS'
    call tstOut t,  'getO c3&', vGet('c3&')
    call vPut 'c3&>', oNew('TstEW0')
    call vPut 'c3&>FEINS', 'v&&fEins'
    call tstEnvSG 'aft Put', 'c3&>FEINS'
    call vWith '+', c3
    call tstEnvSG 'Push c3', 'F3.FEINS'
    call vPut 'F3.FEINS', 'pushPut(F3.FEINS)'
    call tstEnvSG 'aftPut=', 'F3.FEINS'

    c4 = oNew('TstEW')
    call mAdd t.trans, c4 '<c4>'
    m.c4.f1 = 'v(c4&f1)'
    call vPut f222, 'f222 no stop'
    call vWith '+',  c4
    call tstEnvSG 'push c4', f1
    call vPut f2, 'put(f2)'
    call tstEnvSG 'put f2', f2
    call vPut f222, 'f222 stopped', 1
    call vPut 'F3.FEINS', 'put(f3.fEins)'
    call tstEnvSG 'put .. ', 'F3.FEINS'
    call vWith '-'
    call tstEnvSG 'popW c4', f1
    call vWith '-'
    call vPut f222, 'f222 pop stop'
    call tstEnvSG 'popW c3', f1
    call tstEnvSG          , f222
    call tstEnd t
    return
endProcedure tstvWith

tstEnvSG: procedure expose m. t
parse arg txt, nm
    call tstOut t, left(txt,10)'s' left(nm, 15)'=' vGet(nm)
    return

tstPipeLazy: procedure expose m.
    call pipeIni
/*
$=/tstPipeLazy/
    ### start tst tstPipeLazy #########################################
    a1 vor pipeBegin loop lazy 0 writeNow *** <class TstPipeLazyBuf>
    bufOpen <
    bufClose
    #jIn 2# tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    #jIn eof 4#
    a5 vor 2 writeNow in inIx 4
    a2 vor writeNow jBuf
    jBuf line 1
    jBuf line 2
    a3 vor writeNow in inIx 1
    tst in line 2 zwei ;   .
    tst in line 3 drei .schluss..
    a4 vor barLast inIx 4
    a6 vor barEnd inIx 4
    a7 nach barEnd lazy 0 writeNow ***
    b1 vor barBegin lazy 0 writeNow *** <class TstPipeLazyRdr>
    RdrOpen <
    #jIn 3# tst in line 3 drei .schluss..
    #jIn eof 4#
    rdrClose
    b4 vor writeNow
    b2 vor writeNow rdr inIx 2
    jRead lazyRdr
    tst in line 3 drei .schluss..
    jRead lazyRdr
    b3 vor barLast inIx 4
    b5 vor barEnd inIx 4
    b6 nach barEnd lazy 0 writeNow ***
    a1 vor pipeBegin loop lazy 1 writeAll *** +
        .<class TstPipeLazyBuf>
    a5 vor 2 writeAll in inIx 0
    a2 vor writeAll jBuf
    bufOpen <
    jBuf line 1
    jBuf line 2
    bufClose
    a3 vor writeAll in inIx 0
    #jIn 1# tst in line 1 eins ,
    tst in line 1 eins ,
    #jIn 2# tst in line 2 zwei ;   .
    tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    tst in line 3 drei .schluss..
    #jIn eof 4#
    a4 vor barLast inIx 0
    a6 vor barEnd inIx 4
    a7 nach barEnd lazy 1 writeAll ***
    b1 vor barBegin lazy 1 writeAll *** <class TstPipeLazyRdr>
    b4 vor writeAll
    b2 vor writeAll rdr inIx 1
    RdrOpen <
    jRead lazyRdr
    #jIn 2# tst in line 2 zwei ;   .
    tst in line 2 zwei ;   .
    jRead lazyRdr
    #jIn 3# tst in line 3 drei .schluss..
    tst in line 3 drei .schluss..
    jRead lazyRdr
    #jIn eof 4#
    rdrClose
    b3 vor barLast inIx 1
    b5 vor barEnd inIx 4
    b6 nach barEnd lazy 1 writeAll ***
$/tstPipeLazy/ */
    call tst t, "tstPipeLazy"
    do lz=0 to 1
        if lz then
            w = 'writeAll'
        else
            w = 'writeNow'
        m.t.inIx = 1-lz
        ty = classNew('n? TstPipeLazyBuf u JRWDeleg', 'm',
            , 'jOpen call tstOut "T", "bufOpen" opt;',
              'call jOpen m.m.deleg, opt',
            , 'jClose call tstOut "T", "bufClose";',
              'call jClose m.m.deleg')
        if \ lz then
             call mAdd t'.TRANS', ty '<class TstPipeLazyBuf>'
        call out 'a1 vor pipeBegin loop lazy' lz w '***' ty
        call pipe '+N'
        call out 'a2 vor' w 'jBuf'
        b = oNew('TstPipeLazyBuf', jBuf('jBuf line 1','jBuf line 2'))
        interpret 'call pipe'w 'b'
        call out 'a3 vor' w 'in inIx' m.t.inIx
        interpret 'call pipe'w
        call out 'a4 vor barLast inIx' m.t.inIx
        call pipe 'P|'
        call out 'a5 vor 2' w 'in inIx' m.t.inIx
        interpret 'call pipe'w
        call out 'a6 vor barEnd inIx' m.t.inIx
        call pipe '-'
        call out 'a7 nach barEnd lazy' lz w '***'

        ty = classNew('n? TstPipeLazyRdr u JRW', 'm',
            , 'jOpen call tstOut "T", "RdrOpen" opt',
            , 'jRead call out "jRead lazyRdr"; mr = m.m.rdr;' ,
                        'm.rStem.0 = jRead(mr); m.rStem.1 = m.mr',
            , 'jClose call tstOut "T",  "rdrClose";')
        if \ lz then
             call mAdd t'.TRANS', ty '<class TstPipeLazyRdr>'

        r = oNew('TstPipeLazyRdr')
        m.r.rdr = m.j.in
        if lz then
            call mAdd t'.TRANS', r '<lazyRdr>'
     m.t.inIx = 2-lz
     call out 'b1 vor barBegin lazy' lz w '***' ty
     call pipe '+N'
     call out 'b2 vor' w 'rdr inIx' m.t.inIx
     interpret 'call pipe'w 'r'
     call out 'b3 vor barLast inIx' m.t.inIx
     call pipe 'P|'
        call out 'b4 vor' w
        interpret 'call pipe'w
        call out 'b5 vor barEnd inIx' m.t.inIx
        call pipe '-'
     call out 'b6 nach barEnd lazy' lz w '***'
        end
    call tstEnd t
    return
endProcedure tstPipeLazy

tstEnvClass: procedure expose m.
    call pipeIni
/*
$=/tstEnvClass/
    ### start tst tstEnvClass #########################################
    a0 vor pipeBegin loop lazy 0 writeNow *** TY
    #jIn 2# tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    #jIn eof 4#
    a5 vor writeNow
    a1 vor jBuf()
    a2 vor writeNow b
    tstR: @<o20 of TstEnvClass10> isA :TstEnvClass10
    tstR:  .f11 = .
    tstR:  .F12 = value F12 of o1 <o20 of TstEnvClass10>
    tstR:  .f13 = .
    WriteO o2
    tstR: @<oc0 of TstEnvClass20> isA :TstEnvClass20 = valueO2Lazy0
    tstR:  .f24 = .
    tstR:  .F25 = value F25 of o20 <o20 of TstEnvClass20>
    a3 vor writeNow
    tst in line 2 zwei ;   .
    tst in line 3 drei .schluss..
    a4 vor barLast inIx 4
    a6 vor barEnd
    a7 nach barEnd lazy 0 writeNow ***
    a0 vor pipeBegin loop lazy 1 writeAll *** TY
    a5 vor writeAll
    a1 vor jBuf()
    a2 vor writeAll b
    tstR: @<o21 of TstEnvClass10> isA :TstEnvClass10
    tstR:  .f11 = .
    tstR:  .F12 = value F12 of o1 <o21 of TstEnvClass10>
    tstR:  .f13 = .
    WriteO o2
    tstR: @<oc1 of TstEnvClass20> isA :TstEnvClass20 = valueO2Lazy1
    tstR:  .f24 = .
    tstR:  .F25 = value F25 of o21 <o21 of TstEnvClass20>
    a3 vor writeAll
    #jIn 1# tst in line 1 eins ,
    tst in line 1 eins ,
    #jIn 2# tst in line 2 zwei ;   .
    tst in line 2 zwei ;   .
    #jIn 3# tst in line 3 drei .schluss..
    tst in line 3 drei .schluss..
    #jIn eof 4#
    a4 vor barLast inIx 0
    a6 vor barEnd
    a7 nach barEnd lazy 1 writeAll ***
$/tstEnvClass/ */

    call tst t, "tstEnvClass"
    t10 = classNew('n? TstEnvClass10 u f f11 v, f F12 v, f f13 v')
    t20 = classNew('n? TstEnvClass20 u v, f f24 v, f F25 v')
    do lz=0 to 1
        if lz then
            w = 'writeAll'
        else
            w = 'writeNow'
        m.t.inIx = 1-lz
        call out 'a0 vor pipeBegin loop lazy' lz w '***' ty
        call pipe '+N'
        call out 'a1 vor jBuf()'
        b = jOpen(jBuf(), m.j.cWri)
        o1 = oNew('TstEnvClass10')
        m.o1.F12 = 'value F12 of o1' o1
        call mAdd t'.TRANS', o1 '<o2'lz 'of TstEnvClass10>'
        call jWrite b, o1
        call jWrite b, 'WriteO o2'
        o2 = oNew('TstEnvClass20')
        m.o2 = 'valueO2Lazy'lz
        m.o2.F25 = 'value F25 of o2'lz o2
        oc = oCopy(oCopy(o2))
        call mAdd t'.TRANS', o2 '<o2'lz 'of TstEnvClass20>'
        call mAdd t'.TRANS', oc '<oc'lz 'of TstEnvClass20>'
        call jWrite b, oc
        call out 'a2 vor' w 'b'
        interpret 'call pipe'w jClose(b)
        call out 'a3 vor' w
        interpret 'call pipe'w
        call out 'a4 vor barLast inIx' m.t.inIx
        call pipe 'P|'
        call out 'a5 vor' w
        interpret 'call pipe'w
        call out 'a6 vor barEnd'
        call pipe '-'
        call out 'a7 nach barEnd lazy' lz w '***'
        end
    call tstEnd t
    m.t.trans.0 = 0
    return
endProcedure tstEnvClass

tstDsn: procedure expose m.
/*
$=/tstDsn/
   ### start tst tstDsn ##############################################
    aa has 4 members: created
    - aa(DREI) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    - aa(EINS) 1 lines, aa(eins) 1/1
    - aa(NULL) 0 lines
    - aa(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    bb has 1 members: copy eins, eins1
    - bb(EINS1) 1 lines, aa(eins) 1/1
$/tstDsn/
$=/tstDsnL/
   ### start tst tstDsnL #############################################
    bb has 2 members: copy zwei
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    cc has 1 members: copy drei cc new
    - cc(DREI) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    bb has 5 members: copy
    - bb(DREI) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    - bb(EINS) 1 lines, aa(eins) 1/1
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(NULL) 0 lines
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    bb has 8 members: copy null eins drei >*4
    - bb(DREI) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    - bb(DREI4) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    - bb(EINS) 1 lines, aa(eins) 1/1
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(EINS4) 1 lines, aa(eins) 1/1
    - bb(NULL) 0 lines
    - bb(NULL4) 0 lines
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    bb has 7 members: delete null4
    - bb(DREI) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    - bb(DREI4) 3 lines, aa(drei) 1/3, aa(drei) 2/3, aa(drei) 3/3
    - bb(EINS) 1 lines, aa(eins) 1/1
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(EINS4) 1 lines, aa(eins) 1/1
    - bb(NULL) 0 lines
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    bb has 3 members: delete eins4 drei4 eins drei
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(NULL) 0 lines
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    bb has 3 members: delete drei4
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(NULL) 0 lines
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    before seqFuenf 5 lines, seqFuenf 1/5, seqFuenf 2/5, seqFue+
    nf 3/5, seqFuenf 4/5, seqFuenf 5/5
    copy zwei seqFuenf 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    copy null seqFuenf 0 lines
    before seqVier 4 lines, seqVier 1/4, seqVier 2/4, seqVier +
    3/4, seqVier 4/4
    bb has 4 members: copy .seqVier
    - bb(EINS1) 1 lines, aa(eins) 1/1
    - bb(FROVIER) 4 lines, seqVier 1/4, seqVier 2/4, seqVier +
    3/4, seqVier 4/4
    - bb(NULL) 0 lines
    - bb(ZWEI) 2 lines, aa(zwei) 1/2, aa(zwei) 2/2
    delete seqFuenf does not exist
    delete seqFuenf does not exist
$/tstDsnL/
*/
    do sx=0 to m.tst_csmRZ \== ''
        sys = copies(m.tst_csmRz'/', sx)
        say 'csm/sys='sys '+++++++++++++++++++++++++++'
        call tst t, 'tstDsn'
        pr = tstFileName(sys'tstDsn', 'r')
        call tstDsnWr pr'.aa(null) ::f', 0
        call tstDsnWr pr'.aa(eins)', 1
        call tstDsnWr pr'.aa(zwei)', 2
        call tstDsnWr pr'.aa(drei)', 3
        call tstDsnWr pr'.seqVier ::f', 4
        call tstDsnWr pr'.seqFuenf ::f', 5
        call tstDsnRL t, pr'.aa', 'created'
        call dsnCopy pr'.aa(eins)', pr'.bb(eins1)'
        call tstDsnRL t, pr'.bb', 'copy eins, eins1'
        call tstEnd t
        if sx & \ m.tst_long then
            iterate
        call tst t, 'tstDsnL'
        call dsnCopy pr'.aa(zwei)', pr'.bb'
        call tstDsnRL t, pr'.bb', 'copy zwei'
        call dsnCopy pr'.aa(drei)', pr'.cc'
        call tstDsnRL t, pr'.cc', 'copy drei cc new'
        call dsnCopy pr'.aa(*', pr'.bb'
        call tstDsnRL t, pr'.bb', 'copy'
        call dsnCopy pr'.aa', pr'.bb', 'null>null4 eins>eins4' ,
                                       'drei>drei4'
        call tstDsnRL t, pr'.bb', 'copy null eins drei >*4'
        call dsnDel pr'.bb(null4)'
        call tstDsnRL t, pr'.bb', 'delete null4'
        call dsnDel pr'.bb(eins)'
        call dsnDel pr'.bb(eins4)'
        call dsnDel pr'.bb', 'drei drei4'
        call tstDsnRL t, pr'.bb', 'delete eins4 drei4 eins drei'
        call dsnDel pr'.bb(drei4)'
        call tstDsnRL t, pr'.bb', 'delete drei4'
        call tstOut t, 'before' tstDsnr1(pr'.seqFuenf')
        call dsnCopy pr'.aa(zwei)', pr'.seqFuenf'
        call tstOut t, 'copy zwei' tstDsnr1(pr'.seqFuenf')
        call dsnCopy pr'.aa(null)', pr'.seqFuenf'
        call tstOut t, 'copy null' tstDsnr1(pr'.seqFuenf')
        call tstOut t, 'before' tstDsnr1(pr'.seqVier')
        call dsnCopy pr'.seqVier', pr'.bb(froVier)'
        call tstDsnRL t, pr'.bb', 'copy .seqVier'
        call dsnDel pr'.seqFuenf'
        call tstOut t, 'delete' tstDsnr1(pr'.seqFuenf')
        call dsnDel pr'.seqFuenf'
        call tstOut t, 'delete' tstDsnr1(pr'.seqFuenf')
              /* delete all to avoid mixup in next loop */
        pr = tstFileName(sys'tstDsn', 'r')
        call tstEnd t
        end
    return
endProcedure tstDsn

tstDsnWr: procedure expose m.
parse arg dsn suf, li
     q = strip(substr(dsn, lastPos('.', dsn) + 1))
     do ox=1 to li
         o.ox = q ox'/'li
         end
     call writeDsn dsn suf, o., li, 1
     return
endProcedure tstDsnWr

tstDsnR1: procedure expose m.
parse arg dsn
     q = strip(substr(dsn, lastPos('.', dsn) + 1))
     if \ dsnExists(dsn) then
          return q 'does not exist'
     call readDsn dsn, i.
     r = q i.0 'lines'
     do ix=1 to i.0
         r = r',' strip(i.ix)
             end
     return r
endProcedure tstDsnR1

tstDsnRL: procedure expose m.
parse arg t, dsn, msg
     q = strip(substr(dsn, lastPos('.', dsn) + 1))
     call mbrList tst_dsnL, dsn
     call tstOut t, q 'has' m.tst_dsnL.0 'members:' msg
     do mx=1 to m.tst_dsnL.0
         call tstOut t, '-' tstDsnR1(dsn'('m.tst_dsnL.mx')')
         end
     return
endProcedure tstDsnRL


tstDsn2: procedure expose m.
/*
$=/tstDsnEq/
    ### start tst tstDsnEq ############################################
    seq= TSTDSNS 1 lines, TSTDSNS 1/1
    p2s= TSTDSNS 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    TSTDSNP has 1 members: par=
    - TSTDSNP(ZWEI) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    TSTDSNP has 4 members: s>*=
    - TSTDSNP(DREI) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    - TSTDSNP(EINS) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    - TSTDSNP(SEQ) 1 lines, TSTDSNS 1/1
    - TSTDSNP(ZWEI) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
$/tstDsnEq/
$=/tstDsnLng/
    ### start tst tstDsnLng ###########################################
    seq= TSTDSNS 1 lines, TSTDSNS 1/1
    p2s= TSTDSNS 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    TSTDSNP has 1 members: par=
    - TSTDSNP(ZWEI) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    TSTDSNP has 4 members: s>*=
    - TSTDSNP(DREI) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    - TSTDSNP(EINS) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
    - TSTDSNP(SEQ) 1 lines, TSTDSNS 1/1
    - TSTDSNP(ZWEI) 2 lines, TSTDSNP(eins) 1/2, TSTDSNP(eins) 2/2
$/tstDsnLng/
$=/tstDsnSht/
    ### start tst tstDsnSht ###########################################
    seq= TSTDSNS 1 lines, TSTDSNS 1/
    p2s= TSTDSNS 2 lines, TSTDSNP(ei, TSTDSNP(ei
    TSTDSNP has 1 members: par=
    - TSTDSNP(ZWEI) 2 lines, TSTDSNP(ei, TSTDSNP(ei
    TSTDSNP has 4 members: s>*=
    - TSTDSNP(DREI) 2 lines, TSTDSNP(ei, TSTDSNP(ei
    - TSTDSNP(EINS) 2 lines, TSTDSNP(ei, TSTDSNP(ei
    - TSTDSNP(SEQ) 1 lines, TSTDSNS 1/
    - TSTDSNP(ZWEI) 2 lines, TSTDSNP(ei, TSTDSNP(ei
$/tstDsnSht/
*/
    call tstIni
    tCnt = 0
    cRZ = (m.tst_csmRZ \== '') * 3
    if m.tst_long then
        cSel = ''
    else do /* one with iebCopy one with copyW */
        cSel = random(0, 10*(cRz+1) - 1)
        cSel = cSel + cSel % 5 + 2 random(0, 2*(cRz+1) - 1) * 6 + 1
        say 'tstDsn2 selects' cSel
        end
    do sx=0 to cRz
        sFr = copies(m.tst_csmRz'/', sx >= 2)
        sTo = copies(m.tst_csmRz'/', sx // 2)
        do fx=1 to 2
            ff = substr('FV', fx, 1)
            fWr = 1
            do ty=1 to 2
                tx = 1 + (fx <> ty)
                tA = word('::F50 ::V54', tx)
                tf = substr(tA, 3, 1)
                tA = copies(tA, ff <> tf)
                do lx=1 to 3 /* 1 + 2 * (ff = tf) */
                    tCnt = tCnt + 1
                    if wordPos(tCnt, cSel) < 1 & cSel <> '' then
                        iterate
                    if lx = 1 then do
                        tq = 'Eq'
                        end
                    else if lx = 2 then do
                        tq = 'Lng'
                        tA = '::'tf'60'
                        end
                    else do
                        tq = 'Sht'
                        tA = '::'tf || if(tf=='F', 10, 14)
                        end
                    if fWr then do
                        fWr = 0
                        fS = tstFileName(sFr'fr'ff'.tstDsnS', 'r')
                        fP = tstFileName(sFr'fr'ff'.tstDsnP', 'r')
                        call tstDsnWr fS '::'ff'50', 1
                        call tstDsnWr fP'(eins) ::'ff'50', 2
                        end
                    call tst t, 'tstDsn'tq
                    say '>>>>> csm/sys from' sFr ff 'to' sTo tf tq tA ,
                        '<<<<<' tCnt 'ff=tf' (ff=tf)
                    tS = tstFileName(sTo || tq || tf'.tstDsnS', 'r')
                    tP = tstFileName(sTo || tq || tf'.tstDsnP', 'r')
                    call dsnCopy fS, tS tA
                    call tstOut t, 'seq=' tstDsnR1(tS)
                    call dsnCopy '-' fP'(eins)', tS tA
                    call tstOut t, 'p2s=' tstDsnR1(tS)
                    call dsnCopy fP'(eins)', tP'(zwei)' tA
                    call tstDsnRL t, tP, 'par='
                    call dsnCopy fS, tP'(seq)' tA
                    call dsnCopy fP, tP tA, 'eins>drei'
                    call dsnCopy fP, tP tA
                    call tstDsnRL t, tP, 's>*='
                    call tstEnd t
                    end
                end
            end
        end
    return
endProcedure tstDsn2

tstDsnEx: procedure expose m.
/*
$=/tstDsnEx/
    ### start tst tstDsnEx ############################################
    dsnExists(A540769.WK.rexx) 1
    dsnExists(RZZ/A540769.WK.rexx) 1
    dsnExists(A540769.WK.wk.rexxYY) 0
    dsnExists(RZZ/A540769.WK.wk.rexxYY) 0
    dsnExists(A540769.WK.rexx(wsh)) 1
    dsnExists(RZZ/A540769.WK.rexx(wsh)) 1
    dsnExists(A540769.WK.rexx(nonono)) 0
    dsnExists(RZZ/A540769.WK.rexx(nonono)) 0
    dsnExists(A540769.WK.rxxYY(nonon)) 0
    dsnExists(RZZ/A540769.WK.rxxYY(nonon)) 0
    *** err: csm rc=8 .
    .    e 1: stmt=csmExec allocate SYSTEM(?QZ) DDNAME(MBRLISDD) DATASE+
    T('A540769.WK.RXXYY') DISP(SHR)  timeout(30) .
    .    e 2: CSMSI77E INVALID SYSTEM NAME (MUST BE * OR A VALID NAME) +
    (COL:8)
    .    e 3: CSMSI77E SYSTEM=?QZ,TIMEOUT=30 .
    %%%
    dsnExists(?qZ/A540769.WK.rxxYY(nonon)) 0
$/tstDsnEx/
*/
    call tst t, 'tstDsnEx'
    lst = 'rexx wk.rexxYY rexx(wsh) rexx(nonono) rxxYY(nonon)'
    rz = m.tst_csmRZ
    do lx =1 to words(lst)
         d1 = 'A540769.WK.'word(lst,lx)
         call tstOut t, 'dsnExists('d1')' dsnExists(d1)
         call tstOut t, 'dsnExists('rz'/'d1')' dsnExists(rz'/'d1)
         end
    call mAdd t'.TRANS', '00'x '?', '0A'x '?'
    call tstOut t, 'dsnExists(?qZ/'d1')' dsnExists('?qz/'d1)
    call tstEnd t
    return
endProceudre tstDsnEx

tstFile: procedure expose m.
    call catIni
/*
$=/tstFile/
    ### start tst tstFile #############################################
    write read 0 last 10 vor anfang
    write read 1 last 80  links1 1   und rechts |  ..
    write read 2 last 80 liinks2 2   und rechts |  ..
    write read 5 last 80 links5 5 rechts5
    write read 99 last 80 links99 99 rechts
    write read 100 last 80 links100 100 rechts
    write read 101 last 80 links101 101 rechts
    write read 999 last 80 links999 999 rechts
    write read 1000 last 80 links1000 1000 rechts
    write read 1001 last 80 links1001 1001 rechts
    write read 2109 last 80 links2109 2109 rechts
    out > eins 1                                                       +
    .             .
    out > eins 2 schluss.                                              +
    .             .
    buf eins
    buf zwei
    buf drei
    out > zwei mit einer einzigen Zeile                                +
    .             .
    . links1 1   und rechts |  .                                       +
    .              .
$/tstFile/ */
    call tst t, "tstFile"
    pds = tstFilename('lib', 'r')
    call tstFileWr pds, 0, ' links0', '  und rechts |  .  '
    call tstFileWr pds, 1, ' links1', '  und rechts |  .  '
    call tstFileWr pds, 2, 'liinks2', '  und rechts |  .  '
    call tstFileWr pds, 5, 'links5', 'rechts5'
    call tstFileWr pds, 99, 'links99', 'rechts'
    call tstFileWr pds, 100, 'links100', 'rechts'
    call tstFileWr pds, 101, 'links101', 'rechts'
    call tstFileWr pds, 999, 'links999', 'rechts'
    call tstFileWr pds, 1000, 'links1000', 'rechts'
    call tstFileWr pds, 1001, 'links1001', 'rechts'
    call tstFileWr pds, 2109, 'links2109', 'rechts'
    pd2 = tstFilename('li2', 'r')
    call pipeIni
    call pipe '+F', s2o(tstPdsMbr(pd2, 'eins'))
    call out tstFB('out > eins 1') /* simulate fixBlock on linux */
    call out tstFB('out > eins 2 schluss.')
    call pipe '-'
    call pipe '+F', s2o(tstPdsMbr(pd2, 'zwei'))
    call out tstFB('out > zwei mit einer einzigen Zeile')
    call pipe '-'
    b = jBuf("buf eins", "buf zwei", "buf drei")
    call pipe '+ffffff', , s2o(tstPdsMbr(pd2, 'eins')), b,
                    ,jBuf(),
                    ,s2o(tstPdsMbr(pd2, 'zwei')),
                    ,s2o(tstPdsMbr(pds, 'wr0')),
                    ,s2o(tstPdsMbr(pds, 'wr1'))
    call pipeWriteNow
    call pipe '-'
    call tstEnd t
    return
endProcedure tstFile

/*--- simulate fixBlock 80 on linux ---------------------------------*/
tstFB: procedure expose m.
parse arg line, recL
    if m.err_os \== 'LINUX' then
        return line
    else if recL == '' then
        return left(line, 80)
    else
        return left(line, recL)
endProcedure tstFB

tstPdsMbr: procedure expose m.
parse arg pds, mbr
    if m.err_os = 'TSO' then
        return pds'('mbr') ::F'
    if m.err_os = 'LINUX' then
        return pds'.'mbr
    call err 'tstPdsMbr implement os' m.err_os
endProcedure tstPdsMbr

tstFileWR: procedure expose m.
parse arg dsn, num, le, ri
    io = file(tstPdsMbr(dsn, 'wr'num))
    call jOpen io, m.j.cWri
    do x = 1 to num /* simulate fixBlock 80 on LINUX*/
        call jWrite io, tstFB(le x ri)
        end
    call jClose io
    if num > 100 then
        call jReset io, tstPdsMbr(dsn, 'wr'num)

    call jOpen io, m.j.cRead
    m.io = 'vor anfang'
    do x = 1 to num
        if \ jRead(io) then
            call err x 'not jRead'
        else if m.io <> le x ri then
            call err x 'read mismatch' m.io
        end
    if jRead(io) then
        call err x 'jRead but should be eof 1'
    if jRead(io) then
        call err x'+1 jjRead but should be eof 2'
    call jClose io
    call tstOut t, 'write read' num 'last' length(m.io) strip(m.io,'t')
    return
endProcedure tstFileWr

tstFileList: procedure expose m.
    call catIni
/*
$=/tstFileList/
    ### start tst tstFileList #########################################
    empty dir
    filled dir
    <<pref 2 List>>eins
    <<pref 2 List>>zwei
    <<pref 2 List>>drei
    <<pref 2 List>>vier
    filled dir recursive
    <<pref 2 List>>eins
    <<pref 2 List>>zwei
    <<pref 2 List>>drei
    <<pref 2 List>>vier
    <<pref 1 vier>>eins
    <<pref 1 vier>>zwei
    <<pref 1 vier>>drei
$/tstFileList/ */
/*
$=/tstFileListTSO/
    ### start tst tstFileListTSO ######################################
    empty dir dsnList 0
    empty dir fileList
    filled dir .* dsnList 3
    <<pref 2 LIST>>DREI
    <<pref 2 LIST>>EINS
    <<pref 2 LIST>>ZWEI
    filled dir fileList
    <<pref 2 LIST>>DREI
    <<pref 2 LIST>>EINS
    <<pref 2 LIST>>ZWEI
    filled dir dsnList 6
    <<pref 2 LIST>>DREI
    <<pref 2 LIST>>EINS
    <<pref 1 VIER>>DREI
    <<pref 1 VIER>>EINS
    <<pref 1 VIER>>ZWEI
    <<pref 2 LIST>>ZWEI
    filled dir fileList recursive
    <<pref 2 LIST>>DREI
    <<pref 2 LIST>>EINS
    <<pref 1 VIER>>DREI
    <<pref 1 VIER>>EINS
    <<pref 1 VIER>>ZWEI
    <<pref 2 LIST>>ZWEI
$/tstFileListTSO/ */
    if m.err_os = 'TSO' then
        call tst t, "tstFileListTSO"
    else
        call tst t, "tstFileList"
    fi = file(tstFileName('FileList', 'r'))
    call fileMkDir fi
    fl = fileList(fi)
    call tstFileListDsn t, filePath(fi), 'empty dir'
    call tstOut t, 'empty dir fileList'
    call jWriteNow t, fl
    call tstFileListMake t, fi, 2
    call tstFileListDsn t, filePath(fi)'.*', 'filled dir .*'
    call tstOut t, 'filled dir fileList'
    call jWriteNow t, fl
    call tstFileListDsn t, filePath(fi), 'filled dir'
    call tstOut t, 'filled dir fileList recursive'
    call jWriteNow t, fileList(fi, 'r')
    call tstEnd t
    return
endProcedure tstFileList

tstFileListDsn: procedure expose m.
parse arg t, fi, msg
     call tstOut t, msg 'dsnList' dsnList(tst_FileListDsn, fi)
     do ox=1 to m.tst_FileListDsn.0
         call tstOut t, m.tst_FileListDsn.ox
         end
     return
endProcedure tstFileListDsn

tstFileListMake: procedure expose m.
parse arg t, fi, lev
    if \ fileIsDir(fi) then
        call fileMkDir fi
    call mAdd t'.TRANS', filePath(fi) || m.file.sep ,
                '<<pref' lev right(filePath(fi),4)'>>'
    call jCat fileChild(fi, 'eins','::F'),jBuf('zeile eins','eins' lev)
    call jCat fileChild(fi, 'zwei','::F'),jBuf('zeile zwei','zwei' lev)
    call jCat fileChild(fi, 'drei','::F'),jBuf('zeile drei','drei' lev)
    if lev > 1 then
        call tstFileListMake t, fileChild(fi, 'vier'), lev-1
    return
endProcedure tstFileListMake
/*--- manualTest time -----------------------------------------------*/
tstUtTime: procedure expose m.
    say 'begin' utTime()  sysvar('sysnode')
    do 3000000
       end
    call sleep 1
    say 'end  ' utTime()
return

/*--- manualTest Mail -----------------------------------------------*/
tstMail: procedure expose m.
do i=1 to 2
    call mailHead xy, 'mail from walter''s rexx' time() i, A540769
    call mailText xy, 'und hier kommt der text' ,
                , 'und zeile zwei timestamp' i':' date('s') time() ,
                , left('und eine lange Zeile 159', 156, '+')159 ,
                , left('und eine lange Zeile 160', 157, '+')160 ,
                , left('und eine lange Zeile 161', 158, '+')161 ,
                , '<ol><li>'left('und eine lange', 200,'+')203 '</li>',
                , '<li bgcolor=yellow>und kurz</li></ol>' ,
                , '<h1>und Schluss mit html</h1>'
    call mailSend xy
    call sleep 3
    end
    return
endprocedure tstMail

tstF: procedure expose m.
/*
$=/tstF/
    ### start tst tstF ################################################
    f(1 23%c345%c67%%8, eins,  zwei ) =1 23eins345 zwei 67%8;
    f(1\S23%c345%S67%%8, eins,  zwei ) =1\S23eins345zwei67%8;
    f(1 23%C345%C67%%8, eins,  zwei ) =1 23eins345 zwei 67%8;
    f(1 23%c345%S67%%8, eins,  zwei ) =1 23eins345zwei67%8;
    f(1%S2%c3@2%S4@%c5, eins,  zwei ) =1eins2 zwei 3zwei4 zwei 5;
    f(1%-2C2%3C3@2%3.2C4, eins,  zwei ) =1ei2ei 3zwe4;
    f(1@F1%c2@f2%c3@F3%c4, eins,  zwei ) =1fEins2fZwei3fDrei4;
    f(a%(b%3Cc%)d, eins,  zwei ) =abinscd;
    f(a%(b%3Cc%,d%-3Ce%)f, eins,  zwei ) =adbinef;
    f(a@2%(b%3Cc%)d, eins,  zwei ) =abei cd;
    f(a@2%(b%3Cc%,d%-3Ce%)f, eins,  zwei ) =adbeief;
    tstF2 _ %-9C @%5I @%8I @%+8I @%-8I -----
    _ 0             0        0       +0 0       .
    _ -1.2         -1       -1       -1 -1      .
    _ 2.34          2        2       +2 2       .
    _ -34.8765    -35      -35      -35 -35     .
    _ 567.91234   568      568     +568 568     .
    _ -8901     -8901    -8901    -8901 -8901   .
    _ 23456     23456    23456   +23456 23456   .
    _ -789012   *****  -789012  -789012 -789012 .
    _ 34e6      ***** 34000000 ******** 34000000
    _ -56e7     ***** ******** ******** ********
    _ 89e8      ***** ******** ******** ********
    _ txtli     txtli    txtli    txtli txtli   .
    _ undEinLan undEi undEinLa undEinLa undEinLa
    tstF2 _ %-9C @%5.2I @%12.2I @%+12.2I @%-12.2I -----
    _ 0          0.00         0.00        +0.00 0.00        .
    _ -1.2      -1.20        -1.20        -1.20 -1.20       .
    _ 2.34       2.34         2.34        +2.34 2.34        .
    _ -34.8765  *****       -34.88       -34.88 -34.88      .
    _ 567.91234 *****       567.91      +567.91 567.91      .
    _ -8901     *****     -8901.00     -8901.00 -8901.00    .
    _ 23456     *****     23456.00    +23456.00 23456.00    .
    _ -789012   *****   -789012.00   -789012.00 -789012.00  .
    _ 34e6      *****  34000000.00 +34000000.00 34000000.00 .
    _ -56e7     ***** ************ ************ ************
    _ 89e8      ***** ************ ************ ************
    _ txtli     txtli        txtli        txtli txtli       .
    _ undEinLan undEi undEinLanger undEinLanger undEinLanger
    tstF2 _ %-9C @%7e @% 8E @% 9.3e @% 11.4E -----
    _ 0         0.00e00  0.00E00  0.000e00  0.0000E000
    _ -1.2      -1.2e00 -1.20E00 -1.200e00 -1.2000E000
    _ 2.34      2.34e00  2.34E00  2.340e00  2.3400E000
    _ -34.8765  -3.5e01 -3.49E01 -3.488e01 -3.4877E001
    _ 567.91234 5.68e02  5.68E02  5.679e02  5.6791E002
    _ -8901     -8.9e03 -8.90E03 -8.901e03 -8.9010E003
    _ 23456     2.35e04  2.35E04  2.346e04  2.3456E004
    _ -789012   -7.9e05 -7.89E05 -7.890e05 -7.8901E005
    _ 34e6      3.40e07  3.40E07  3.400e07  3.4000E007
    _ -56e7     -5.6e08 -5.60E08 -5.600e08 -5.6000E008
    _ 89e8      8.90e09  8.90E09  8.900e09  8.9000E009
    _ txtli       txtli    txtli     txtli       txtli.
    _ undEinLan undEinL undEinLa undEinLan undEinLange
    _ 8.76e-07  8.76e-7  8.76E-7  8.760e-7  8.7600E-07
    _ 5.43e-11  5.4e-11  5.4E-11  5.43e-11  5.4300E-11
    _ -8.76e-07 -8.8e-7 -8.76E-7 -8.760e-7 -8.7600E-07
    _ -5.43e-11 -5e-011 -5.4E-11 -5.43e-11 -5.4300E-11
    tstF2 _ %-9C @%kt @%kd @%kb -----
    _ 0          0s00    0     0 .
    _ -1.2      -1s20   -1    -1 .
    _ 2.34       2s34 2340m    2 .
    _ -34.8765  -0m35  -35   -35 .
    _ 567.91234  9m28  568   568 .
    _ -8901     -2h28   -9k   -9k
    _ 23456      6h31   23k   23k
    _ -789012   -9d03 -789k -771k
    _ 34e6       394d   34M   32M
    _ -56e7     -++++ -560M -534M
    _ 89e8      +++++ 8900M 8488M
    _ txtli     txtli txtli txtli
    _ undEinLan Text? Text? Text?
    _ 8.76e-07   0s00  876n    0 .
    _ 5.43e-11   0s00   54p    0 .
    _ -8.76e-07 -0s00 -876n   -0 .
    _ -5.43e-11 -0s00  -54p   -0 .
$/tstF/ */
    call tst t, 'tstF'
    call tstF1 '1 23%c345%c67%%8'
    call tstF1 '1\S23%c345%S67%%8'
    call tstF1 '1 23%C345%C67%%8'
    call tstF1 '1 23%c345%S67%%8'
    call tstF1 '1%S2%c3@2%S4@%c5'
    call tstF1 '1%-2C2%3C3@2%3.2C4'
    call tstF1 '1@F1%c2@f2%c3@F3%c4'
    call tstF1 'a%(b%3Cc%)d'
    call tstF1 'a%(b%3Cc%,d%-3Ce%)f'
    call tstF1 'a@2%(b%3Cc%)d'
    call tstF1 'a@2%(b%3Cc%,d%-3Ce%)f'
    nums = '0 -1.2 2.34 -34.8765 567.91234 -8901 23456' ,
                '-789012 34e6 -56e7 89e8 txtli undEinLangerText?'
    call tstF2 '_ %-9C @%5I @%8I @%+8I @%-8I', nums
    call tstF2 '_ %-9C @%5.2I @%12.2I @%+12.2I @%-12.2I', nums
    num2 = ' 8.76e-07  5.43e-11 -8.76e-07  -5.43e-11'
    call tstF2 '_ %-9C @%7e @% 8E @% 9.3e @% 11.4E', nums num2
    call tstF2 '_ %-9C @%kt @%kd @%kb', nums num2
    call tstEnd t
    return
endProcedure tstF

tstF1: procedure expose m.
parse arg fmt
    e='eins'
    z=' zwei '
    f2 = 'f2'
    m.e.f1 = 'fEins'
    m.e.f2 = 'fZwei'
    m.e.f3 = 'fDrei'
    call tstOut t, "f("fmt"," e"," z") ="f(fmt, e, z)";"
    return
endProcedure tstF1

tstF2: procedure expose m.
parse arg fmt, vals
    call tstOut t, 'tstF2' fmt '-----'
    do vx=1 to words(vals)
        call tstOut t, f(fmt, word(vals, vx))
        end
    return
endProcedure tstF2

tstFWords: procedure expose m.
/*
$=/tstFWords/
    ### start tst tstFWords ###########################################
    ??empty??  .
    1space     .
    , #0--     --
    #a%9c#l<<#r>> <<>>
    *#a%-7c    .
    ??empty??  eins
    1space     eins
    , #0--     eins
    #a%9c#l<<#r>> <<     eins>>
    *#a%-7c    eins   .
    ??empty??  einszwei
    1space     eins zwei
    , #0--     eins, zwei
    #a%9c#l<<#r>> <<     eins     zwei>>
    *#a%-7c    eins   *zwei   .
    ??empty??  einszweidrei
    1space     eins zwei drei
    , #0--     eins, zwei, drei
    #a%9c#l<<#r>> <<     eins     zwei     drei>>
    *#a%-7c    eins   *zwei   *drei   .
$/tstFWords/
*/
    ws = '  eins zwei   drei '
    call tst t, 'tstFWords'
    do l=0 to 3
      call tstOut t, '??empty?? ' fWords(            ,subword(ws,1,l))
      call tstOut t, '1space    ' fWords(' '         ,subword(ws,1,l))
      call tstOut t, ', #0--    ' fWords(', #0--'    ,subword(ws,1,l))
      call tstOut t, '#a%9c#l<<#r>>',
              fWords('#a%9c#l<<#r>>' ,subword(ws,1,l))
      call tstOut t, '*#a%-7c   ' fWords('*#a%-7c'    ,subword(ws,1,l))
      end
    call tstEnd t
    return
endProcedure tstFWords
tstFe: procedure expose m.
/*
$=/tstFe/
  ### start tst tstFe ###############################################
  .                   1 < 1.00e00> <1.00e00>
  .                   0 < 0.00e00> <0.00e00>
  .                -2.1 <-2.10e00> <-2.1e00>
  .                  .3 < 3.00e-1> <3.00e-1>
  .             -.45678 <-4.57e-1> <-4.6e-1>
  .                 901 < 9.01e02> <9.01e02>
  .               -2345 <-2.35e03> <-2.3e03>
  .              678e90 < 6.78e92> <6.78e92>
  .              123e-4 < 1.23e-2> <1.23e-2>
  .             567e-89 < 5.7e-87> <5.7e-87>
  .              12e456 < 1.2e457> <1.2e457>
  .             78e-901 < 8e-0900> <8e-0900>
  .           2345e5789 < 2e05792> <2e05792>
  .           123e-4567 < 1e-4565> <1e-4565>
  .          8901e23456 < 9e23459> <9e23459>
  .          -123e-4567 <-1e-4565> <-0e-999>
  .          567e890123 <********> <*******>
  .       45678e-901234 < 0e-9999> <0e-9999>
  .                kurz <    kurz> <kurz   >
  .       undLangerText <undLange> <undLang>
$/tstFe/
*/
    call tst t, 'tstFe'
    vAll = '1 0 -2.1 .3 -.45678 901 -2345 678e90 123e-4' ,
            '567e-89 12e456 78e-901 2345e5789  123e-4567 8901e23456' ,
            '-123e-4567 567e890123 45678e-901234' ,
            'kurz undLangerText'
    do vx=1 to words(vAll)
        v = word(vAll, vx)
        call tstOut t, right(v, 20)  '<'fe(v, 8, 2, 'e', ' ')'>' ,
                                     '<'fe(v, 7, 1, 'e', '-')'>'
        end
    call tstEnd t
    return
endProcedure

tstFTst: procedure expose m.
/*
$=/tstFTstS/
    ### start tst tstFTstS ############################################
    1956-01-29-23.34.56.987654     SS => 1956-01-29-23.34.56.987654|
    1956-01-29-23.34.56.987654     Ss => 1956-01-29-23.34.56|
    1956-01-29-23.34.56.987654     S  => 1956-01-29-23.34.56|
    1956-01-29-23.34.56.987654     SD => 19560129|
    1956-01-29-23.34.56.987654     Sd => 560129|
    1956-01-29-23.34.56.987654     SE => 29.01.1956|
    1956-01-29-23.34.56.987654     Se => 29.01.56|
    1956-01-29-23.34.56.987654     St => 23.34.56|
    1956-01-29-23.34.56.987654     ST => 23:34:56.987654|
    1956-01-29-23.34.56.987654     SZ => GB29|
    1956-01-29-23.34.56.987654     SM => B2923345|
    1956-01-29-23.34.56.987654     SH => C33456|
    1956-01-29-23.34.56.987654     SY => GB29X3LV|
    1956-01-29-23.34.56.987654     SA => C9233456|
    1956-01-29-23.34.56.987654     Sj => 56029|
    1956-01-29-23.34.56.987654     SJ => 714076|
$/tstFTstS/
$=/tstFTsts/
    ### start tst tstFTsts ############################################
    2014-12-23-16.57.38            sS => 2014-12-23-16.57.38.000000|
    2014-12-23-16.57.38            ss => 2014-12-23-16.57.38|
    2014-12-23-16.57.38            s  => 2014-12-23-16.57.38|
    2014-12-23-16.57.38            sD => 20141223|
    2014-12-23-16.57.38            sd => 141223|
    2014-12-23-16.57.38            sE => 23.12.2014|
    2014-12-23-16.57.38            se => 23.12.14|
    2014-12-23-16.57.38            st => 16.57.38|
    2014-12-23-16.57.38            sT => 16:57:38.000000|
    2014-12-23-16.57.38            sZ => EM23|
    2014-12-23-16.57.38            sM => M2316573|
    2014-12-23-16.57.38            sH => B65738|
    2014-12-23-16.57.38            sY => OM23Q5SI|
    2014-12-23-16.57.38            sA => C3165738|
    2014-12-23-16.57.38            sj => 14357|
    2014-12-23-16.57.38            sJ => 735589|
    2014-12-23-16.57.38            su +> E1KCA3JT|
    2014-12-23-16.57.38            sL +> 00CE3F48639FB0000000|
$/tstFTsts/
Winterzeit
    2014-12-23-16.57.38            su +> E1KCA3JT|
    2014-12-23-16.57.38            sL +> 00CE3F48639FB0000000|
Sommerzeit
    2014-12-23-16.57.38            su +> E1J8X3NE|
    2014-12-23-16.57.38            sL +> 00CE3F3AFA6570000000|
$=/tstFTstD/
    ### start tst tstFTstD ############################################
    23450618                       DS => 2345-06-18-00.00.00.000000|
    23450618                       Ds => 2345-06-18-00.00.00|
    23450618                       D  => 2345-06-18-00.00.00|
    23450618                       DD => 23450618|
    23450618                       Dd => 450618|
    23450618                       DE => 18.06.2345|
    23450618                       De => 18.06.45|
    23450618                       Dt => 00.00.00|
    23450618                       DT => 00:00:00.000000|
    23450618                       DZ => PG18|
    23450618                       DM => G1800000|
    23450618                       DH => A00000|
    23450618                       DY => UG18A0AA|
    23450618                       DA => B8000000|
    23450618                       Dj => 45169|
    23450618                       DJ => 856296|
$/tstFTstD/
$=/tstFTstd/
    ### start tst tstFTstd ############################################
    120724                         dS => 2012-07-24-00.00.00.000000|
    120724                         ds => 2012-07-24-00.00.00|
    120724                         d  => 2012-07-24-00.00.00|
    120724                         dD => 20120724|
    120724                         dd => 120724|
    120724                         dE => 24.07.2012|
    120724                         de => 24.07.12|
    120724                         dt => 00.00.00|
    120724                         dT => 00:00:00.000000|
    120724                         dZ => CH24|
    120724                         dM => H2400000|
    120724                         dH => A00000|
    120724                         dY => MH24A0AA|
    120724                         dA => C4000000|
    120724                         dj => 12206|
    120724                         dJ => 734707|
$/tstFTstd/
$=/tstFTstE/
    ### start tst tstFTstE ############################################
    09.12.1345                     ES => 1345-12-09-00.00.00.000000|
    09.12.1345                     Es => 1345-12-09-00.00.00|
    09.12.1345                     E  => 1345-12-09-00.00.00|
    09.12.1345                     ED => 13451209|
    09.12.1345                     Ed => 451209|
    09.12.1345                     EE => 09.12.1345|
    09.12.1345                     Ee => 09.12.45|
    09.12.1345                     Et => 00.00.00|
    09.12.1345                     ET => 00:00:00.000000|
    09.12.1345                     EZ => PM09|
    09.12.1345                     EM => M0900000|
    09.12.1345                     EH => A00000|
    09.12.1345                     EY => UM09A0AA|
    09.12.1345                     EA => A9000000|
    09.12.1345                     Ej => 45343|
    09.12.1345                     EJ => 491228|
$/tstFTstE/
$=/tstFTste/
    ### start tst tstFTste ############################################
    31.05.24                       eS => 2024-05-31-00.00.00.000000|
    31.05.24                       es => 2024-05-31-00.00.00|
    31.05.24                       e  => 2024-05-31-00.00.00|
    31.05.24                       eD => 20240531|
    31.05.24                       ed => 240531|
    31.05.24                       eE => 31.05.2024|
    31.05.24                       ee => 31.05.24|
    31.05.24                       et => 00.00.00|
    31.05.24                       eT => 00:00:00.000000|
    31.05.24                       eZ => OF31|
    31.05.24                       eM => F3100000|
    31.05.24                       eH => A00000|
    31.05.24                       eY => YF31A0AA|
    31.05.24                       eA => D1000000|
    31.05.24                       ej => 24152|
    31.05.24                       eJ => 739036|
$/tstFTste/
$=/tstFTstt/
### start tst tstFTstt ############################################
    12.34.56                       tS => 0001-01-01-12.34.56.000000|
    12.34.56                       ts => 0001-01-01-12.34.56|
    12.34.56                       t  => 0001-01-01-12.34.56|
    12.34.56                       tD => 00010101|
    12.34.56                       td => 010101|
    12.34.56                       tE => 01.01.0001|
    12.34.56                       te => 01.01.01|
    12.34.56                       tt => 12.34.56|
    12.34.56                       tT => 12:34:56.000000|
    12.34.56                       tZ => ??01|
    12.34.56                       tM => ?0112345|
    12.34.56                       tH => B23456|
    12.34.56                       tY => ??01M3LV|
    12.34.56                       tA => A1123456|
    12.34.56                       tj => 01001|
    12.34.56                       tJ => 0|
$/tstFTstt/
$=/tstFTstT/
    ### start tst tstFTstT ############################################
    23.45.06.784019                TS => 0001-01-01-23.45.06.784019|
    23.45.06.784019                Ts => 0001-01-01-23.45.06|
    23.45.06.784019                T  => 0001-01-01-23.45.06|
    23.45.06.784019                TD => 00010101|
    23.45.06.784019                Td => 010101|
    23.45.06.784019                TE => 01.01.0001|
    23.45.06.784019                Te => 01.01.01|
    23.45.06.784019                Tt => 23.45.06|
    23.45.06.784019                TT => 23.45.06.784019|
    23.45.06.784019                TZ => ??01|
    23.45.06.784019                TM => ?0123450|
    23.45.06.784019                TH => C34506|
    23.45.06.784019                TY => ??01X4MG|
    23.45.06.784019                TA => A1234506|
    23.45.06.784019                Tj => 01001|
    23.45.06.784019                TJ => 0|
$/tstFTstT/
$=/tstFTstYold/
    ### start tst tstFTstY ############################################
    PE25                           YS => 2015-04-25-00.00.00.000000|
    PE25                           Ys => 2015-04-25-00.00.00|
    PE25                           Y  => 2015-04-25-00.00.00|
    PE25                           YD => 20150425|
    PE25                           Yd => 150425|
    PE25                           YE => 25.04.2015|
    PE25                           Ye => 25.04.15|
    PE25                           Yt => 00.00.00|
    PE25                           YT => 00:00:00.000000|
    PE25                           YZ => ?E25|
    PE25                           YM => E2500000|
    PE25                           YH => A00000|
    PE25                           YY => PE25A0AA|
    PE25                           YA => C5000000|
    PE25                           Yj => 15115|
    PE25                           YJ => 735712|
$/tstFTstYold/
$=/tstFTstM/
    ### start tst tstFTstM ############################################
    I2317495                       MS => 0001-08-23-17.49.50.000000|
    I2317495                       Ms => 0001-08-23-17.49.50|
    I2317495                       M  => 0001-08-23-17.49.50|
    I2317495                       MD => 00010823|
    I2317495                       Md => 010823|
    I2317495                       ME => 23.08.0001|
    I2317495                       Me => 23.08.01|
    I2317495                       Mt => 17.49.50|
    I2317495                       MT => 17:49:50.000000|
    I2317495                       MZ => ?I23|
    I2317495                       MM => I2317495|
    I2317495                       MH => B74950|
    I2317495                       MY => ?I23R4XP|
    I2317495                       MA => C3174950|
    I2317495                       Mj => 01235|
    I2317495                       MJ => 234|
$/tstFTstM/
$=/tstFTstH/
    ### start tst tstFTstH ############################################
    B23456                         HS => 0001-01-01-12.34.56.000000|
    B23456                         Hs => 0001-01-01-12.34.56|
    B23456                         H  => 0001-01-01-12.34.56|
    B23456                         HD => 00010101|
    B23456                         Hd => 010101|
    B23456                         HE => 01.01.0001|
    B23456                         He => 01.01.01|
    B23456                         Ht => 12.34.56|
    B23456                         HT => 12:34:56.000000|
    B23456                         HZ => ??01|
    B23456                         HM => ?0112345|
    B23456                         HH => B23456|
    B23456                         HY => ??01M3LV|
    B23456                         HA => A1123456|
    B23456                         Hj => 01001|
    B23456                         HJ => 0|
$/tstFTstH/
$=/tstFTstn/
    ### start tst tstFTstn ############################################
    19560423 17:58:29              nS => 1956-04-23-17.58.29.000000|
    19560423 17:58:29              ns => 1956-04-23-17.58.29|
    19560423 17:58:29              n  => 1956-04-23-17.58.29|
    19560423 17:58:29              nD => 19560423|
    19560423 17:58:29              nd => 560423|
    19560423 17:58:29              nE => 23.04.1956|
    19560423 17:58:29              ne => 23.04.56|
    19560423 17:58:29              nt => 17.58.29|
    19560423 17:58:29              nT => 17:58:29.000000|
    19560423 17:58:29              nZ => GE23|
    19560423 17:58:29              nM => E2317582|
    19560423 17:58:29              nH => B75829|
    19560423 17:58:29              nY => GE23R5UJ|
    19560423 17:58:29              nA => C3175829|
    19560423 17:58:29              nj => 56114|
    19560423 17:58:29              nJ => 714161|
$/tstFTstn/
$=/tstFTstN/
    ### start tst tstFTstN ############################################
    32101230 10:21:32.456789       NS => 3210-12-30-10.21.32.456789|
    32101230 10:21:32.456789       Ns => 3210-12-30-10.21.32|
    32101230 10:21:32.456789       N  => 3210-12-30-10.21.32|
    32101230 10:21:32.456789       ND => 32101230|
    32101230 10:21:32.456789       Nd => 101230|
    32101230 10:21:32.456789       NE => 30.12.3210|
    32101230 10:21:32.456789       Ne => 30.12.10|
    32101230 10:21:32.456789       Nt => 10.21.32|
    32101230 10:21:32.456789       NT => 10:21:32.456789|
    32101230 10:21:32.456789       NZ => AM30|
    32101230 10:21:32.456789       NM => M3010213|
    32101230 10:21:32.456789       NH => B02132|
    32101230 10:21:32.456789       NY => KM30K2DR|
    32101230 10:21:32.456789       NA => D0102132|
    32101230 10:21:32.456789       Nj => 10364|
    32101230 10:21:32.456789       NJ => 1172426|
$/tstFTstN/
$=/tstFTstY/
    ### start tst tstFTstY ############################################
    RF06R2UT                       YS => 2017-05-06-17.28.39.000000|
    RF06R2UT                       Ys => 2017-05-06-17.28.39|
    RF06R2UT                       Y  => 2017-05-06-17.28.39|
    RF06R2UT                       YD => 20170506|
    RF06R2UT                       Yd => 170506|
    RF06R2UT                       YE => 06.05.2017|
    RF06R2UT                       Ye => 06.05.17|
    RF06R2UT                       Yt => 17.28.39|
    RF06R2UT                       YT => 17:28:39.000000|
    RF06R2UT                       YZ => ?F06|
    RF06R2UT                       YM => F0617283|
    RF06R2UT                       YH => B72839|
    RF06R2UT                       YY => RF06R2UT|
    RF06R2UT                       YA => A6172839|
    RF06R2UT                       Yj => 17126|
    RF06R2UT                       YJ => 736454|
$/tstFTstY/
*/
    say "current time '%t  '" f('%t  ') "'%t D'" f('%t D')
    say "  '%t S'" f('%t S') "'%t t'" f('%t t') "'%t T'" f('%t T')
    allOut = 'Ss DdEetTZMHYAjJ'
    allIn  = 'S1956-01-29-23.34.56.987654' ,
             's2014-12-23-16.57.38' ,
             'D23450618' ,
             'd120724'   ,
             'E09.12.1345' ,
             'e31.05.24' ,
             't12.34.56'  ,
             'T23.45.06.784019' ,
      /*     'YPE25' ,
      */     'MI2317495' ,
             'HB23456' ,
             'n19560423*17:58:29' ,
             'N32101230*10:21:32.456789',
             'YRF06R2UT'
    do ix=1 to words(allIn)
        parse value word(allIn, ix) with iF 2 iV
        iv = translate(iv, ' ', '*')
        call tst t, "tstFTst"iF
        do ox=1 to length(allOut)
            ft = iF || substr(allOut, ox, 1)
            call tstOut t, left(iV, 30) ft  '=>' f('%t'ft, iV)'|'
            if 0 & iF = 'Y' then
                say '???' ft '>>>' mGet('F_GEN.%t'ft)
            end
        if ix=2 then do
            call tstOut t, left(iV, 30) iF'u'  '+>' f('%t'iF'u', iV)'|'
            call tstOut t, left(iV, 30) iF'L'  '+>' f('%t'iF'L', iV)'|'
            end
        call tstEnd t
        end
    return
endProcedure tstFTst

tstFUnit2: procedure expose m.
/*      b
$=/tstFUnit2/
    ### start tst tstFUnit2 ###########################################
    . 12  = 12 12
    . 23k = 23000 23552
    34 K = 34000 34816
    45 M = 45000000 47185920
    567G = 567000000000 608811614208
    . 678 = 678
$/tstFUnit2/
*/
    call tst t, 'tstFUnit2'
    call tstOut t, ' 12  =' fUnit2I('d',' 12 ')  fUnit2I('b',' 12 ')
    call tstOut t, ' 23k =' fUnit2I('d',' 23k')  fUnit2I('b',' 23k')
    call tstOut t, '34 K =' fUnit2I('d','34 K ') fUnit2I('b','34 K ')
    call tstOut t, '45 M =' fUnit2I('d','45 M')  fUnit2I('b','45 M')
    call tstOut t, '567G =' fUnit2I('d','567G')  fUnit2I('b','567G')
    call tstOut t, ' 678 =' fUnit2I('t',' 678 ')
 /* t umbauen, funktioniert nicht mit jetztigen Metadaten ||||
    call tstOut t, ' 78  s ='fUnit2I('t', ' 78 s ')
    call tstOut t, '567G' fUnit2I('t', ' 123 ')           */
    call tstEnd t
    return
endProcedure tstFU
tstFmt: procedure expose m.
    call pipeIni
/*
$=/tstFmt/
    ### start tst tstFmt ##############################################
    =   a2i b3b   d4                       fl5          ex6
    -11 -11 b3    d4-11+d4++++    -111.1000000 -1.11000e-12
    -1  -10 b     d4-10+d4+++            null1        null3
    -    -9 b3b-9 d4-9+d4+++       -11.0000000 -1.11900e-10
    -8+  -8 b3b-  d4-8+d4++        -18.0000000 -1.18000e010
    -7   -7 b3b   d4-7+d4+          -7.0000000 -1.70000e-07
    -    -6 b3    d4-6+d4           -0.1111160 -6.00000e006
    -5+  -5 b     d4-5+d                 null2        null2
    -4   -4 b3b-4 d4-4+         -11114.0000000 -1.11140e008
    -    -3 b3b-  d4-3              -0.1130000 -1.13000e-04
    -2+  -2 b3b   d4-               -0.1200000 -1.20000e001
    -1   -1 b3    d4                -0.1000000 -1.00000e-02
    0     0 b     d                      null1        null1
    1+    1 b3    d4                 0.1000000  1.00000e-02
    2++   2 b3b   d42                0.1200000  1.20000e001
    3     3 b3b3  d43+               0.1130000  1.13000e-04
    4+    4 b3b4+ d44+d          11114.0000000  1.11140e008
    5++   5 b     d45+d4                 null2        null2
    6     6 b3    d46+d4+            0.1111160  1.11116e005
    7+    7 b3b   d47+d4++           0.1111117  7.00000e-08
    8++   8 b3b8  d48+d4+++          8.0000000  1.80000e009
    9     9 b3b9+ d49+d4++++         0.9000000  1.19000e-08
    10   10 b     d410+d4++++            null1        null3
    11+  11 b3    d411+d4+++++       0.1110000  1.00000e-12
    1    12 b3b   d412+d4++++++  11112.0000000  2.00000e012
    13   13 b3b1  d               1111.3000000  1.13000e-12
    14+  14 b3b14 d4            111111.0000000  1.40000e013
    1    15 b     d41                    null2        null1
    16   16 b3    d416               6.0000000  1.16000e003
    17+  17 b3b   d417+              0.7000000  1.11170e-03
    1    18 b3b1  d418+d            11.0000000  1.11800e003
    19   19 b3b19 d419+d4            0.1190000  9.00000e-05
    20+  20 b     d420+d4+               null1        null2
    2    21 b3    d421+d4++         11.1210000  1.11000e-05
    22   22 b3b   d422+d4+++     11111.2000000  2.00000e007
    23+  23 b3b2  d423+d4++++        0.1111123  1.11230e-09
    c3L      a2i drei  d4                 fl5          ex6
    -11 -1.10E01 b3    d4-11+d   -111.1000000 -1.11000e-12
    -1  -1.00E01 b     d4-10+d          null1        null3
    -   -9.00E00 b3b-9 d4-9+d4    -11.0000000 -1.11900e-10
    -8+ -8.00E00 b3b-  d4-8+d4    -18.0000000 -1.18000e010
    -7  -7.00E00 b3b   d4-7+d4     -7.0000000 -1.70000e-07
    -   -6.00E00 b3    d4-6+d4     -0.1111160 -6.00000e006
    -5+ -5.00E00 b     d4-5+d           null2        null2
    -4  -4.00E00 b3b-4 d4-4+   -11114.0000000 -1.11140e008
    -   -3.00E00 b3b-  d4-3        -0.1130000 -1.13000e-04
    -2+ -2.00E00 b3b   d4-         -0.1200000 -1.20000e001
    -1  -1.00E00 b3    d4          -0.1000000 -1.00000e-02
    0    0.00E00 b     d                null1        null1
    1+   1.00E00 b3    d4           0.1000000  1.00000e-02
    2++  2.00E00 b3b   d42          0.1200000  1.20000e001
    3    3.00E00 b3b3  d43+         0.1130000  1.13000e-04
    4+   4.00E00 b3b4+ d44+d    11114.0000000  1.11140e008
    5++  5.00E00 b     d45+d4           null2        null2
    6    6.00E00 b3    d46+d4+      0.1111160  1.11116e005
    7+   7.00E00 b3b   d47+d4+      0.1111117  7.00000e-08
    8++  8.00E00 b3b8  d48+d4+      8.0000000  1.80000e009
    9    9.00E00 b3b9+ d49+d4+      0.9000000  1.19000e-08
    10   1.00E01 b     d410+d4          null1        null3
    11+  1.10E01 b3    d411+d4      0.1110000  1.00000e-12
    1    1.20E01 b3b   d412+d4  11112.0000000  2.00000e012
    13   1.30E01 b3b1  d         1111.3000000  1.13000e-12
    14+  1.40E01 b3b14 d4      111111.0000000  1.40000e013
    1    1.50E01 b     d41              null2        null1
    16   1.60E01 b3    d416         6.0000000  1.16000e003
    17+  1.70E01 b3b   d417+        0.7000000  1.11170e-03
    1    1.80E01 b3b1  d418+d      11.0000000  1.11800e003
    19   1.90E01 b3b19 d419+d4      0.1190000  9.00000e-05
    20+  2.00E01 b     d420+d4          null1        null2
    2    2.10E01 b3    d421+d4     11.1210000  1.11000e-05
    22   2.20E01 b3b   d422+d4  11111.2000000  2.00000e007
    23+  2.30E01 b3b2  d423+d4      0.1111123  1.11230e-09
$/tstFmt/ */

    call tst t, "tstFmt"
    b = jBuf()
    st = b'.BUF'
    call pipe '+F', b
    call tstDataClassOut '. c3 a2i i b3b c5 d4 c13 fl5 f8n2 ex6 e9n3',
        , -11, + 23
    call pipe '-'
    call fTabAuto fTabReset(abc, 1), b
    call fTabReset abc, 1
    cc = fTabAdd(abc,      , , 'c3L')
    m.cc.fmt = fTabDetectFmt(st)
    call fTabAdd abc, 'a2i', '% 8E'
    cc = fTabAdd(abc, 'b3b', ,'drei')
    m.cc.fmt = fTabDetectFmt(st, '.b3b')
    call fTabAdd abc, 'd4', '%-7C'
    cc = fTabAdd(abc, 'fl5')
    m.cc.fmt = fTabDetectFmt(st, '.fl5')
    cc = fTabAdd(abc, 'ex6')
    m.cc.fmt = fTabDetectFmt(st, '.ex6')
    call fTab abc, b
    call tstEnd t
    return
endProcedure tstFmt

tstFTab: procedure expose m.
/*
$=/tstFTab/
    ### start tst tstFTab #############################################
    testData begin
    ..---------a2i-b3b------------------d4------fl5-----ex6---
    -11       -11 b3           -11+d4++++ -111.100 -1e-012
    -1        -10 b            4-10+d4+++    null1   null3
    -          -9 b3b-9        d4-9+d4+++  -11.000 -1e-010
    -8+        -8 b3b-          d4-8+d4++  -18.000 -1.2e10
    -7         -7 b3b            d4-7+d4+   -7.000 -1.7e-7
    -          -6 b3              d4-6+d4   -0.111 -6.0e06
    -5+        -5 b                d4-5+d    null2   null2
    -4         -4 b3b-4             d4-4+ ******** -1.1e08
    -          -3 b3b-               d4-3   -0.113 -1.1e-4
    -2+        -2 b3b                 d4-   -0.120 -1.2e01
    -1         -1 b3                   d4   -0.100 -1.0e-2
    0           0 b                     d    null1   null1
    1+          1 b3                   d4    0.100 1.00e-2
    2++         2 b3b                 d42    0.120 1.20e01
    3           3 b3b3               d43+    0.113 1.13e-4
    4+          4 b3b4+             d44+d ******** 1.11e08
    5++         5 b                d45+d4    null2   null2
    6           6 b3              d46+d4+    0.111 1.11e05
    7+          7 b3b            d47+d4++    0.111 7.00e-8
    8++         8 b3b8          d48+d4+++    8.000 1.80e09
    9           9 b3b9+        d49+d4++++    0.900 1.19e-8
    10         10 b            410+d4++++    null1   null3
    11+        11 b3           11+d4+++++    0.111 1.0e-12
    1          12 b3b          2+d4++++++ ******** 2.00e12
    13         13 b3b1                  d 1111.300 1.1e-12
    14+        14 b3b14                d4 ******** 1.40e13
    1          15 b                   d41    null2   null1
    16         16 b3                 d416    6.000 1.16e03
    17+        17 b3b               d417+    0.700 1.11e-3
    1          18 b3b1             d418+d   11.000 1.12e03
    19         19 b3b19           d419+d4    0.119 9.00e-5
    20+        20 b              d420+d4+    null1   null2
    2          21 b3            d421+d4++   11.121 1.11e-5
    22         22 b3b          d422+d4+++ ******** 2.00e07
    23+        23 b3b2         423+d4++++    0.111 1.11e-9
    ..---------a2i-b3b------------------d4------fl5-----ex6---
    testData end
$/tstFTab/ */

    call pipeIni
    call tst t, "tstFTab"
    b = jBuf()
    st = b'.BUF'
    call pipe '+F', b
    call tstDataClassOut '. c3 a2i i b3b c5 d4 c13 fl5 f8n2 ex6 e9n3',
        , -11, + 23
    call pipe 'P|'
    call fTabReset ft, 2 1, 1 3, '-'
    call fTabAdd      ft, ''   , '%-6C', '.', , 'testData begin',
                                                , 'testData end'
    call fTabAdd      ft, 'a2i' , '%6i'
    call fTabAdd      ft, 'b3b' , '%-12C'
    call fTabAdd      ft, 'd4'  , '%10C'
    call fTabAdd      ft, 'fl5' , '%8.3I'
    call fTabAdd      ft, 'ex6' , '%7e'
    call fTab ft
    call pipe '-'
    call tstEnd t
    return
endProcedure tstFTab

tstCSV: procedure expose m.
/*
$=/tstCSV/
    ### start tst tstCSV ##############################################
    value,value eins,value zwei
    value,"value, , eins",value zwei
    value,"","value ""zwei"" oder?"
    value,,"value ""zwei"" oder?"
$/tstCSV/ */
    m.tstCsv.c.1 = ''
    m.tstCsv.c.2 = .eins
    m.tstCsv.c.3 = .zwei
    m.tstCsv.c.0 = 3
    call tst t, "tstCSV"
    m.tstCsv.o      = 'value'
    m.tstCsv.o.eins = 'value eins'
    m.tstCsv.o.zwei = 'value zwei'
    call tstOut t, csv4O(tstCsv'.'o, tstCsv'.'c, 0)
    m.tstCsv.o.eins = 'value, , eins'
    call tstOut t, csv4O(tstCsv'.'o, tstCsv'.'c, 0)
    m.tstCsv.o.eins = ''
    m.tstCsv.o.zwei = 'value "zwei" oder?'
    call tstOut t, csv4O(tstCsv'.'o, tstCsv'.'c, 0)
    m.tstCsv.o.eins = '---'
    call tstOut t, csv4O(tstCsv'.'o, tstCsv'.'c, 1, '---')
    call tstEnd t
    return
endProcedure tstCSV

tstCSV2: procedure expose m.
/*
$=/tstCSV2/
    ### start tst tstCSV2 #############################################
    w: [f1=1 fZwei=eins fDr=r]
    w: [f1=2 fZwei= zwei , 2  fDr=]
    w: [f1=3 fZwei=schluss fDr=]
    W: [F1=1 FZWEI=eins FDR=r]
    W: [F1=2 FZWEI= zwei , 2  FDR=]
    W: [F1=3 FZWEI=schluss FDR=]
    c: [f1=1 fComma=eins fDr=r]
    c: [f1=    2  fComma= zwei , 2  fDr=]
    c: [f1=3 fComma=schluss fDr=]
    C: [F1=1 FCOMMA=eins FDR=r]
    C: [F1=    2  FCOMMA= zwei , 2  FDR=]
    C: [F1=3 FCOMMA=schluss FDR=]
    o: [f1=1 fCol=eins fDr=drei fVie=und   vier]
    o: [f1=222222Z fCol=ccccccccC fDr=dddddddD fVie=vvvvvvvvvvvvvv V]
    o: [f1=3 fCol=schluss fDr=drei fVie=vier]
    O: [F1=1 FCOL=eins FDR=drei FVIE=und   vier]
    O: [F1=222222Z FCOL=ccccccccC FDR=dddddddD FVIE=vvvvvvvvvvvvvv V]
    O: [F1=3 FCOL=schluss FDR=drei FVIE=vier]
$/tstCSV2/
*/
    call jIni
    call tst t, "tstCSV2"
    b = jBuf('   f1    fZwei   fDr ', '1 eins r','    2  " zwei , 2 "',
                                 , '3 schluss')
    call tstCsv22 t, 'w', csvWordRdr(b)
    call tstCsv22 t, 'W', csvWordRdr(b, 'u')
    b = jBuf('   f1 ,  fComma, fDr ', '1,eins,r','    2 ," zwei , 2 "',
                                 , '3,schluss')
    call tstCsv22 t, 'c', csv2ObjRdr(b)
    call tstCsv22 t, 'C', csv2ObjRdr(b, 'u')
    b = jBuf(' > f1 >< fCol   <fDr    fVie',
            ,'      1eins     drei             und   vier  ',
            ,'222222ZccccccccCdddddddDvvvvvvvvvvvvvv V',
            ,'   3     schluss    dreivier')
    call tstCsv22 t, 'o', csvColRdr(b)
    call tstCsv22 t, 'O', csvColRdr(b, 'u')
    call tstEnd t
    return
endProcedure tstCSV2

tstCSV22: procedure expose m.
parse arg t, l, c
    call jOpen c, '<'
    do while jRead(c)
        call tstOut t, l':' o2TexLR(m.c, , '[', ']')
        end
    call jCLose c
    return
endProcedure tstCSV22

tstCSVExt: procedure expose m.
/*
$=/tstCsvExt/
    ### start tst tstCsvExt ###########################################
    v,string eins, oder nicht?
    v,
    w,string_W zwei, usw,,,|
    c TstCsvExtF class@TstCsvExtF,u f FEINS v,f FZWEI v
    o class@TstCsvExtF o1,f1Feins,"f1,fzwei  "
    c TstCsvExtG class@TstCsvExtG,u f gDrei v,f GVIER v,f gRef r o
    f class@TstCsvExtG objG4,
    d class@TstCsvExtG objG4,objG4gDrei,objG4.gVier,objG4
    d class@TstCsvExtG objG3,,objG3.gVier,objG4
    o class@TstCsvExtG G2,g2gDrei,,objG3
    b TstCsvExtH class@TstCsvExtH,
    m metEins method@metEins,call a b,c,"d e",
    c TstCsvExtH class@TstCsvExtH,u v,f rr r o,f rH r class@TstCsvExtH,+
    method@metEins
    f class@TstCsvExtH H5,
    d class@TstCsvExtH H9,H9value,objG3,H5
    d class@TstCsvExtH H8,H8value rrWText,]escText,H9
    d class@TstCsvExtH H7,H7value rrText,]textli,H8
    d class@TstCsvExtH h6,h6-value6 rrLeer,,H7
    o class@TstCsvExtH H5,h5Value,o1,h6
$/tstCsvExt/
 */
    call jIni
    call tst t, "tstCsvExt"
    m = 'TST_CsvExt'
    call csvExtBegin m
    m.o.0 = 0
    cF = classNew('n? TstCsvExtF u f FEINS v, f FZWEI v')
    cG = classNew('n? TstCsvExtG u f gDrei v, f GVIER v, f gRef r')
    cH = class4Name('TstCsvExtH', '-')
    if cH ==  '-' then do
        cH = classNew('n TstCsvExtH u')
        cH = classNew('n= TstCsvExtH u v, f rr r, f rH r TstCsvExtH',
                              , 'm metEins call a b,c,"d e",')
        end
    do cx=1 to m.ch.0 until m.cy == 'm'
        cy = m.cH.cx
        end
    call mAdd t.trans, cF 'class@TstCsvExtF', cG 'class@TstCsvExtG' ,
                     , cH 'class@TstCsvExtH', cY 'method@'m.cy.name
    call csvExt m, o, 'string eins, oder nicht?'
    call csvExt m, o
    call csvExt m, o, s2o('string_W zwei, usw,,,|')
    call csvExt m, o, csv2o('o1',cF, 'f1Feins,"f1,fzwei  "')
    call csvExt m, o, csv2o(g2, cG, 'g2gDrei,',
           || ','csv2o('objG3', cG, ',objG3.gVier',
           || ','csv2o('objG4', cG, 'objG4gDrei,objG4.gVier,objG4')))
    call csvExt m, o, csv2o(h5, cH, 'h5Value,o1',
           || ','csv2o('h6', cH, 'h6-value6 rrLeer,',
           || ','csv2o(h7,   cH, 'H7value rrText,textli',
           || ','csv2o(h8,   cH, 'H8value rrWText,]escText',
           || ','csv2o(h9,   cH, 'H9value,objG3,H5')))))
    call outSt o
    call tstEnd t
    return
endProcedure tstCSVExt

tstCsvV2F: procedure expose m.
/*
$=/tstCsvV2F/
    ### start tst tstCsvV2F ###########################################
    abcd
    abcde
    abcd&
    ef
    abc |
    abcd&
    . |
    abcd&
    e |
    abc&|
    abcd&
    ||
    abcd&
    e&|
    abcd&
    efgh
    abcd&
    efghi
    abcd&
    efgh&
    ij
    abcd&
    efgh&
    ij |
    abcd&
    efgh&
    ijk&|
    abcd&
    efgh&
    ijkl&
    ||
    * f2v
    abcd
    abcde
    abcdef
    abc .
    abcd .
    abcde .
    abc&
    abcd|
    abcde&
    abcdefgh
    abcdefghi
    abcdefghij
    abcdefghij .
    abcdefghijk&
    abcdefghijkl|
    * f2v zwei
    begin zwei
    *** err: csvF2vEnd but strt='drei '
$/tstCsvV2F/
 */
    call jIni
    call tst t, "tstCsvV2F"
    m = 'TST_csvV2F'
    call csvV2FBegin m, 5
    m.o.0 = 0
    call mAdd mCut(i1, 0), 'abcd'          ,
                         , 'abcde'         ,
                         , 'abcdef'        ,
                         , 'abc '          ,
                         , 'abcd '         ,
                         , 'abcde '        ,
                         , 'abc&'          ,
                         , 'abcd|'         ,
                         , 'abcde&'        ,
                         , 'abcdefgh'      ,
                         , 'abcdefghi'     ,
                         , 'abcdefghij'    ,
                         , 'abcdefghij '   ,
                         , 'abcdefghijk&'  ,
                         , 'abcdefghijkl|'
    do ix=1 to m.i1.0
        call csvV2F m, o, m.i1.ix
        end
    call outSt o
    call tstOut t, '* f2v'
    m.p.0 = 0
    call csvF2VBegin m
    do ox=1 to m.o.0
        call csvF2V m, p, m.o.ox || left(' ', ox // 3)
        end
    call csvF2VEnd m
    call outSt p
    call tstOut t, '* f2v zwei'
    call mAdd mCut(o2, 0), 'begin zwei', 'drei &'
    call csvF2VBegin m
    call csvF2V m, mCut(p, 0), m.o2.1
    call csvF2V m, p, m.o2.2
    call outSt p
    call csvF2VEnd m
    call tstEnd t
    say 'test with 1sRdr'
    call tst t, "tstCsvV2F"
    b1 = jBuf()
    call mAddSt b1'.BUF', i1
    call jIni
    j1s = csvV2FRdr(b1, 5)
    call jWriteAll t, j1s
    call tstOut t, '* f2v'
    call mAddSt mCut(b1'.BUF', 0), o
    j1s = CsvF2VRdr(b1)
    call jWriteAll t, j1s
    call tstOut t, '* f2v zwei'
    call mAddSt mCut(b1'.BUF', 0), o2
    j1s = CsvF2VRdr(b1)
    call jWriteAll t, j1s
    call tstEnd t
    return
endProcedure tstCsvV2F

tstCsvInt: procedure expose m.
/*
$=/tstCsvInt/
    ### start tst tstCsvInt ###########################################
    wie geht es, "Dir", denn? .
    tstR: @ obj null
    wie geht es, "Dir", denn? class_W .
    tstR: @tstWriteoV1 isA :TstCsvIntF*2
    tstR:  .FEINS = f1Feins
    tstR:  .FZWEI = f1,fzwei  .
    tstR: @tstWriteoV3 isA :TstCsvIntG*4 = o4Value
    tstR:  .R1 refTo @tstWriteoV5 :TstCsvIntG*4 = o3Value
    tstR:   .R1 refTo @tstWriteoV3 done :TstCsvIntG*4 @tstWriteoV3
    tstR: @tstWriteoV5 isA :TstCsvIntG*4 = o3Value
    tstR:  .R1 refTo @tstWriteoV3 :TstCsvIntG*4 = o4Value
    tstR:   .R1 refTo @tstWriteoV5 done :TstCsvIntG*4 @tstWriteoV5
    metEins=call out o, "calling metEins" m.m.R1
$/tstCsvInt/
*/
    call jIni
    call tst t, "tstCsvInt"
    i = 'TST_csvInt'
    call csvIntBegin i
    call csvInt i, mCut(o, 0), 'v,wie geht es, "Dir", denn? '
    call csvInt i, o, 'v,'
    call csvInt i, o, 'w,wie geht es, "Dir", denn? class_W '
    call csvInt i, o, 'c TstCsvIntF ClassIF,u f FEINS v,f FZWEI v'
    call csvInt i, o, 'o ClassIF o1,f1Feins,"f1,fzwei  "'
    call csvInt i, o, 'b TstCsvIntG ClassIG'
    call csvInt i, o, 'm metEins adrM1,call out o,' ,
                                '"calling metEins" m.m.R1'
    call csvInt i, o, 'c TstCsvIntG ClassIG,u v, f R1 r ClassIG, adrM1'
    call csvInt i, o, 'f ClassIG o4,'
    call csvInt i, o, 'd ClassIG o3,o3Value,o4'
    call csvInt i, o, 'o ClassIG o4,o4Value,o3'
    call csvInt i, o, 'r o3,'
    do ox=1 to m.o.0
        call tstTransOc t, m.o.ox
        end
    call outSt o
    ox = m.o.0
    call out 'metEins='objMet(m.o.ox, 'metEins')
    call tstEnd t
    return
endProcedure tstCsvInt

tstFUnit: procedure
/*
$=/tstFUnit/
    ### start tst tstFUnit ############################################
    .             1 ==>    1  =->   -1  =+>    +1  =b>    1 .
    .             5 ==>    5  =->   -5  =+>    +5  =b>    5 .
    .            13 ==>   13  =->  -13  =+>   +13  =b>   13 .
    .           144 ==>  144  =-> -144  =+>  +144  =b>  144 .
    .          1234 ==> 1234  =->   -1k =+> +1234  =b> 1234 .
    .          7890 ==> 7890  =->   -8k =+> +7890  =b> 7890 .
    .             0 ==>    0  =->    0  =+>    +0  =b>    0 .
    .         234E3 ==>  234k =-> -234k =+>  +234k =b>  229k
    .          89E6 ==>   89M =->  -89M =+>   +89M =b>   85M
    .         123E9 ==>  123G =-> -123G =+>  +123G =b>  115G
    .     4567891E9 ==> 4568T =->   -5P =+> +4568T =b> 4154T
    .         0.123 ==>  123m =-> -123m =+>  +123m =b>    0 .
    .  0.0000456789 ==>   46u =->  -46u =+>   +46u =b>    0 .
    .   345.567E-12 ==>  346p =-> -346p =+>  +346p =b>    0 .
    .  123.4567E-15 ==>  123f =-> -123f =+>  +123f =b>    0 .
    .           ABC ==>   ABC =->  -ABC =+>    ABC =b>   ABC
    ABCDEFGHIJKLMN ==> JKLMN =-> JKLMN =+> IJKLMN =b> JKLMN
    .          1E77 ==> +++++ =-> -++++ =+> ++++++ =b> +++++.
    .         1E-77 ==>    0a =->   -0a =+>    +0a =b>    0 .
    .     18.543E18 ==>   19E =->  -19E =+>   +19E =b>   16E
    .     20.987E20 ==> 2099E =-> -++++ =+> +2099E =b> 1820E
    .             1 ==>  1.000  =-> -1.000  =+> +1.000  =b>  1.000 .
    .             5 ==>  5.000  =-> -5.000  =+> +5.000  =b>  5.000 .
    .            13 ==> 13.000  =-> -0.013k =+> +0.013k =b> 13.000 .
    .           144 ==>  0.144k =-> -0.144k =+> +0.144k =b>  0.141k
    .          1234 ==>  1.234k =-> -1.234k =+> +1.234k =b>  1.205k
    .          7890 ==>  7.890k =-> -7.890k =+> +7.890k =b>  7.705k
    .             0 ==>  0.000  =->  0.000  =+> +0.000  =b>  0.000 .
    .         234E3 ==>  0.234M =-> -0.234M =+> +0.234M =b>  0.223M
    .          89E6 ==> 89.000M =-> -0.089G =+> +0.089G =b> 84.877M
    .         123E9 ==>  0.123T =-> -0.123T =+> +0.123T =b>  0.112T
    .     4567891E9 ==>  4.568P =-> -4.568P =+> +4.568P =b>  4.057P
    .         0.123 ==>  0.123  =-> -0.123  =+> +0.123  =b>  0.123 .
    .  0.0000456789 ==> 45.679u =-> -0.046m =+> +0.046m =b>  0.000 .
    .   345.567E-12 ==>  0.346n =-> -0.346n =+> +0.346n =b>  0.000 .
    .  123.4567E-15 ==>  0.123p =-> -0.123p =+> +0.123p =b>  0.000 .
    .           ABC ==>     ABC =->    -ABC =+>     ABC =b>     ABC
    ABCDEFGHIJKLMN ==> HIJKLMN =-> HIJKLMN =+> HIJKLMN =b> HIJKLMN
    .          1E77 ==> +++++++ =-> -++++++ =+> +++++++ =b> +++++++.
    .         1E-77 ==>  0.000a =-> -0.000a =+> +0.000a =b>  0.000 .
    .     18.543E18 ==> 18.543E =-> -++++++ =+> +++++++ =b> 16.083E
    .     20.987E20 ==> +++++++ =-> -++++++ =+> +++++++ =b> +++++++.
$/tstFUnit/
$=/tstFUnitT/
    ### start tst tstFUnitT ###########################################
    .            .3 ==>  0s30 ++>   0s30 -+> -0s30 -->  -0s30
    .            .8 ==>  0s80 ++>   0s80 -+> -0s80 -->  -0s80
    .             1 ==>  1s00 ++>   1s00 -+> -1s00 -->  -1s00
    .           1.2 ==>  1s20 ++>   1s20 -+> -1s20 -->  -1s20
    .            59 ==> 59s00 ++>  59s00 -+> -0m59 --> -59s00
    .         59.07 ==> 59s07 ++>  59s07 -+> -0m59 --> -59s07
    .        59.997 ==>  1m00 ++>   1m00 -+> -1m00 -->  -1m00
    .            60 ==>  1m00 ++>   1m00 -+> -1m00 -->  -1m00
    .          60.1 ==>  1m00 ++>   1m00 -+> -1m00 -->  -1m00
    .           611 ==> 10m11 ++>  10m11 -+> -0h10 --> -10m11
    .        3599.4 ==> 59m59 ++>  59m59 -+> -1h00 --> -59m59
    .        3599.5 ==>  1h00 ++>   1h00 -+> -1h00 -->  -1h00
    .          3661 ==>  1h01 ++>   1h01 -+> -1h01 -->  -1h01
    .         83400 ==> 23h10 ++>  23h10 -+> -0d23 --> -23h10
    .         84700 ==> 23h32 ++>  23h32 -+> -1d00 --> -23h32
    .         86400 ==>  1d00 ++>   1d00 -+> -1d00 -->  -1d00
    .         89900 ==>  1d01 ++>   1d01 -+> -1d01 -->  -1d01
    .       8467200 ==> 98d00 ++>  98d00 -+>  -98d --> -98d00
    .    8595936.00 ==> 99d12 ++>  99d12 -+>  -99d --> -99d12
    .    8638704.00 ==>  100d ++>   100d -+> -100d -->  -100d
    .       8640000 ==>  100d ++>   100d -+> -100d -->  -100d
    .     863913600 ==> 9999d ++>  9999d -+> -++++ --> -9999d
    .     863965440 ==> +++++ ++>  +++++ -+> -++++ --> -+++++.
    .     8.6400E+9 ==> +++++ ++>  +++++ -+> -++++ --> -+++++.
$/tstFUnitT/ */
    call jIni
    call tst t, "tstFUnit"
    numeric digits 9
    d = 86400
    lst = 1 5 13 144 1234 7890 0 234e3  89e6 123e9,
          4567891e9 0.123 0.0000456789 345.567e-12 123.4567e-15 ,
           abc abcdefghijklmn   1e77 1e-77 18.543e18 20.987e20
    do wx=1 to words(lst)
        call tstOut t, right(word(lst, wx), 14) ,
                 '==>' fUnit('d'  ,    word(lst, wx)),
                 '=->' fUnit('d'  , '-'word(lst, wx)),
                 '=+>' fUnit('d[+',    word(lst, wx)),
                 '=b>' fUnit('b'  ,    word(lst, wx))
        end
    do wx=1 to words(lst)
        call tstOut t, right(word(lst, wx), 14) ,
                 '==>' fUnit('d7.3'  ,    word(lst, wx)),
                 '=->' fUnit('d7.3'  , '-'word(lst, wx)),
                 '=+>' fUnit('d7.3[+',    word(lst, wx)),
                 '=b>' fUnit('b7.3'  ,    word(lst, wx))
        end
    call tstEnd t
    call tst t, "tstFUnitT"
    d = 86400
    lst = .3 .8 1 1.2 59 59.07 59.997 60 60.1 611 ,
          3599.4 3599.5 3661 d-3000 d-1700 d d+3500 ,
          d * 98 d * 99.49 d * 99.985 d*100 d * 9999 d * 9999.6 ,
          d * 1e5
    do wx=1 to words(lst)
        call tstOut t, right(word(lst, wx), 14) ,
                 '==>' fUnit('t'  ,    word(lst, wx)),
                 '++>' fUnit('t[ ',    word(lst, wx)),
                 '-+>' fUnit('t'  , '-'word(lst, wx)),
                 '-->' fUnit('t[ ', '-'word(lst, wx))
        end
    call tstEnd t
    return
endProcedure tstFUnit

tstSb: procedure expose m.
/*
$=/tstSb/
    ### start tst tstSb ###############################################
    end        : 0
    char  3    : 1 abc
    lit   d?   : 0 .
    lit   de   : 1 de
    lit   de ? fg fgh: 1 fg
    while HIJ  : 0 .
    end        : 0
    while Jih  : 1 hi
    while ? klj: 1 jklkl ?
    end        : 1
    while ? klj: 0 .
    char  3    : 0 .
    lit        : 0 .
    until cba  : 0 .
    until ?qd  : 1 abc
    until ?qr  : 1 defdef .
    until ?qr  : 0 .
    strEnd ?   : 1 ?
    strEnd ?   : 0 ?
    strEnd ?   : 1 ab??cd????gh?
    strEnd ") ": 1 ab) .
    strEnd ") ": 1 ab) cd) ) gh) .
    string     : 1 'eins?''' v=eins?'
    space      : 1  >
    string     : 1 "zwei""" v=zwei"
    string ?   : 1 ?drei??? v=drei?
    *** err: scanErr ending Apostroph missing
    .    e 1: last token " scanPosition noEnd
    .    e 2: pos 28 in string 'eins?''' "zwei"""?drei???"noEnd
    string     : 0 " v=noEnd
$/tstSb/ */
    call pipeIni
    call tst t, 'tstSb'
    call scanSrc s, 'abcdefghijklkl ?'
    call out 'end        :' scanEnd(s)
    call out 'char  3    :' scanChar(s, 3) m.s.tok
    call out 'lit   d?   :' scanLit(s, 'd?') m.s.tok
    call out 'lit   de   :' scanLit(s, 'de') m.s.tok
    call out 'lit   de ? fg fgh:',
            scanLit(s, 'de', '?', 'fg', 'fgh') m.s.tok
    call out 'while HIJ  :' scanWhile(s, 'HIJ') m.s.tok
    call out 'end        :' scanEnd(s)
    call out 'while Jih  :' scanWhile(s, 'Jih') m.s.tok
    call out 'while ? klj:' scanWhile(s, '? klj') m.s.tok
    call out 'end        :' scanEnd(s)
    call out 'while ? klj:' scanWhile(s, '? klj') m.s.tok
    call out 'char  3    :' scanChar(s, 3) m.s.tok
    call out 'lit        :' scanLit(s) m.s.tok
    call scanSrc s, 'abcdefdef ?'
    call out 'until cba  :' scanUntil(s, 'cba') m.s.tok
    call out 'until ?qd  :' scanUntil(s, '?qd') m.s.tok
    call out 'until ?qr  :' scanUntil(s, '?qr') m.s.tok
    call out 'until ?qr  :' scanUntil(s, '?qr') m.s.tok
    call out 'strEnd ?   :' scanStrEnd(s, '?') m.s.tok
    call out 'strEnd ?   :' scanStrEnd(s, '?') m.s.tok
    call scanSrc s, 'ab??cd????gh?ijk'
    call out 'strEnd ?   :' scanStrEnd(s, '?') m.s.tok
    call scanSrc s, 'ab) cd) ) gh) jk) )'
    call out 'strEnd ") ":' scanStrEnd(s, ') ') m.s.tok
    call out 'strEnd ") ":' scanStrEnd(s, ') ') m.s.tok
    call scanSrc s, "'eins?'''" '"zwei"""?drei???"noEnd'
    call out 'string     :' scanString(s) m.s.tok 'v='m.s.val
    call out 'space      :' scanWhile(s, ' ') m.s.tok'>'
    call out 'string     :' scanString(s) m.s.tok 'v='m.s.val
    call out 'string ?   :' scanString(s, '?') m.s.tok 'v='m.s.val
    call out 'string     :' scanString(s) m.s.tok 'v='m.s.val
    call tstEnd t
    return
endProcedure tstSb

tstSb2: procedure expose m.
/*
$=/tstSb2/
    ### start tst tstSb2 ##############################################
    end        : 0
    char  3    : 1 abc
    lit   d?   : 0 .
    lit   de   : 1 de
    lit   de ? fg fgh: 1 fg
    while HIJ  : 0 .
    end        : 0
    while Jih  : 1 hi
    while ? klj: 1 jklkl ?
    end        : 1
    while ? klj: 0 .
    char  3    : 0 .
    lit        : 0 .
    until cba  : 0 .
    until ?qd  : 1 abc
    until ?qr  : 1 defdef .
    until ?qr  : 0 .
    strEnd ?   : 1 ?
    strEnd ?   : 0 ?
    strEnd ?   : 1 ab??cd????gh?
    strEnd ") ": 1 ab) .
    strEnd ") ": 1 ab) cd) ) gh) .
$/tstSb2/ */
    call pipeIni
    call tst t, 'tstSb2'
    call scanSrc s, 'abcdefghijklkl ?'
    call out 'end        :' scanEnd(s)
    call out 'char  3    :' scanChar(s, 3) m.s.tok
    call out 'lit   d?   :' scanLit(s, 'd?') m.s.tok
    call out 'lit   de   :' scanLit(s, 'de') m.s.tok
    call out 'lit   de ? fg fgh:',
            scanLit(s, 'de', '?', 'fg', 'fgh') m.s.tok
    call out 'while HIJ  :' scanWhile(s, 'HIJ') m.s.tok
    call out 'end        :' scanEnd(s)
    call out 'while Jih  :' scanWhile(s, 'Jih') m.s.tok
    call out 'while ? klj:' scanWhile(s, '? klj') m.s.tok
    call out 'end        :' scanEnd(s)
    call out 'while ? klj:' scanWhile(s, '? klj') m.s.tok
    call out 'char  3    :' scanChar(s, 3) m.s.tok
    call out 'lit        :' scanLit(s) m.s.tok
    call scanSrc s, 'abcdefdef ?'
    call out 'until cba  :' scanUntil(s, 'cba') m.s.tok
    call out 'until ?qd  :' scanUntil(s, '?qd') m.s.tok
    call out 'until ?qr  :' scanUntil(s, '?qr') m.s.tok
    call out 'until ?qr  :' scanUntil(s, '?qr') m.s.tok
    call out 'strEnd ?   :' scanStrEnd(s, '?') m.s.tok
    call out 'strEnd ?   :' scanStrEnd(s, '?') m.s.tok
    call scanSrc s, 'ab??cd????gh?ijk'
    call out 'strEnd ?   :' scanStrEnd(s, '?') m.s.tok
    call scanSrc s, 'ab) cd) ) gh) jk) )'
    call out 'strEnd ") ":' scanStrEnd(s, ') ') m.s.tok
    call out 'strEnd ") ":' scanStrEnd(s, ') ') m.s.tok
    call tstEnd t
    return
endProcedure tstSb2

tstScan: procedure expose m.
/*
$=/tstScan.1/
    ### start tst tstScan.1 ###########################################
    scan src a034,Und hr123sdfER"st1" 'str2''mit''apo''s' .
    scan n tok 4: a034 key  val .
    scan , tok 1: , key  val .
    scan n tok 3: Und key  val .
    scan v tok 1:   key  val .
    scan n tok 10: hr123sdfER key  val .
    scan q tok 5: "st1" key  val st1
    scan v tok 1:   key  val st1
    scan a tok 19: 'str2''mit''apo''s' key  val str2'mit'apo's
    scan v tok 1:   key  val str2'mit'apo's
$/tstScan.1/ */
    call tst t, 'tstScan.1'
    call tstScan1 'l"litEins"l"litZwei"ndv" "aq1' ,
        ,"a034,Und hr123sdfER""st1"" 'str2''mit''apo''s' "
    call tstEnd t

/*
$=/tstScan.2/
    ### start tst tstScan.2 ###########################################
    scan src a034,Und hr123sdfER"st1" 'str2''mit''apo''s' .
    scan n tok 4: a034 key  val .
    scan , tok 1: , key  val .
    scan n tok 3: Und key  val .
    scan b tok 1:   key  val .
    scan n tok 10: hr123sdfER key  val .
    scan " tok 5: "st1" key  val st1
    scan b tok 1:   key  val st1
    scan ' tok 19: 'str2''mit''apo''s' key  val str2'mit'apo's
    scan b tok 1:   key  val str2'mit'apo's
$/tstScan.2/ */
    call tst t, 'tstScan.2'
    call tstScan1 'ndsb1' ,
        ,"a034,Und hr123sdfER""st1"" 'str2''mit''apo''s' "
    call tstEnd t

/*
$=/tstScan.3/
    ### start tst tstScan.3 ###########################################
    scan src a034,'wie 789abc
    scan n tok 4: a034 key  val .
    scan , tok 1: , key  val .
    *** err: scanErr ending Apostroph missing
    .    e 1: last token ' scanPosition wie 789abc
    .    e 2: pos 7 in string a034,'wie 789abc
    scan w tok 1: w key  val wie 789abc
    scan n tok 2: ie key  val wie 789abc
    scan s tok 1:   key  val wie 789abc
    *** err: scanErr illegal char after number 789
    .    e 1: last token 789 scanPosition abc
    .    e 2: pos 14 in string a034,'wie 789abc
    scan d tok 3: 789 key  val wie 789abc
    scan n tok 3: abc key  val wie 789abc
$/tstScan.3/ */
    call tst t, 'tstScan.3'
    call tstScan1 'nds1' ,
        ,"a034,'wie 789abc"
    call tstEnd t
/*
$=/tstScan.4/
    ### start tst tstScan.4 ###########################################
    scan src litEinsefr 23 sdfER'str1'litZwei "str2""mit quo"s .
    scan l tok 7: litEins key  val .
    scan n tok 3: efr key  val .
    scan b tok 1:   key  val .
    scan d tok 2: 23 key  val .
    scan b tok 1:   key  val .
    scan n tok 5: sdfER key  val .
    scan a tok 6: 'str1' key  val str1
    scan l tok 7: litZwei key  val str1
    scan b tok 1:   key  val str1
    scan q tok 15: "str2""mit quo" key  val str2"mit quo
    scan n tok 1: s key  val str2"mit quo
    scan b tok 1:   key  val str2"mit quo
$/tstScan.4/ */
    call tst t, 'tstScan.4'
    call tstScan1 'l"litEins"l"litZwei"ndbaq1' ,
           ,"litEinsefr 23 sdfER'str1'litZwei ""str2""""mit quo""s "
    call tstEnd t

/*
$=/tstScan.5/
    ### start tst tstScan.5 ###########################################
    scan src  aha q3  =  f ab=cdEf eF='strIng' .
    scan s tok 1:   key  val .
    scan k tok 0:  key aha val def
    scan k tok 1: f key q3 val f
    scan s tok 1:   key q3 val f
    scan k tok 4: cdEf key ab val cdEf
    scan s tok 1:   key ab val cdEf
    scan k tok 8: 'strIng' key eF val strIng
    scan s tok 1:   key eF val strIng
$/tstScan.5/ */
    call tst t, 'tstScan.5'
    call tstScan1 'k1'," aha q3  =  f ab=cdEf eF='strIng' "
    call tstEnd t
    return
endProcedure tstScan

/*--- one single test scan with lines to scan in stem ln ------------*/
tstScan1:
parse arg classs, ln
    call tstOut t, 'scan src' ln
    call scanSrc scanOpt(s), ln
    m.s.key = ''
    m.s.val = ''
    do forever
        x = tstScanType(s, classs)
        if x == '' then
           leave
        call tstOut t, 'scan' x 'tok' length(m.s.tok)':' m.s.tok ,
                  'key' m.s.key 'val' m.s.val
        end
    return
endProcedure tstScan1

tstScanType: procedure expose m.
parse arg s, opt
    cx = 1
    a2 = ''
    res = 0
    do while cx <= length(opt)
        f = substr(opt, cx, 1)
        cx = cx + 1
        if pos(substr(opt, cx, 1), "'""") > 0 then do
            m.tstScanType.src = opt
            m.tstScanType.pos = cx
            call scanString tstScanType
            a2 = m.tstScanType.val
            cx = m.tstScanType.pos
            end
        if      f == 'a' then
            res = scanString(s, "'")
        else if f == 'b' then
            res = scanSpace(s)
        else if f == 'c' then
            res = scanChar(s, a2)
        else if f == 'd' then
            if a2 == 0 then
                res = scanNatIA(s)
            else
                res = scanNat(s)
        else if f == 'k' then
            res = scanKeyValue(s, 'def')
        else if f == 'l' then
            res = scanLit(s, a2)
        else if f == 'q' then
            res = scanString(s, '"')
        else if f == 'v' then
            res = scanVerify(s, a2)
        else if f == 'w' then
            res = scanWord(s)
        else if f == 'y' then
            res = scanVerify(s, a2, 'm')
        if res then
            return f
        end
    return scanType(s)
endProcedure tstScanType

tstScanRead: procedure expose m.
/*
$=/tstScanRead/
    ### start tst tstScanRead #########################################
    name erste
    space
    name Zeile
    nextLine
    nextLine
    space
    name dritte
    space
    name Zeile
    space
    name schluss
$/tstScanRead/ */
    call scanReadIni
    call tst t, 'tstScanRead'
    b = jBuf('erste Zeile  ',,'  dritte Zeile  schluss  ')
    s = jOpen(jReset0(scanRead(b)), m.j.cRead)
    do while \scanEnd(s)
        if scanName(s) then             call tstOut t, 'name' m.s.tok
        else if scanVerify(s, ' ') then call tstOut t, 'space'
        else if scanReadNL(s) then      call tstOut t, 'nextLine'
        else if \scanEnd(s) then        call scanErr s, 'cannot scan'
        end
    call jClose s
    call tstEnd t

/*
$=/tstScanReadMitSpaceLn/
    ### start tst tstScanReadMitSpaceLn ###############################
    name erste
    spaceLn
    name Zeile
    spaceLn
    name dritte
    spaceLn
    name Zeile
    spaceLn
    name schluss
$/tstScanReadMitSpaceLn/ */
    call tst t, 'tstScanReadMitSpaceLn'
    s = scanReadOpen(scanRead(b))
    do forever
        if scanName(s) then         call out 'name' m.s.tok
        else if scanSpace(s) then call out 'spaceLn'
        else if \scanEnd(s) then        call scanErr s, 'cannot scan'
        else                        leave
        end
    call scanReadClose s
    call tstEnd t

/*
$=/tstScanJRead/
    ### start tst tstScanJRead ########################################
    1 jRead n tok erste val .
    2 jRead s tok   val .
    3 jRead n tok Zeile val .
    4 jRead s tok   val .
    5 jRead n tok dritte val .
    6 jRead s tok   val .
    7 jRead n tok Zeile val .
    8 jRead s tok   val .
    9 jRead n tok schluss val .
    10 jRead s tok   val .
    11 jRead 0 tok 1 val 1
    12 jRead s tok   val 1
    13 jRead + tok + val 1
    14 jRead s tok   val 1
    15 jRead 0 tok 2. val 2..
    16 jRead s tok   val 2..
    17 jRead + tok + val 2..
    18 jRead . tok . val 2..
    19 jRead s tok   val 2..
    20 jRead 0 tok +.3 val +.3
    21 jRead 0 tok -45e-3 val -45E-3
    22 jRead s tok   val -45E-3
    23 jRead " tok "a""b" val a"b
    24 jRead s tok   val a"b
    25 jRead ' tok 'c''d' val c'd
    className 1: ScanRes 18: ScanRes
$/tstScanJRead/ */

    call tst t, 'tstScanJRead'
    call jWrite jOpen(b,'>>'), '1  + 2. +. +.3-45e-3 "a""b"' "'c''d'"
    s = jOpen(jReset0(scanRead(jClose(b))), '<')
    do x=1 while jRead(s)
        v = m.s
        call out x 'jRead' m.v.type 'tok' m.v.tok 'val' m.v.val
        v.x = v
        end
    call jClose s
    call out 'className 1:' className(objClass(v.1)),
                    '18:' className(objClass(v.18))
    call tstEnd t
/*
$=/tstScanReadPos/
    ### start tst tstScanReadPos ######################################
    1
    2
    345678
    4
    5678
    4
$/tstScanReadPos/ */
    call tst t, 'tstScanReadPos'
    b = jBuf(1, 2, 345678, 4)
    call scanReadOpen scanReadReset(scanOpt(tstScn), b)
    do while scanNat(scanSkip(tstScn))
         call tstOut t, m.tstScn.tok
         end
    call scanSetPos tstScn, 3 3
    do while scanNat(scanSkip(tstScn))
         call tstOut t, m.tstScn.tok
         end
    call tstEnd t
    return
endProcedure tstScanRead

tstScanUtilInto: procedure expose m.
/*
$=/tstScanUtilIntoL/
TEMPLATE P3
     DSN('DBAF.DA540769.A802A.P00003.BV5I3NRN.REC')
     DISP(OLD,KEEP,KEEP)
TEMPLATE P4
     DSN('DBAF.DA540769.A802A.P00004.BV5I3NTK.REC')
     DISP(OLD,KEEP,KEEP)
LOAD DATA        LOG NO RESUME NO REPLACE COPYDDN(TCOPYD)
           STATISTICS INDEX(ALL) REPORT NO UPDATE ALL
 EBCDIC  CCSID(00500,00000,00000)
 SORTKEYS
  -- ENFORCE NO
  SORTDEVT DISK
  SORTNUM 160
  WORKDDN(TSYUTD,TSOUTD)
  INTO TABLE OA1P.TWB981 PART 1 INDDN TREC134
 WORKDDN(TSYUTS,TSOUTS)
 INTO TABLE "A540769"
   ."TWK802A1"
 PART 00001 INDDN P0
 WHEN(00001:00002) = X'0041'
 ( "DE1"
  POSITION(  00003:00010) DECIMAL
 , "CH2"
  POSITION(  00011:00015) CHAR(00005)
 , "TS3"
  POSITION(  00016:00041) TIMESTAMP EXTERNAL
 , "TI4"
  POSITION(  00042:00049) TIME EXTERNAL
 , "DA5"
  POSITION(  00050:00059) DATE EXTERNAL
 , "IN6"
  POSITION(  00060:00063) INTEGER
 , "RE7"
  POSITION(  00064:00067) FLOAT(21)
 )
 INTO TABLE "A540769"."TWK802A1"
 PART 00002 INDDN P0
 WHEN(00001:00002) = X'0041'
 ( "DE1"
  POSITION(  00003:00010) DECIMAL
 , "CH2"
  POSITION(  00011:00015) CHAR(00005)
 )
 dobido
$/tstScanUtilIntoL/
$=/tstScanUtilInto/
  ### start tst tstScanUtilInto #####################################
  -- 1 scanUtilInto
  . ( "DE1"
  .  POSITION(  00003:00010) DECIMAL
  . , "CH2"
  .  POSITION(  00011:00015) CHAR(00005)
  . , "TS3"
  .  POSITION(  00016:00041) TIMESTAMP EXTERNAL
  . , "TI4"
  .  POSITION(  00042:00049) TIME EXTERNAL
  . , "DA5"
  .  POSITION(  00050:00059) DATE EXTERNAL
  . , "IN6"
  .  POSITION(  00060:00063) INTEGER
  . , "RE7"
  .  POSITION(  00064:00067) FLOAT(21)
  . ) .
  .  -- table OA1P.TWB981 part 00001
  -- 2 scanUtilInto
  . ( "DE1"
  .  POSITION(  00003:00010) DECIMAL
  . , "CH2"
  .  POSITION(  00011:00015) CHAR(00005)
  . ) .
  .  -- table A540769.TWK802A1 part 00002
  -- 3 scanUtilInto
$/tstScanUtilInto/ */

    call scanReadIni
    b = jBuf()
    call mAddst b'.BUF', mapInline('tstScanUtilIntoL')
    call tst t, 'tstScanUtilInto'
    s = jOpen(jReset0(scanUtilOpt(ScanRead(b))), '<')
    do ix=1
        call out '--' ix 'scanUtilInto'
        if \ scanUtilInto(s) then
            leave
        call out '  -- table' m.s.tb 'part' m.s.part
        end
    call tstEnd t
    return
endProcedure tstSCanUtilInto

tstScanWin: procedure expose m.
/*
$=/tstScanWin/
    ### start tst tstScanWin ##########################################
    info 0: last token  scanPosition erste     Zeile                 dr+
    itteZe\npos 1 in line 1: erste     Zeile
    name erste
    spaceNL
    name Zeile
    spaceNL
    name dritteZeeeile
    info 5: last token dritteZeeeile scanPosition    zeile4            +
    .    fuenfueberSechs\npos 1 in line 4:    zeile4
    spaceNL
    name zeile4
    spaceNL
    name fuenfueberSechsUnddSiebenUNDundUndUAcht
    spaceNL
    info 10: last token   scanPosition undZehnueberElfundNochWeiterZwoe+
    lfundim1\npos 9 in line 10:         undZehn
    name undZehnueberElfundNochWeiterZwoelfundim13
    spaceNL
    name Punkt
    infoE 14: last token Punkt scanPosition \natEnd after line 13: im13+
    .      Punkt
$/tstScanWin/ */
    call scanWinIni
    call tst t, 'tstScanWin'
    b = jBuf('?erste     Zeile?',,'?  dritteZeeeile?', '?   zeile4 ',
       ,'?          fuenf?', '?ueberSechsUnddS?', '?iebenUNDundUndU?',
       ,'?Acht           ?', '?               ?', '?        undZehn?',
       ,'?ueberElfundNoch?', '?WeiterZwoelfund?', '?im13      Punkt?')
    s = jOpen(jReset0(scanWin(b, '15@2')), m.j.cRead)
    call tstOut t, 'info 0:' scanInfo(s)
    do sx=1 while \scanEnd(s)
        if scanSpace(s) then call tstOut t, 'spaceNL'
        else if scanName(s) then        call tstOut t, 'name' m.s.tok
        else if \scanEnd(s) then        call scanErr s, 'cannot scan'
        if sx // 5 = 0 then
            call tstOut t, 'info' sx':' scanInfo(s)
        end
    call tstOut t, 'infoE' sx':' scanInfo(s)
    call tstEnd t

/*
$=/tstScanWinRead/
    ### start tst tstScanWinRead ######################################
    info 0: last token  scanPosition erste     Zeile                z3 +
    com Ze\npos 1 in line 1: erste     Zeile
    name erste
    spaceNL
    name Zeile
    spaceNL
    name z3
    info 5: last token z3 scanPosition  com Zeeeile z4 come4          f+
    uenf\npos 4 in line 3:  z3 com Zeeeile
    spaceNL
    name z4
    spaceNL
    name fuenf
    spaceNL
    info 10: last token   scanPosition com    Sechs  com  sieben   comA+
    cht  com\npos 15 in line 5:     fuenf     c
    name com
    spaceNL
    name Sechs
    spaceNL
    name com
    info 15: last token com scanPosition   sieben   comAcht  com com   +
    . com\npos 2 in line 7: m  sieben   com
    spaceNL
    name sieben
    spaceNL
    name Acht
    spaceNL
    info 20: last token   scanPosition ueberElfundNochWeit com elfundim+
    13\npos 1 in line 11: ueberElfundNoch
    name ueberElfundNochWeit
    spaceNL
    name im13
    spaceNL
    name Punkt
    info 25: last token Punkt scanPosition \natEnd after line 13: im13 +
    .     Punkt
    infoE 26: last token Punkt scanPosition \natEnd after line 13: im13+
    .      Punkt
$/tstScanWinRead/ */
    call tst t, 'tstScanWinRead'
    b = jBuf('?erste     Zeile?',,'? z3 com Zeeeile?', '? z4 come4 ',
       ,'?    fuenf     c?', '?om    Sechs  co?', '?m  sieben   com?',
       ,'?Acht  com com  ?', '?  com          ?', '?  com   undZehn?',
       ,'?ueberElfundNoch?', '?Weit com elfund?', '?im13      Punkt?')
    s = jReset0(scanWin(b, '15@2'))
    call scanOpt s, , , 'com'
    call tstOut t, 'info 0:' scanInfo(jOpen(s, m.j.cRead))
    do sx=1 while \scanEnd(s)
        if scanName(s) then        call tstOut t, 'name' m.s.tok
        else if scanSpace(s) then call tstOut t, 'spaceNL'
        else if \scanEnd(s) then        call scanErr s, 'cannot scan'
        if sx // 5 = 0 then
            call tstOut t, 'info' sx':' scanInfo(s)
        end
    call tstOut t, 'infoE' sx':' scanInfo(s)
    call tstEnd t
/*
$=/tstScanWinPos/
    ### start tst tstScanWinPos #######################################
    infoA1 1: last token 1 scanPosition                    2           +
    .        3\npos 2 in line 1: 1
    1
    2
    345678
    4
    infoB1: last token  scanPosition \natEnd after line 4: 4
    infoC1: last token  scanPosition 678              4\npos 4 in line+
    . 3: 345678
    678
    4
    infoA0 1: last token -2 scanPosition          -1         -0      1 +
    .        2\npos 3 in line -2: -2
    -2
    -1
    -0
    1
    2
    345678
    4
    infoB0: last token  scanPosition \natEnd after line 4: 4
    infoC0: last token  scanPosition 5678    4\npos 3 in line 3: 345678
    5678
    4
$/tstScanWinPos/ */
    call tst t, 'tstScanWinPos'
    b = jBuf(1, 2, 345678, 4)
    do ox=1 to 0 by -1
        if ox then
            s = scanWinOpen(scanWinReset(scanOpt(tstScn), b, 20))
        else
            s = scanWinOpen(scanWinReset(scanOpt(tstScn), b, 10),
                ,'-2         -1         -0')
        do nx=1 while scanNum(scanSkip(s))
             if nx = 1 then
                 call tstOut t, 'infoA'ox nx':' scanInfo(s)
             call tstOut t, m.s.tok
             end
        call tstOut t, 'infoB'ox':' scanInfo(s)
        call scanSetPos s, 3 3+ox
        call tstOut t, 'infoC'ox':' scanInfo(s)
        do while scanNat(scanSkip(s))
             call tstOut t, m.s.tok
             end
        call scanClose s
        end
    call tstEnd t
    return
endProcedure tstScanWin

tstScanSqlStmt: procedure expose m.
/*
$=/tstScanSqlStmt/
    ### start tst tstScanSqlStmt ######################################
    cmd1 select   current time                 stamp from s.1
    cmd2 update ";--""'/*"
    cmd3 delete '*/''"' / 3 - 1
    cmd4 terminator test
    cmd5 und so
    cmd6 term: ist
    cmd7 term>  in com nein >
    cmd8 .
$/tstScanSqlStmt/ */
    call pipeIni
    call scanWinIni
    call tst t, 'tstScanSqlStmt'
    b = jBuf('select -- /* c1', ' /* c1 */ current/* c2 " '' ',
       ,'c3"', '  c4   */time', 'stamp-- c5', 'from s.1; /* c6 */ ;' ,
       ,';update ";--""''/*";;       del123',
       , 'ete ''*/''''"'' / 3 - 1  -- c7', '/*c8 */   ' ,
       , ';terminator test; ','terminator|; und--  ', 'so| | |',
       , 'term: --#SET TERMINATOR : oder', 'ist: ',
       , 'term> /*--#SET TERMINATOR > oder', ' */ in com nein >:')
    call scanWinOpen scanSqlStmtOpt(scanWinReset(tstJcat, b, 30), ';')
    call scanSqlOpt tstJcat
    do sx=1 until nx = ''
        nx = scanSqlStmt(tstJCat)
        call tstOut t, 'cmd'sx nx
        end
    call scanReadCLose tstJCat
    call tstEnd t
/*
$=/tstScanSqlStmtRdr/
    ### start tst tstScanSqlStmtRdr ###################################
    cmd1 select   current time                 stamp from s.1
    cmd2 update ";--""'/*"
    cmd3 delete '*/''"' / 3 - 1
    cmd4 terminator test
    cmd5 und so
    cmd6 term: ist
    cmd7 term>  in com nein >
$/tstScanSqlStmtRdr/ */
    call tst t, 'tstScanSqlStmtRdr'
    r = jOpen(ScanSqlStmtRdr(b, 30), '<')
    do sx=1 while jRead(r)
        call tstOut t, 'cmd'sx m.r
        end
    call jClose r
    call tstEnd t
    return
endProcedure tstScanSqlStmt

tstScanSql: procedure expose m.
    call scanWinIni
/*
$=/tstScanSqlId/
    ### start tst tstScanSqlId ########################################
    sqlId ABC
    spaceNL
    sqlId AB__345EF
    spaceNL
$/tstScanSqlId/ */
    call tst t, 'tstScanSqlId'
    b = jBuf('abc  --  kommentar', right('ab_', 72), '_345ef-- kom')
    s = scanOpen(scanSqlReset(tstScn, b))
    do sx=1 while \scanEnd(s)
        if scanSqlID(s) then       call tstOut t, 'sqlId' m.s.val
        else if scanSpace(s) then call tstOut t, 'spaceNL'
        else                            call scanErr s, 'cannot scan'
        end
    call tstEnd t
/*
$=/tstScanSqlDelimited/
    ### start tst tstScanSqlDelimited #################################
    sqlDeId ABC
    spaceNL
    sqlDeId AB_3F
    spaceNL
    sqlDeId abc
    spaceNL
    sqlDeId ab_Ef
    spaceNL
$/tstScanSqlDelimited/ */
    call tst t, 'tstScanSqlDelimited'
    b =jBuf('abc  --  kommentar',,'  -- ',,right('ab_', 72),'3F-- kom',
           , '"abc"  --  ko', ' -- ',,right('"ab_', 72),'Ef"-- kom')
    s = scanOpen(scanSqlReset(tstScn, b))
    do sx=1 while \scanEnd(s)
        if scanSqlDeID(s) then       call tstOut t, 'sqlDeId' m.s.val
        else if scanSpace(s) then call tstOut t, 'spaceNL'
        else                            call scanErr s, 'cannot scan'
        end
    call tstEnd t
/*
$=/tstScanSqlQualified/
    ### start tst tstScanSqlQualified #################################
    sqlQuId ABC 1 ABC
    sqlQuId AB_3F 1 AB_3F
    sqlQuId abc 1 abc
    sqlQuId ab_Ef 1 ab_Ef
    sqlQuId EINS.Zwei.DREI 3 EINS
    sqlQuId vi er.fu  enf 2 vi er
$/tstScanSqlQualified/ */
    call tst t, 'tstScanSqlQualified'
    b =jBuf('abc  --  kommentar',,'  -- ',,right('ab_', 72),'3F-- kom',
           , '"abc"  --  ko', ' -- ',right('"ab_', 72),'Ef"-- kom',
           , 'eins."Zwei', '" -- com', ' . -- com', '  -- com',
           , 'drei -- ko', '"vi er"."fu  enf   " -- co')
    s = scanOpen(scanSqlReset(tstScn, b))
    do sx=1 while \scanEnd(s)
        if scanSqlQuID(s) then
            call tstOut t, 'sqlQuId' m.s.val m.s.val.0 m.s.val.1
        else if scanSpace(s) then call tstOut t, 'spaceNL'
        else                            call scanErr s, 'cannot scan'
        end
    call tstEnd t
/*
$=/tstScanSqlNum/
    ### start tst tstScanSqlNum #######################################
    sqlNum 1
    spaceNL
    sqlNum 2..
    spaceNL
    sqlNum .3
    spaceNL
    sqlNum 4.5
    spaceNL
    sqlNum +6
    spaceNL
    sqlNum +7.03
    spaceNL
    sqlNum -8
    spaceNL
    sqlNum -.9
    spaceNL
    sqlNum 1E2
    spaceNL
    sqlNum -2.E-2
    spaceNL
    sqlNum +.3E+3
    spaceNL
$/tstScanSqlNum/ */
    call tst t, 'tstScanSqlNum'
    b =jBuf('1 2. .3 4.5 +6 + --kom', , ' -- com ', , ' 7.03 -8 -  .9',
             '1e2 - 2.e-2 + .3e+3')
    s = scanOpen(scanSqlReset(tstScn, b))
    do sx=1 while \scanEnd(s)
        if scanSqlNum(s) then
            call tstOut t, 'sqlNum' m.s.val
        else if scanSpace(s) then call tstOut t, 'spaceNL'
        else                            call scanErr s, 'cannot scan'
        end
    call tstEnd t
/*
$=/tstScanSqlNumUnit/
    ### start tst tstScanSqlNumUnit ###################################
    sqlNumUnit 1 KB
    spaceNL
    sqlNumUnit .3 MB
    sqlNumUnit .5
    sqlNumUnit +6.E-5 B
    spaceNL
    sqlNumUnit -7
    char *
    spaceNL
    sqlNumUnit -.8
    char T
    char B
    spaceNL
    *** err: scanErr bad unit TB after +9..
    .    e 1: last token Tb scanPosition .
    .    e 2: pos 41 in line 1: 1 kb .3mB.5 +   6.e-5B -7* -.8 TB + 9.T+
    b
    sqlNumUnit +9..
    spaceNL
$/tstScanSqlNumUnit/ */
    call tst t, 'tstScanSqlNumUnit'
    b = jBuf('1 kb .3mB.5 +   6.e-5B -7* -.8 TB + 9.Tb')
    s = scanOpen(scanSqlReset(tstScn, b))
    do sx=1 while \scanEnd(s)
        if scanSqlNumUnit(s, 0, 'B KB MB') then
            call tstOut t, 'sqlNumUnit' m.s.val
        else if scanSpace(s) then call tstOut t, 'spaceNL'
        else if scanChar(s ,1) then call tstOut t, 'char' m.s.tok
        else call scanErr s, 'cannot scan'
        end
    call tstEnd t
/*
$=/tstScanSqlClass/
    ### start tst tstScanSqlClass #####################################
    i a 1 A
    d "bC" 1 bC
    q d.e 2 D.E
    q f." g".h 3 F. g.H
    s 'ij''kl' 3 ij'kl
    s x'f1f2' 3 12
    s X'f3F4F5' 3 345
    .. . 3 .
    n .0 3 .0
    n 123.4 3 123.4
    n 5 3 5
    i g 1 G
$/tstScanSqlClass/ */
    call tst t, 'tstScanSqlClass'
    b = jBuf('a "bC" d.e f." g".h' "'ij''kl' x'f1f2' X'f3F4F5'" ,
            , '. .0 123.4 5 g')
    h = scanOpen(scanSqlReset(tstScn, b))
    do sx=1 while scanSqlClass(h)
        call tstOut t, m.h.sqlClass m.h.tok m.h.val.0 m.h.val
        end
    call tstEnd t
    return
endProcedure tstScanSql

tstUtc2d: procedure expose m.
/*
$=/tstUtc2d/
    ### start tst tstUtc2d ############################################
    .             ff            255
    .           ffff          65535
    .          10000          65536          65536 = 1 * 16 ** 4
    .          10001          65537
    .         ffffff       16777215
    .        1000000       16777216       16777216 = 1 * 16 ** 6
    .        1000001       16777217
    .        20000FF       33554687
    .      100000000     4294967296     4294967296 = 1 * 16 ** 8
    .      300000000    12884901888    12884901888 = 3 * 16 ** 8
    .      3020000EF    12918456559
$/tstUtc2d/
*/
    numeric digits 33
    call tst t, 'tstUtc2d'
    all = 'ff ffff 10000 10001 ffffff 1000000 1000001 20000FF' ,
           '100000000 300000000 3020000EF'
    do ax = 1 to words(all)
        a = word(all, ax)
        if substr(a, 2) = 0 then
            b = right(left(a, 1) * 16 ** (length(a)-1), 15) ,
              '=' left(a, 1) '* 16 **' (length(a)-1)
        else
            b = ''
        call tstout t, right(a, 15)right(utc2d(x2c(a)), 15)b
        end
    call tstEnd t
    return
endProcedure tstUtc2d
/**** tst: test infrastructure ***************************************/
/*--- test hook -----------------------------------------------------*/
wshHook_T: procedure expose m.
parse arg m, rest
    do wx=1 to words(rest)
        interpret 'call tst'word(rest, wx)
        end
    if wx > 2 then
        call tstTotal
    if wx > 1 then
        return ''
    /* default  test */
    say ii2rzdb(ee)
    say ii2rzdb(eq)
    say ii2rzdb(eq)
    do y = left(date('s'), 4) - 17 to left(date('s'), 4) + 7
        say y timeYear2Y(y) timeY2Year(timeYear2Y(y))
        end
    do y = left(date('s'), 4) - 69 to left(date('s'), 4) + 30
        say y timeYear24(substr(y, 3))
        end
    d = date('s')
    say d 'b' date('b', d , 's')
    say d 'b' date('b', 20150101, 's') 'jul' date('j')
    say d 'l14' date('b', 20150101, 's') - date('b', 20140101, 's')
    say d 'l16' date('b', 20170101, 's') - date('b', 20160101, 's')
    say fUnit('d', 3e7)
    call err tstEnd
    call tstfTst
    call sqlConnect DBAF
    call catColCom 'cmnBatch', 'DSN_PGROUP_TABLE',
                 , 'cmnBatch', 'DSN_PGROUP_TABLE_new'
    call sqlDisConnect
    return ''
endProcedure wshTst

/*--- initialise m as tester with name nm
        use inline input nm as compare lines ------------------------*/
tst: procedure expose m.
parse arg m, nm, cmpSt
    call tstReset m, nm
    m.tst.tests = m.tst.tests+1
    if cmpSt == '' then do
        cmpSt = mCut(t'.CMP', 0)
        call tst4dp cmpSt, mapInline(nm)
        end
    m.m.cmp = cmpSt
    m.m.moreOutOk = 0
    call mAdd mCut(m'.IN', 0), 'tst in line 1 eins ,'    ,
                     , 'tst in line 2 zwei ;   ' ,
                     , 'tst in line 3 drei .schluss.'
    call tstOut m, left('### start tst' nm '', 67, '#')
    call errReset 'hos', 'return tstErrHandler(ggTxt)'
    call sqlRetDef
    m.m.errCleanup = m.err_cleanup
    m.tst_m = m
    if m.tst.ini.j == 1 then do
        m.m.jWriting = 0
        call jOpen jReset(oMutatName(m, 'Tst')), '>'
        m.m.in.jReading = 0
        call jOpen jReset(oMutatName(m'.IN', 'Tst')), '<'
        if m.tst.ini.e \== 1 then do
            m.m.oldJin = m.j.in
            m.m.oldOut = m.j.out
            m.j.in = m'.IN'
            m.j.out = m
            end
        else do
            if m.pipe.0 <> 2 then
                call tstErr m, 'm.pipe.0' m.pipe.0 '<> 2'
            call pipe '+Ff', m , m'.IN'
            end
        end
    if m.tstTime_ini \== 1 then do
       m.tstTime_ini = 1
        m.tstTimeNm = ''
        aE = right(time('L'), 20, 0)
        m.tstTimeLaEla = substr(aE, 12) ,
            + 60 * substr(aE, 9, 2) + 3600 * left(aE, 7)
        m.tstTimeLaCpu = sysvar('syscpu')
        end
    return m
endProcedure tst

tstEnd: procedure expose m.
parse arg m, opt opt2
    cmp = m.m.cmp
    m.m.jReading = 0
    m.m.jWriting = 0
    drop m.tst_m
    if m.tst.ini.j == 1 then do
        m.m.jReading = 0
        m.m.jWriting = 0
           if m.tst.ini.e \== 1 then do
            m.j.in = m.m.oldJin
            m.j.out = m.m.oldOut
            end
        else do
            if m.j.in \== m'.IN' | m.j.out \== m then
                call tstErr m, m.j.in '\==' m '|' m.j.out '\==' m
            call pipe '-'
            if m.pipe.0 <> 2 then
                call tstErr m, 'm.pipe.0' m.pipe.0 '<> 2'
            end
        end
    if m.m.err = 0 then
        if m.m.errCleanup \= m.err_cleanup then
            call tstErr m, 'err_cleanup' m.err_cleanup '<> old',
                        m.m.errCleanup
    if m.m.out.0 \= m.cmp.0 & \ (m.m.moreOutOk,
            &  m.m.out.0 > m.cmp.0) then do
        call tstErr m, 'old' m.cmp.0 'lines \= new' m.m.out.0
        do nx = m.m.out.0 + 1 to min(m.m.out.0+10, m.cmp.0)
            say 'old -  ' m.cmp.nx
            end
        end
    call errReset 'h'
    m.tst.act = ''
    soll = 0
    if opt = 'err' then do
        soll = opt2
        if m.m.err \= soll then
            call err soll 'errors expected, but got' m.m.err
        end
    if m.m.err \= soll then do
        say 'new lines:' (m.m.out.0 - 1)
           call tst2dpSay m.m.name, m'.OUT', 68
        end
    say left('###' m.m.name 'end with' m.m.err 'errors ', 67, '#')

    if 1 & m.m.err \= soll then
        call err 'dying because of' m.m.err 'errors'
    m.m.trans.0 = m.m.trans.old
    nm = strip(m.m.name)
    aE = right(time('L'), 20, 0)
    aE = substr(aE, 12) + 60 * substr(aE, 9, 2) + 3600 * left(aE, 7)
    aC = sysvar('syscpu')
    if aE < m.tstTimeLaEla |  aC < m.tstTimeLaCpu then
        call err 'backward time/cpu'
    if m.tstTime.nm \== 1 then do
        m.tstTime.nm = 1
        m.tstTimeNm = m.tstTimeNm nm
        m.tstTime.nm.count = 1
        m.tstTime.nm.ela   = aE - m.tstTimeLaEla
        m.tstTime.nm.cpu   = aC - m.tstTimeLaCpu
        end
    else do
        m.tstTime.nm.count = m.tstTime.nm.count + 1
        m.tstTime.nm.ela   = m.tstTime.nm.ela   +  aE - m.tstTimeLaEla
        m.tstTime.nm.cpu   = m.tstTime.nm.cpu   +  aC - m.tstTimeLaCpu
        end
 /* say left('%%%time' nm, 20) ,
        f('%7.3i %9.3i', aC - m.tstTimeLaCpu , aE - m.tstTimeLaEla) ,
        f('cum %6i %7.3i %9.3i', m.tstTime.nm.count, m.tstTime.nm.cpu,
                                                 , m.tstTime.nm.ela) */
    m.tstTimeLaEla = aE
    m.tstTimeLaCpu = aC
    return
endProcedure tstEnd

tstTimeTot: procedure expose m.
      tCnt = 0
      tCpu = 0
      tEla = 0
      say 'tstTimeTotal'
      do tx=1 to words(m.tstTimeNm)
         nm = word(m.tstTimeNm, tx)
         say left(nm, 12) f('%6i %7.3i %9.3i', m.tstTime.nm.count,
                           , m.tstTime.nm.cpu, m.tstTime.nm.ela)

         tCnt = tCnt + m.tstTime.nm.count
         tCpu = tCpu + m.tstTime.nm.cpu
         tEla = tEla + m.tstTime.nm.ela
         end
     say left('total', 12) ,
          f('%6i %7.3i %9.3i', tCnt, tCpu, tEla)
      return
endProcedre tstTimeTot

tstReset: procedure expose m.
parse arg m, nm
    call tstIni
    m.m.name = nm
    m.m.inIx  = 0
    m.m.out.0 = 0
    m.m.err   = 0
    m.err.count = 0
    m.tst.act = m
    if \ datatype(m.m.trans.0, 'n') then
        m.m.trans.0 = 0
    m.m.trans.old = m.m.trans.0
    return
endProcedure tstReset

/*--- tstIni: global initialization ---------------------------------*/
tstIni: procedure expose m.
    if m.tst.ini \== 1 then do
        m.tst.ini = 1
        call mapIni
        m.tst.err = 0
        m.tst.trc = 0
        m.tst.errNames = ''
        m.tst.tests = 0
        m.tst.act = ''
        m.tst_csmRz   = 'RZZ'
        m.tst_csmDb   = 'DE0G'
        m.tst_csmRzDb = m.tst_csmRz'/'m.tst_csmDb
        m.tst_csmServer = 'CHROI00ZDE0G'
        m.tst_long = 0
        end
    if m.tst.ini.j \== 1 & m.j.ini == 1 then do
        m.tst.ini.j = 1
          call classNew 'n Tst u JRW', 'm',
             , "jOpen",
             , "jRead if \ tstRead(m, rStem) then return 0",
             , "jWrite call tstWriteBuf m, wStem"
        end
    if m.tst.ini.e \== 1 & m.pipe_ini == 1 then do
        m.tst.ini.e = 1
        end
    return
endProcedure tstIni

tst2dp: procedure expose m.
parse arg st, dp, ml
    dx = m.dp.0
    do sx=1 to m.st.0
        li = m.st.sx
        cx = 1
        do until cx > length(li)
            c = substr(li, cx, 1)
            ou = left('.', strip(c) == '' | pos(c, '.+') > 0)
            ex = min(length(li),cx+ml-length(ou)-2)
            ou = ou || substr(li, cx, ex+1-cx)
            dx = dx + 1
            c = right(ou, 1)
            if ex < length(li) then
                m.dp.dx = ou || '+'
            else if strip(c) == '' | pos(c, '.+') > 0 then
                m.dp.dx = ou || '.'
            else
                m.dp.dx = ou
            cx = ex +1
            end
        end
    m.dp.0 = dx
    return
endProcedure tst2dp

tst2dpSay: procedure expose m.
parse arg name, st, ml
    say '$=/'name'/'
    call tst2dp st, mCut('TST.TMP', 0), 68
    do nx=1 to m.tst.tmp.0
           say '   ' m.tst.tmp.nx
           end
     say '$/'name'/'
return tst2dpSay

tst4dp: procedure expose m.
parse arg st, dp
    sx = m.st.0
    inData = 0
    data = ''
    do dx=1 to m.dp.0
        li = strip(m.dp.dx)
        if pos(left(li, 1), '.+') > 0 then
         li = substr(li, 2)
        if right(li, 1) == '+' then do
            inData = 1
            data = data || left(li, length(li)-1)
            iterate
            end
        if right(li, 1) == '.' then
            li = left(li, length(li)-1)
        sx = sx + 1
        m.st.sx = repAll(data || li, '$ä', '/*', '$ö', '*/')
        inData = 0
        data = ''
        end
    m.st.0 = sx
    if inData then
        call err 'end inData'
    return
endProcedure tst4dp

/*--- write to test: say lines and compare them ---------------------*/
tstOut: procedure expose m.
parse arg m, arg
    do tx=m.m.trans.0 by -1 to 1
        arg = repAll(arg, word(m.m.trans.tx, 1),
            , subword(m.m.trans.tx, 2))
        end
    arg = repAll(arg, 'in' m.myWsh':', 'in wsM:')
    call mAdd m'.OUT', arg
    nx = m.m.out.0
    cmp = m.m.cmp
    c = m.cmp.nx
    if nx > m.cmp.0 then do
        if nx = m.cmp.0+1 & \ m.m.moreOutOK then
            call tstErr m, 'more new Lines' nx
        end
    else if c \== arg & c \== '%%%' then do
        do cx=1 to min(length(c), length(arg)) ,
             while substr(c, cx, 1) == substr(arg, cx, 1)
             end
         msg = 'old line' nx '<> new overnext, firstDiff' cx',',
                 'len old' length(c)', new' length(arg)

        if cx > 10 then
            msg = overlay('|', msg, cx-10)
        call tstErr m, msg
        say c
        end
    say arg
    return 0
endProcedure tstOut

tstWriteBuf: procedure expose m.
parse arg m, wStem
     if wStem == m'.BUF' then do
         xStem = mAddSt(mCut(wStem'_tstWriteXStem', 0), wStem)
         m.wStem.0 = 0  /* attention avoid infinite recursion | */
         end
     else
         xStem = wStem
     do wx=1 to m.xStem.0
         call tstWrite m, m.xStem.wx
         end
     return
endProcedure tstWriteBuf

tstWrite: procedure expose m.
parse arg m, var
    cl = objClass(var)
    if cl == m.class_N then do
        call tstOut m, 'tstR: @ obj null'
        end
    else if cl == m.class_S then do
        call tstOut m, var
        end
    else if abbrev(var, m.o_escW) then do
        call tstOut m, o2String(var)
        end
    else if cl == m.class_V then do
        call tstOut m, m.var
        end
    else if oKindOf(var, 'JRW') then do
        call tstOut m, 'tstWriteO kindOf JRW jWriteNow begin <<<'
        call jWriteNow m, var
        call tstOut m, 'tstWriteO kindOf JRW jWriteNow end   >>>'
        end
    else if oKindOf(var, 'ORun') then do
        call tstOut m, 'tstWriteO kindOf ORun oRun begin <<<'
        call oRun var
        call tstOut m, 'tstWriteO kindOf ORun oRun end   >>>'
        end
    else do
        call tstTransOC m, var
        call classOut , var, 'tstR: '
        end
    return
endProcedure tstWrite

tstTransOC: procedure expose m.
parse arg m, var
    cl = objClass(var)
    if cl == m.class_N | cl == m.class_S | cl == m.class_W then
        return
    c1 = className(cl)
    vF = 0
    do tx=m.m.trans.0 by -1 to 1 until vF & c1 == ''
        if word(m.m.trans.tx, 1) == var then
            vF = 1
        if word(m.m.trans.tx, 1) == c1 then
            c1 = ''
        end
    if \ vF then
        call mAdd M'.TRANS', var 'tstWriteoV' ||(m.m.trans.0+1)
    if c1 == '' then nop
    else if m.cl.name == '' then
        call mAdd M'.TRANS', c1 'class*' ||(m.m.trans.0+1)
    else if m.cl.name \== m.cl.met then
        call mAdd M'.TRANS', c1 m.cl.met ||(m.m.trans.0+1)
    return
endProcedure tstTransOC

/*--- translate the tst_csm* variables ------------------------------*/
tstTransCsm: procedure expose m.
parse arg t
    say 'csm to' m.tst_csmRzDb m.tst_csmServer
    call mAdd t.trans, m.tst_csmRZ     '<csmRZ>' ,
                     , m.tst_csmDb     '<csmDB>' ,
                     , m.tst_csmServer '<csmServer>'
    s2 = iirz2sys(m.tst_csmRz)
    do sx=0 to 9
        call mAdd t.trans, s2 || sx '<csmSys*>'
        end
    return
 endProcedure tstTransCsm

tstRead: procedure expose m.
parse arg mP, rStem
    if right(mP, 3) \== '.IN' then
        call err 'tstRead bad m' mP
    m = left(mP, length(mP)-3)
    ix = m.m.inIx + 1
    m.m.inIx = ix
    m.rStem.0 = ix <= m.mP.0
    m.rStem.1 = m.mP.ix
    if ix <= m.m.in.0 then
        call tstOut m, '#jIn' ix'#' m.m.in.ix
    else
        call tstOut m, '#jIn eof' ix'#'
    return m.rStem.0
endProcedure tstRead

tstFilename: procedure expose m.
parse arg suf, opt
    if m.err_os == 'TSO' then do
        parse value dsnCsmSys(suf) with sys '/' suf
        dsn = dsn2jcl('~tmp.tst.'suf)
        if sys \== '*' then
            dsn = sys'/'dsn
        if opt = 'r' then do
            if dsnExists(dsn) then
                call dsnDel dsn
            do fx=1 to dsnList(tstFileName, dsn)
                call dsnDel m.tstFileName.fx
                end
            end
        return dsn
        end
    else if m.err_os == 'LINUX' then do
        if abbrev(suf, '/') then
            fn = suf
        else
            fn = .Stream%%new('~/tmp/tst/'suf)%%qualify /* full path */
        cx = lastPos('/', fn)
        if cx > 0 then do
            dir = left(fn, cx-1)
            if \sysIsFileDirectory(dir) then
                call adrSh "mkdir -p" dir
            if \sysIsFileDirectory(dir) then
                call err 'tstFileName could not create dir' dir
            end
        if opt \= 'r' then
            nop
        else if sysIsFile(fn) then
            call sysFileDelete fn
        else if sysIsFileDirectory(fn) then
            call adrSh 'rm -r' fn
        return fn
        end
    else
        call err 'tstFilename does not implement os' m.err_os
endProcedure tstFilename

/*--- say total errors and fail if not zero -------------------------*/
tstTotal: procedure expose m.
    say '######'
 /* say '###### astStatsTotals'
    do sx=1 to words(m.comp_astStats)
        k = word(m.comp_astStats, sx)
        say f('%5c %7i %7i %7i', k, m.comp_astStats.k,
                , m.comp_astStatT.k, m.comp_astStat1.k)
        end
    say '######'    */
    say '######' m.tst.tests 'tests with' ,
                 m.tst.err 'errors in' m.tst.errNames
    say '######'
    say '######'
    if m.tst.err \== 0 then
        call err m.tst.err 'errors total'
    return
endProcedure tstTotal

/*--- test err: message, count it and continue ----------------------*/
tstErr: procedure expose m.
parse arg m, msg
    say '### error' msg
    m.m.err = m.m.err + 1
    m.tst.err = m.tst.err + 1
    nm = m.m.name
    if wordPos(nm, m.tst.errNames) < 1 then
        m.tst.errNames = m.tst.errNames nm
    return 0
endProcedure tstErr

/*--- tstErrHandler: intercept errors -------------------------------*/
tstErrHandler: procedure expose m.
parse arg ggTxt
    m = m.tst.act
    if m == '' then
        call err ggTxt
    m.err.count = m.err.count + 1
    call splitNl err, 0, errMsg(' }'ggTxt)
    call tstOut m.tst.act, '*** err:' m.err.1
    do x=2 to m.err.0
        call tstOut m, '    e' (x-1)':' m.err.x
        end
    return 0
endSubroutine tstErrHandler

tstTrc: procedure expose m.
parse arg msg
    m.tst.trc = m.tst.trc + 1
    say 'tstTrc' m.tst.trc msg
    return m.tst.trc
endProcedure tstTrc

/*--- tstData -------------------------------------------------------*/
tstData: procedure expose m.
parse arg ty 2 le 'n' nu, l, r, num
    abs = abs(num)
    if nu \== '' then do
        if abs // 5 = 0 then
            return 'null' || (abs % 5 // nu + 1)
        end
    if ty = 'c' then do
        if le = '' then
            le = 8
        le = abs // le + 1
        if r = '' then
            r = '+'
        return left(l || num || r, le, right(r, 1))
        end
    if pos(ty, 'ief') < 1 then
        call err 'bad type' ty
    nn = abs
    if abbrev(num, '-') | abbrev(num, '+') then
        parse var num si 2 nn
    else
        si = ''
    if ty == 'e' then
        ex = 'e' || left('-', abs // 2) || (abs // 15)
    else
        ex = ''
    if le \== '' then
        nn = right(nn, abs // max(1, le - length(si||ex)) + 1, 1)
    if ty \== 'i' & (abs // 4) \= 0 & length(nn) > 1 then
            nn = overlay('.', nn, length(nn) - abs // length(nn))
    return si || nn || ex
endProcedure tstData

tstDataClassFo: procedure expose m.
parse arg flds
    ty = ''
    do fx=1 by 2 to words(flds)
        if word(flds, fx) = '.' then
            ty = ty', v'
        else
            ty = ty', f' word(flds, fx) 'v'
        end
    t = classNew('n* tstData u' substr(ty, 2))
    fo = oNew(m.t.name)
    ff = oFldD(fo)
    do fx=1 to m.ff.0
        f = fo || m.ff.fx
        m.f = word(flds, 2*fx)
        end
    return fo
endProcedure tstDataClassFo

tstDataClassOut: procedure expose m.
parse arg flds, f, t
    fo = tstDataClassFo(flds)
    ff = oFldD(fo)
    do x=f to t
        o = oCopy(fo)
        do fx=1 to m.ff.0
            f = o || m.ff.fx
            m.f = tstData(m.f, substr(m.ff.fx, 2),
                  , '+'substr(m.ff.fx,2)'+', x)
            end
        call out o
        end
    return
endProcedure tstDataClassOut
/* copy tstAll end  **************************************************/