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