check-msgs.lua revision 1.5 1 1.1 rillig #! /usr/bin/lua
2 1.5 rillig -- $NetBSD: check-msgs.lua,v 1.5 2021/01/02 01:12:38 rillig Exp $
3 1.1 rillig
4 1.1 rillig --[[
5 1.1 rillig
6 1.5 rillig usage: lua ./check-msgs.lua *.c
7 1.1 rillig
8 1.5 rillig Check that the message text in the comments of the C source code matches the
9 1.5 rillig actual user-visible message text in err.c.
10 1.1 rillig
11 1.1 rillig ]]
12 1.1 rillig
13 1.1 rillig
14 1.1 rillig local function load_messages(fname)
15 1.1 rillig local msgs = {}
16 1.1 rillig
17 1.1 rillig local f = assert(io.open(fname, "r"))
18 1.1 rillig for line in f:lines() do
19 1.1 rillig local msg, id = line:match("%s*\"(.+)\",%s*/%*%s*(%d+)%s*%*/$")
20 1.1 rillig if msg ~= nil then
21 1.1 rillig msgs[tonumber(id)] = msg
22 1.1 rillig end
23 1.1 rillig end
24 1.1 rillig
25 1.1 rillig f:close()
26 1.1 rillig
27 1.1 rillig return msgs
28 1.1 rillig end
29 1.1 rillig
30 1.1 rillig
31 1.1 rillig local function check_message(fname, lineno, id, comment, msgs, errors)
32 1.1 rillig local msg = msgs[id]
33 1.1 rillig
34 1.1 rillig if msg == nil then
35 1.1 rillig errors:add("%s:%d: id=%d not found", fname, lineno, id)
36 1.1 rillig return
37 1.1 rillig end
38 1.1 rillig
39 1.2 rillig msg = string.gsub(msg, "/%*", "**")
40 1.2 rillig msg = string.gsub(msg, "%*/", "**")
41 1.3 rillig msg = string.gsub(msg, "\\(.)", "%1")
42 1.5 rillig
43 1.2 rillig comment = string.gsub(comment, "arg%.", "argument")
44 1.2 rillig comment = string.gsub(comment, "bitop%.", "bitwise operation")
45 1.2 rillig comment = string.gsub(comment, "comb%.", "combination")
46 1.2 rillig comment = string.gsub(comment, "conv%.", "conversion")
47 1.2 rillig comment = string.gsub(comment, "decl%.", "declaration")
48 1.2 rillig comment = string.gsub(comment, "defn%.", "definition")
49 1.4 rillig comment = string.gsub(comment, "des%.s", "designators")
50 1.2 rillig comment = string.gsub(comment, "expr%.", "expression")
51 1.2 rillig comment = string.gsub(comment, "func%.", "function")
52 1.2 rillig comment = string.gsub(comment, "incomp%.", "incompatible")
53 1.2 rillig comment = string.gsub(comment, "init%.", "initialize")
54 1.2 rillig comment = string.gsub(comment, "param%.", "parameter")
55 1.3 rillig comment = string.gsub(comment, "req%.", "requires")
56 1.2 rillig comment = string.gsub(comment, "poss%.", "possibly")
57 1.2 rillig comment = string.gsub(comment, "trad%.", "traditional")
58 1.2 rillig
59 1.1 rillig if comment == msg then
60 1.1 rillig return
61 1.1 rillig end
62 1.1 rillig
63 1.2 rillig local prefix = comment:match("^(.-)%s*%.%.%.$")
64 1.2 rillig if prefix ~= nil and msg:find(prefix, 1, 1) == 1 then
65 1.1 rillig return
66 1.1 rillig end
67 1.1 rillig
68 1.1 rillig errors:add("%s:%d: id=%-3d msg=%-40s comment=%s",
69 1.1 rillig fname, lineno, id, msg, comment)
70 1.1 rillig end
71 1.1 rillig
72 1.1 rillig
73 1.1 rillig local function collect_errors(fname, msgs)
74 1.1 rillig local errors = {}
75 1.1 rillig errors.add = function(self, fmt, ...)
76 1.1 rillig table.insert(self, string.format(fmt, ...))
77 1.1 rillig end
78 1.1 rillig local f = assert(io.open(fname, "r"))
79 1.1 rillig local lineno = 0
80 1.1 rillig local prev = ""
81 1.1 rillig for line in f:lines() do
82 1.1 rillig lineno = lineno + 1
83 1.1 rillig
84 1.3 rillig local func, id = line:match("^%s+(%w+)%((%d+)[),]")
85 1.4 rillig id = tonumber(id)
86 1.3 rillig if func == "error" or func == "warning" or func == "c99ism" or
87 1.3 rillig func == "gnuism" or func == "message" then
88 1.2 rillig local comment = prev:match("^%s+/%* (.+) %*/$")
89 1.1 rillig if comment ~= nil then
90 1.4 rillig check_message(fname, lineno, id, comment, msgs, errors)
91 1.4 rillig else
92 1.4 rillig errors:add("%s:%d: missing comment for %d: /* %s */",
93 1.4 rillig fname, lineno, id, msgs[id])
94 1.1 rillig end
95 1.1 rillig end
96 1.1 rillig
97 1.1 rillig prev = line
98 1.1 rillig end
99 1.1 rillig
100 1.1 rillig f:close()
101 1.1 rillig
102 1.1 rillig return errors
103 1.1 rillig end
104 1.1 rillig
105 1.1 rillig
106 1.1 rillig local function check_file(fname, msgs)
107 1.1 rillig local errors = collect_errors(fname, msgs)
108 1.1 rillig for _, err in ipairs(errors) do
109 1.1 rillig print(err)
110 1.1 rillig end
111 1.1 rillig return #errors == 0
112 1.1 rillig end
113 1.1 rillig
114 1.1 rillig
115 1.1 rillig local function main(arg)
116 1.1 rillig local msgs = load_messages("err.c")
117 1.1 rillig local ok = true
118 1.1 rillig for _, fname in ipairs(arg) do
119 1.1 rillig ok = check_file(fname, msgs) and ok
120 1.1 rillig end
121 1.1 rillig return ok
122 1.1 rillig end
123 1.1 rillig
124 1.1 rillig os.exit(main(arg))
125