zOs/REXX.O13/POS

/* copy pos begin *****************************************************
StringHandling
    pos*:   several repetitions of pos (from left or right)
    dsn*:   convenience functions using pos* for dataset names
***********************************************************************/
/*--- return the index of rep'th occurrence of needle
          negativ rep are counted from right -------------------------*/
posRep: procedure
parse arg needle, hayStack, rep, start
    if rep > 0 then do
        if start = '' then
            start = 1
        do cc = 1 to rep
             sx = pos(needle, hayStack, start)
             if sx < 1 then
                 return 0
             start = sx + length(needle)
             end
        return sx
        end
    else if rep < 0 then do
        if start = '' then
            start = length(hayStack)
        do cc = 1 to -rep
             sx = lastPos(needle, hayStack, start)
             if sx < 1 then
                 return 0
             start = sx - length(needle)
             end
        return sx
        end
    else
        return 0
endProcedure posRep

/*--- return n'th level (separated by needle, negative from right) ---*/
posLev: procedure
parse arg needle, hayStack, rep, start
    if rep > 1 then do
        sx = posRep(needle, hayStack, rep-1, start)
        if sx < 1 then
            return 0
        return 1+sx
        end
    else if rep < -1 then do
        sx = posRep(needle, hayStack, rep+1, start)
        if sx < 1 then
            return 0
        return 1+lastPos(needle, hayStack, sx-1)
        end
    else if rep ^= -1 then
        return rep     /* for 0 and 1 */
    else if start == '' then   /* pos fails with empty start| */
        return 1 + lastPos(needle, hayStack)
    else
        return 1 + lastPos(needle, hayStack, start)
endProcedure posLev

/*--- return the count of occurrences of needle in heyStack ----------*/
posCount: procedure
parse arg needle, hayStack, start, fin
    if start = '' then
        start = 1
    if fin = '' then
        fin = length(hayStack) + 1 - length(needle)
    cnt = 0
    do forever
        start = pos(needle, haystack, start)
        if start < 1 | start > fin then
             return cnt
        cnt = cnt + 1
        start = start + length(needle)
        end
endProcedure posCount

/*--- concatenate several parts to a dsn -----------------------------*/
dsnApp: procedure
parse arg parts
    dsn = ''
    do wx=1 by 1
        w = word(parts, wx)
        if w = '' then
            leave
        do while w <> ''
            if pos(right(w, 1), "') ") <= 0 then
                leave
            w = left(w, length(w)-1)
            end
        dsn = dsn || w
        end
    if pos('(', dsn) > 0 then
        dsn = dsn')'
    if left(dsn,1) = "'" then
        return "'"strip(dsn, 'b', "'")"'"
    else
        return dsn
endProcedure dsnApp

/*--- set the membername mbr into dsn --------------------------------*/
dsnSetMbr: procedure
parse arg dsn, mbr
     mbr = strip(mbr)
     bx = pos('(', dsn)
     if mbr = '' then do
         if bx < 1 then
             return dsn
         else if left(dsn, 1) = "'" then
             return left(dsn,bx-1)"'"
         else
             return left(dsn,bx-1)
         end
     else do
         if bx < 1 then
             return dsnApp(dsn '('mbr)
         else
             return dsnApp(left(dsn, bx)  mbr)
         end
endProcedure dsnSetMbr

/*--- get the membername from dsn ------------------------------------*/
dsnGetMbr: procedure
parse arg dsn
     lx = pos('(', dsn)
     rx = pos(')', dsn, lx+1)
     if lx < 1 then
         return ''
     else if lx < rx then
         return substr(dsn, lx+1, rx-lx-1)
     else
         return strip(substr(dsn,lx+1), 't', "'")
endProcedure dsnGetMbr

/*--- get the index of the lx'd level of dsn -------------------------*/
dsnPosLev: procedure
parse arg dsn, lx
    sx = posLev('.', dsn, lx)
    if sx ^= 1 then
        return sx
    else
        return 1 + (left(dsn, 1) == "'")
endProcedure dsnPosLev

/*--- get the the lx'd level of dsn ----------------------------------*/
dsnGetLev: procedure
parse arg dsn, lx
    sx = dsnPosLev(dsn, lx)
    if sx < 1 then
        return ''
    ex = pos('.', dsn, sx)
    if ex < 1 then do
         ex = pos('(', dsn, sx)
         if ex < 1 then
             return substr(dsn, sx)
        end
    return substr(dsn, sx, ex-sx)
endProcedure dsnGetLev

/* copy pos end   ****************************************************/