tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Consistent layout for file lists in distrib/sets/lists



Hi,

since I regularly add test files to usr.bin/make/unit-tests, I need to
update distrib/sets/lists/tests/mi every few days.  As a side task, I
wrote a beautifier for these file lists.

Would src/distrib/sets be a good place for this utility?  How would it
fit with the existing tools?  I briefly looked at them but couldn't find
anything similar.

I intend to extend the utility with a few command line options, such as
syncing the list with the current state of a directory, automatically
adding new entries and marking deleted entries as obsolete.

Thoughts?
Roland
#! /usr/bin/lua
-- $NetBSD$
--
-- Align the lines of the mi file so that all lines from the same directory
-- have the other fields at the same indentation.  Sort the lines and remove
-- duplicate lines.
--
-- The second field is indented to at least column 56 since only few test
-- filenames are shorter.  This reduces the number of times that the fields
-- "jump" horizontally.

local function read_mi()
  local head = {}
  local entries = {}

  local mi = assert(io.open("mi", "r"))
  local lineno = 0
  for line in mi:lines() do
    lineno = lineno + 1

    local fullname, dirname, basename, category, flags =
      line:match("^((%./%g+)/([^/%s]+))%s+(%g+)%s+(%g+)$")
    if dirname == nil then
      fullname, dirname, basename, category =
        line:match("^((%./%g+)/([^/%s]+))%s+(%g+)$")
    end

    if dirname ~= nil then
      table.insert(entries, {
        fullname = fullname,
        dirname = dirname,
        basename = basename,
        category = category,
        flags = flags
      })

    elseif line:match("^#") then
      table.insert(head, line)

    else
      error(string.format("line %d: %s\n", lineno, line))
    end
  end

  mi:close()

  return head, entries
end

local function roundup(n, mul)
  return (n + mul) // mul * mul
end

local function normalize_mi(entries)

  -- Calculate the maximum pathname length per directory.
  local pathlen = {}
  for _, entry in ipairs(entries) do
    local len = math.max(pathlen[entry.dirname] or 0, #entry.fullname)
    pathlen[entry.dirname] = len
  end

  -- Calculate the field separators for each entry.
  for _, entry in ipairs(entries) do
    local entrylen = roundup(#entry.fullname, 8)
    local grouplen = math.max(56, roundup(pathlen[entry.dirname], 8))
    entry.fullname_sep = string.rep("\t", 1 + (grouplen - entrylen) // 8)
    entry.category_sep = string.rep("\t", (24 + 7 - #entry.category) // 8)
  end

  table.sort(entries, function(a, b)
    if a.fullname ~= b.fullname then return a.fullname < b.fullname end
    if a.category ~= b.category then return a.category < b.category end
    return a.flags < b.flags
  end)
end

-- Write the normalized mi file.
--
-- Duplicate lines are skipped.  This allows to append arbitrary lines to
-- the end of the file and have them cleaned up automatically.
local function write_mi(head, entries)
  local f = assert(io.open("mi.fixed", "w"))

  for _, line in ipairs(head) do
    f:write(line, "\n")
  end

  local prev_line = ""
  for _, entry in ipairs(entries) do
    local fullname = entry.fullname
    local category = entry.fullname_sep .. entry.category
    local flags = entry.flags and entry.category_sep .. entry.flags or ""

    local line = fullname .. category .. flags
    if line ~= prev_line then
      prev_line = line
      f:write(line, "\n")
    end
  end

  f:close()
end

local function format_mi()
  local head, entries = read_mi()
  normalize_mi(entries)
  write_mi(head, entries)
end

format_mi()


Home | Main Index | Thread Index | Old Index