lint.lua revision 1.4
11.1Srillig#! /usr/bin/lua
21.4Srillig-- $NetBSD: lint.lua,v 1.4 2021/06/13 19:25:08 rillig Exp $
31.1Srillig
41.1Srillig--[[
51.1Srillig
61.1Srilligusage: lua ./lint.lua
71.1Srillig
81.4SrilligCheck that the argument handling code does not contain unintended
91.1Srilliginconsistencies.
101.1Srillig
111.1Srillig]]
121.1Srillig
131.3Srillig---@return string[]
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.4Srillig  local curr_argc, curr_arg ---@type number|nil, number|nil
531.1Srillig
541.1Srillig  for lineno, line in ipairs(lines) do
551.1Srillig
561.4Srillig    local line_argc = num(line:match("^\tARGC%((%d)"))
571.4Srillig    local line_arg = line:match("^\tARG_[%w_]+%(")
581.4Srillig
591.4Srillig    if line_argc and line_argc > 0 then
601.4Srillig      curr_argc, curr_arg = line_argc, 0
611.1Srillig    end
621.1Srillig
631.4Srillig    if line_arg and not curr_arg then
641.1Srillig      errors:add("%s:%d: ARG without preceding ARGC", fname, lineno)
651.1Srillig    end
661.1Srillig
671.4Srillig    if not line_arg and curr_arg and not line_argc then
681.4Srillig      errors:add("%s:%d: expecting ARG %d, got %s",
691.4Srillig        fname, lineno, curr_arg, line)
701.4Srillig      curr_argc, curr_arg = nil, nil
711.1Srillig    end
721.1Srillig
731.4Srillig    if line_arg and curr_arg then
741.4Srillig      curr_arg = curr_arg + 1
751.4Srillig      if curr_arg == curr_argc then
761.4Srillig        curr_argc, curr_arg = nil, nil
771.1Srillig      end
781.1Srillig    end
791.1Srillig  end
801.1Srilligend
811.1Srillig
821.1Srillig
831.1Srilliglocal function main(arg)
841.1Srillig  local errors = new_errors()
851.1Srillig  check_args(errors)
861.1Srillig  errors:print()
871.1Srillig  return #errors == 0
881.1Srilligend
891.1Srillig
901.1Srillig
911.1Srilligos.exit(main(arg))
92