zOs/REXX/WSHCOPY

/* copy wshCopy begin ************************************************/
wshIni: procedure expose m.
    call compIni
    call sqlIni
    call fTabIni
    call csmIni
    return
endProcedure wshIni

/*--- call hooks and/or compile wsh
      finally execute any generated code ----------------------------*/
wshRun: procedure expose m.
parse arg m, spec, inp
    m.m.info = 'compile'
    r = wshHookComp(m, spec, inp)
    m.m.info = 'run'
    if r \== '' then
        call oRun r
    return
endProcedure wshRun

/*--- call hooks, handle $# clauses, compile wsh
      return generated code as ORunner or ''-------------------------*/
wshHookComp: procedure expose m.
parse arg m, spec, inp
    if m == '' then do
        if symbol('m.wsh_new') \== 'VAR' then
            m.wsh_new = 1
        else
            m.wsh_new = m.wsh_new + 1
        m = 'wsh_new'm.wsh_new
        end
    m.m.in   = inp
    m.m.comp = ''
    m.m.kind = '@'
    m.m.out  = ''
    m.m.wshEnd = 0
    run = ''
    rest = strip(spec)
    if abbrev(rest, '$#') then
        rest = strip(substr(rest, 3))
    workDone = 0
    do until m.m.comp \== '' | (workDone & rest = '')
        if pos(left(rest, 1), '<>') > 0 then do
            parse var rest s2 r2
            end
        else do
            workDone = 1
            parse var rest s2 '$#' r2
            end
        run = run wshHook(m, strip(s2), rest)
        rest = strip(r2)
        end
    if m.m.comp \== '' then do
        c = m.m.comp
        s = m.c.scan
        do while \ m.m.wshEnd
             if \ scanLit(s, '$#') then
                     leave
             call scanChar s
             sp2 = m.s.tok
             run = run wshHook(m, sp2, sp2)
             end
        call compEnd c, left(m.m.kind, \ m.m.wshEnd)
        end
    run = space(run, 1)
    if words(run) <= 1 then
        return run
    else
        return oRunner('call oRun' repAll(run, ' ', '; call oRun '))
endProcedure wshHookComp

/*--- compile wsh until eof or unknown syntax -----------------------*/
wshHook: procedure expose m.
parse arg m, spec, specAll
    parse var spec sp1 spR
    if pos(left(sp1, 1), '<>') > 0 then
        return wshHookRedir(m, sp1 spR)
    if verifId(sp1) > 0 | sp1 == '' then
        return wshCompile(m, specAll)
    if wordPos(sp1, 'out end version') <= 0 then do
        cd = "return wshHook_"sp1"(m, '"strip(spR)"')"
     /* say 'interpreting hook' cd */
        interpret cd
        end
    c = m.m.comp
    s = m.c.scan
    if c == '' then
        call err 'wshHook before compiler created:' spec
    else if sp1 == 'out' then do
        m.m.out = scanPos(s)
        m.m.wshEnd = 1
        end
    else if sp1 == 'end' then
        call scanNlUntil s, '$#out'
    else if m.s.tok == 'version' then
        call scanErr s, 'implement version'
    return ''
endProcedure wshHook

/*--- initialize compiler if necessary and compile one unit ---------*/
wshCompile: procedure expose m.
parse arg m, spec
    spec = strip(spec, 'l')
    if m.m.comp == '' then
        call wshIni
    if pos(left(spec, 1), m.comp_chKind'*') > 0 then
        parse var spec m.m.kind 2 spec
    if m.m.comp == '' then do
        c = comp(m.m.in)
        m.m.comp = c
        call compBegin c, spec
        end
    else do
        c = m.m.comp
        call scanBack m.c.scan, spec
        end
    return compile(c, m.m.kind)
endProcedure wshCompile

/*--- redirection hook ----------------------------------------------*/
wshHookRedir: procedure expose m.
parse upper arg m,  op 2 dsn
    call pipeIni
    f = ''
    if op == '<' then
        call pipe '+f', , file(dsn)
    else if op \== '>' then
        call err 'bad op' op 'in wshHookRedir' op || dsn
    else do
        if pos('>', dsn) > 0 then
            parse var dsn f '>' dsn
        else if verify(dsn, '.~/', 'm') > 0 then
            nop
        else if abbrev(dsn, 'E') | abbrev(dsn, 'VV') ,
                                  | abbrev(dsn, 'VF') then
            parse var dsn f 2 dsn
        else
            f = 'E'
        dsn = strip(dsn)
        if dsn \== '' & verify(dsn, '.~/:', 'm') == 0 then
            dsn = '::'dsn
        if f <> '' then
             call pipe '+F', fEdit(dsn, f)
        else
             call pipe '+F', file(dsn)
        end
    m.m.pipeCnt = m.m.pipeCnt + 1
    return ''
endProcedure wshHookRedir
/* copy wshCopy end   ************************************************/