Lua4z
A binary distribution of Lua for z/OS, with batteries
-- PDS directory iterator.
--
-- Uses Lua coroutines to create a PDS directory iterator.
--
-- Usage:
--
--   local pdsdir = require "pdsdir"
--   for member in pdsdir("'MY.PDS'") do print(member) end

local struct  = require "struct"
local str = require "pl.stringx"

local unpack = struct.unpack
local x = string.x2c
printf = function(...)  return io.write(string.format(...)) end

local function pds_dir_iterator(dsname)
  local EOF = x'FFFFFFFFFFFFFFFF' -- end of directory marker
  local endOfList = false

  -- for each directory block in the PDS
  local pds = assert(io.open(dsname, "rb"))
  repeat
    local rec = pds:read(256) -- read a directory block
    if not rec then break end
    local size, index = unpack("H",rec) -- size of the block
    -- for each directory entry in the block
    while index < size do
      local member, ttr, info, userData
      -- unpack the directory entry
      member, ttr, info, index = unpack("c8I3I1",rec, index)
      if member == EOF then -- end of directory
        endOfList = true; break
      end
      local dataSize = bit32.band(info, 0x1F) * 2 -- size of user data
      if dataSize > 0 then
        userData, index = unpack("c"..dataSize, rec, index)
      end
      -- return the member name
      coroutine.yield(str.rtrim(member))
    end
  until endOfList
end

-- return the PDS directory iterator
return function (dsname)
  return coroutine.wrap(function () pds_dir_iterator(dsname) end)
end