Home | History | Annotate | Line # | Download | only in lint2
check-msgs.lua revision 1.3
      1 #! /usr/bin/lua
      2 -- $NetBSD: check-msgs.lua,v 1.3 2024/11/30 18:17:11 rillig Exp $
      3 
      4 --[[
      5 
      6 usage: lua ./check-msgs.lua *.c
      7 
      8 Check that the message text in the comments of the C source code matches the
      9 actual user-visible message text in msg.c.
     10 
     11 ]]
     12 
     13 
     14 local function load_messages(fname)
     15   local msgs = {} ---@type table<number>string
     16 
     17   local f = assert(io.open(fname, "r"))
     18   for line in f:lines() do
     19     local msg, id = line:match("%s*\"(.+)\",%s*// (%d+)$")
     20     if msg ~= nil then
     21       msgs[tonumber(id)] = msg
     22     end
     23   end
     24 
     25   f:close()
     26 
     27   return msgs
     28 end
     29 
     30 
     31 local had_errors = false
     32 ---@param fmt string
     33 function print_error(fmt, ...)
     34   print(fmt:format(...))
     35   had_errors = true
     36 end
     37 
     38 
     39 local function check_message(fname, lineno, id, comment, msgs)
     40   local msg = msgs[id]
     41 
     42   if msg == nil then
     43     print_error("%s:%d: id=%d not found", fname, lineno, id)
     44     return
     45   end
     46 
     47   msg = msg:gsub("/%*", "**")
     48   msg = msg:gsub("%*/", "**")
     49   msg = msg:gsub("\\t", "\\\\t")  -- for lint2
     50   msg = msg:gsub("\\(.)", "%1")
     51 
     52   if comment == msg then
     53     return
     54   end
     55 
     56   local prefix = comment:match("^(.-)%s*%.%.%.$")
     57   if prefix ~= nil and msg:find(prefix, 1, 1) == 1 then
     58     return
     59   end
     60 
     61   print_error("%s:%d:   id=%-3d   msg=%-40s   comment=%s",
     62     fname, lineno, id, msg, comment)
     63 end
     64 
     65 
     66 local function check_file(fname, msgs)
     67   local f = assert(io.open(fname, "r"))
     68   local lineno = 0
     69   local prev = ""
     70   for line in f:lines() do
     71     lineno = lineno + 1
     72 
     73     local func, id = line:match("^%s+(%w+)%((%d+)[),]")
     74     id = tonumber(id)
     75     if func == "msg" then
     76       local comment = prev:match("^%s+/%* (.+) %*/$")
     77       if comment ~= nil then
     78         check_message(fname, lineno, id, comment, msgs)
     79       else
     80         print_error("%s:%d: missing comment for %d: /* %s */",
     81           fname, lineno, id, msgs[id])
     82       end
     83     end
     84 
     85     prev = line
     86   end
     87 
     88   f:close()
     89 end
     90 
     91 
     92 local function main(arg)
     93   local msgs = load_messages("msg.c")
     94   for _, fname in ipairs(arg) do
     95     check_file(fname, msgs)
     96   end
     97 end
     98 
     99 main(arg)
    100 os.exit(not had_errors)
    101