lint.lua revision 1.1
11.1Srillig#! /usr/bin/lua
21.1Srillig-- $NetBSD: lint.lua,v 1.1 2021/02/12 20:41:37 rillig Exp $
31.1Srillig
41.1Srillig--[[
51.1Srillig
61.1Srilligusage: lua ./lint.lua
71.1Srillig
81.1SrilligCheck that the boilerplate code does not contain unintended
91.1Srilliginconsistencies.
101.1Srillig
111.1Srillig]]
121.1Srillig
131.1Srillig
141.1Srilliglocal function load_lines(fname)
151.1Srillig  local lines = {}
161.1Srillig
171.1Srillig  local f = assert(io.open(fname, "r"))
181.1Srillig  for line in f:lines() do
191.1Srillig    table.insert(lines, line)
201.1Srillig  end
211.1Srillig
221.1Srillig  f:close()
231.1Srillig
241.1Srillig  return lines
251.1Srilligend
261.1Srillig
271.1Srillig
281.1Srilliglocal function new_errors()
291.1Srillig  local errors = {}
301.1Srillig  errors.add = function(self, fmt, ...)
311.1Srillig    table.insert(self, string.format(fmt, ...))
321.1Srillig  end
331.1Srillig  errors.print = function(self)
341.1Srillig    for _, msg in ipairs(self) do
351.1Srillig      print(msg)
361.1Srillig    end
371.1Srillig  end
381.1Srillig  return errors
391.1Srilligend
401.1Srillig
411.1Srillig
421.1Srilliglocal function num(s)
431.1Srillig  if s == nil then return nil end
441.1Srillig  return tonumber(s)
451.1Srilligend
461.1Srillig
471.1Srillig
481.1Srillig-- After each macro ARGC, there must be the corresponding macros for ARG.
491.1Srilliglocal function check_args(errors)
501.1Srillig  local fname = "curses_commands.c"
511.1Srillig  local lines = load_lines(fname)
521.1Srillig  local argi, argc
531.1Srillig
541.1Srillig  for lineno, line in ipairs(lines) do
551.1Srillig
561.1Srillig    local c = num(line:match("^\tARGC%((%d)"))
571.1Srillig    if c ~= nil and c > 0 then
581.1Srillig      argc, argi = c, 0
591.1Srillig    end
601.1Srillig
611.1Srillig    local i = num(line:match("^\tARG_[%w_]+%((%d+)"))
621.1Srillig    if i ~= nil and argi == nil then
631.1Srillig      errors:add("%s:%d: ARG without preceding ARGC", fname, lineno)
641.1Srillig    end
651.1Srillig
661.1Srillig    if i == nil and argi ~= nil and c == nil then
671.1Srillig      errors:add("%s:%d: expecting ARG %d, got %s", fname, lineno, argi, line)
681.1Srillig      argc, argi = nil, nil
691.1Srillig    end
701.1Srillig
711.1Srillig    if i ~= nil and argi ~= nil and i ~= argi then
721.1Srillig      errors:add("%s:%d: expecting ARG %d, not %d", fname, lineno, argi, i)
731.1Srillig      argi = i
741.1Srillig    end
751.1Srillig
761.1Srillig    if i ~= nil and argi ~= nil and i == argi then
771.1Srillig      argi = argi + 1
781.1Srillig      if argi == argc then
791.1Srillig        argc, argi = nil, nil
801.1Srillig      end
811.1Srillig    end
821.1Srillig  end
831.1Srilligend
841.1Srillig
851.1Srillig
861.1Srilliglocal function check_file(fname, msgs)
871.1Srillig  local errors = collect_errors(fname, msgs)
881.1Srillig  for _, err in ipairs(errors) do
891.1Srillig    print(err)
901.1Srillig  end
911.1Srillig  return #errors == 0
921.1Srilligend
931.1Srillig
941.1Srillig
951.1Srilliglocal function main(arg)
961.1Srillig  local errors = new_errors()
971.1Srillig  check_args(errors)
981.1Srillig  errors:print()
991.1Srillig  return #errors == 0
1001.1Srilligend
1011.1Srillig
1021.1Srillig
1031.1Srilligos.exit(main(arg))
104