lint.lua revision 1.5
1#! /usr/bin/lua 2-- $NetBSD: lint.lua,v 1.5 2021/06/13 19:41:12 rillig Exp $ 3 4--[[ 5 6usage: lua ./lint.lua 7 8Check that the argument handling code does not contain unintended 9inconsistencies. 10 11]] 12 13---@return string[] 14local function load_lines(fname) 15 local lines = {} 16 17 local f = assert(io.open(fname, "r")) 18 for line in f:lines() do 19 table.insert(lines, line) 20 end 21 22 f:close() 23 24 return lines 25end 26 27 28local function new_errors() 29 local errors = {} 30 errors.add = function(self, fmt, ...) 31 table.insert(self, string.format(fmt, ...)) 32 end 33 errors.print = function(self) 34 for _, msg in ipairs(self) do 35 print(msg) 36 end 37 end 38 return errors 39end 40 41 42local function num(s) 43 if s == nil then return nil end 44 return tonumber(s) 45end 46 47 48-- After each macro ARGC, there must be the corresponding macros for ARG. 49local function check_args(errors) 50 local fname = "curses_commands.c" 51 local lines = load_lines(fname) 52 local curr_argc, curr_arg ---@type number|nil, number|nil 53 54 for lineno, line in ipairs(lines) do 55 56 local line_argc = num(line:match("^\tARGC%((%d+)")) 57 if line_argc and line_argc > 0 then 58 curr_argc, curr_arg = line_argc, 0 59 goto next 60 end 61 62 local line_arg = line:match("^\tARG_[%w_]+%(") 63 if line_arg and curr_arg then 64 curr_arg = curr_arg + 1 65 if curr_arg == curr_argc then 66 curr_argc, curr_arg = nil, nil 67 end 68 elseif line_arg then 69 errors:add("%s:%d: ARG without preceding ARGC", fname, lineno) 70 elseif curr_arg then 71 errors:add("%s:%d: expecting ARG %d, got %s", 72 fname, lineno, curr_arg, line) 73 curr_argc, curr_arg = nil, nil 74 end 75 76 ::next:: 77 end 78end 79 80 81local function main(arg) 82 local errors = new_errors() 83 check_args(errors) 84 errors:print() 85 return #errors == 0 86end 87 88 89os.exit(main(arg)) 90