check-msgs.lua revision 1.9 1 1.1 rillig #! /usr/bin/lua
2 1.9 rillig -- $NetBSD: check-msgs.lua,v 1.9 2021/02/28 12:45:47 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.7 rillig msg = msg:gsub("/%*", "**")
40 1.7 rillig msg = msg:gsub("%*/", "**")
41 1.7 rillig msg = msg:gsub("\\(.)", "%1")
42 1.7 rillig
43 1.7 rillig comment = comment:gsub("arg%.", "argument")
44 1.7 rillig comment = comment:gsub("comb%.", "combination")
45 1.7 rillig comment = comment:gsub("conv%.", "conversion")
46 1.7 rillig comment = comment:gsub("decl%.", "declaration")
47 1.7 rillig comment = comment:gsub("defn%.", "definition")
48 1.7 rillig comment = comment:gsub("des%.s", "designators")
49 1.7 rillig comment = comment:gsub("expr%.", "expression")
50 1.7 rillig comment = comment:gsub("func%.", "function")
51 1.7 rillig comment = comment:gsub("incomp%.", "incompatible")
52 1.7 rillig comment = comment:gsub("init%.", "initialize")
53 1.7 rillig comment = comment:gsub("param%.", "parameter")
54 1.7 rillig comment = comment:gsub("req%.", "requires")
55 1.7 rillig comment = comment:gsub("poss%.", "possibly")
56 1.7 rillig comment = comment:gsub("trad%.", "traditional")
57 1.2 rillig
58 1.1 rillig if comment == msg then
59 1.1 rillig return
60 1.1 rillig end
61 1.1 rillig
62 1.2 rillig local prefix = comment:match("^(.-)%s*%.%.%.$")
63 1.2 rillig if prefix ~= nil and msg:find(prefix, 1, 1) == 1 then
64 1.1 rillig return
65 1.1 rillig end
66 1.1 rillig
67 1.1 rillig errors:add("%s:%d: id=%-3d msg=%-40s comment=%s",
68 1.1 rillig fname, lineno, id, msg, comment)
69 1.1 rillig end
70 1.1 rillig
71 1.1 rillig
72 1.1 rillig local function collect_errors(fname, msgs)
73 1.1 rillig local errors = {}
74 1.1 rillig errors.add = function(self, fmt, ...)
75 1.7 rillig table.insert(self, fmt:format(...))
76 1.1 rillig end
77 1.8 rillig
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.8 rillig local function file_contains(filename, text)
115 1.8 rillig local f = assert(io.open(filename, "r"))
116 1.9 rillig local found = f:read("a"):find(text, 1, true)
117 1.8 rillig f:close()
118 1.9 rillig return found
119 1.8 rillig end
120 1.8 rillig
121 1.8 rillig local function check_test_files(msgs)
122 1.8 rillig
123 1.8 rillig local msgids = {}
124 1.8 rillig for msgid, _ in pairs(msgs) do
125 1.8 rillig table.insert(msgids, msgid)
126 1.8 rillig end
127 1.8 rillig table.sort(msgids)
128 1.8 rillig
129 1.8 rillig local testdir = "../../../tests/usr.bin/xlint/lint1"
130 1.8 rillig local ok = true
131 1.8 rillig for _, msgid in ipairs(msgids) do
132 1.8 rillig local msg = msgs[msgid]:gsub("\\(.)", "%1")
133 1.8 rillig local filename = ("%s/msg_%03d.c"):format(testdir, msgid)
134 1.8 rillig if not file_contains(filename, msg) then
135 1.8 rillig ok = false
136 1.8 rillig print(("%s must contain: %s"):format(filename, msg))
137 1.8 rillig end
138 1.8 rillig end
139 1.8 rillig
140 1.8 rillig return ok
141 1.8 rillig end
142 1.1 rillig
143 1.1 rillig local function main(arg)
144 1.1 rillig local msgs = load_messages("err.c")
145 1.1 rillig local ok = true
146 1.1 rillig for _, fname in ipairs(arg) do
147 1.1 rillig ok = check_file(fname, msgs) and ok
148 1.1 rillig end
149 1.8 rillig ok = check_test_files(msgs) and ok
150 1.1 rillig return ok
151 1.1 rillig end
152 1.1 rillig
153 1.7 rillig
154 1.1 rillig os.exit(main(arg))
155