xref: /netbsd-src/usr.bin/xlint/lint2/check-msgs.lua (revision 5827310fa54d5b9ae500de221a6d494531270fee)
1#! /usr/bin/lua
2-- $NetBSD: check-msgs.lua,v 1.3 2024/11/30 18:17:11 rillig Exp $
3
4--[[
5
6usage: lua ./check-msgs.lua *.c
7
8Check that the message text in the comments of the C source code matches the
9actual user-visible message text in msg.c.
10
11]]
12
13
14local 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
28end
29
30
31local had_errors = false
32---@param fmt string
33function print_error(fmt, ...)
34  print(fmt:format(...))
35  had_errors = true
36end
37
38
39local 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)
63end
64
65
66local 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()
89end
90
91
92local function main(arg)
93  local msgs = load_messages("msg.c")
94  for _, fname in ipairs(arg) do
95    check_file(fname, msgs)
96  end
97end
98
99main(arg)
100os.exit(not had_errors)
101