Home | History | Annotate | Line # | Download | only in lint1
check-msgs.lua revision 1.3
      1  1.1  rillig #! /usr/bin/lua
      2  1.3  rillig -- $NetBSD: check-msgs.lua,v 1.3 2021/01/01 01:26:02 rillig Exp $
      3  1.1  rillig 
      4  1.1  rillig --[[
      5  1.1  rillig 
      6  1.1  rillig Check that the message text in the C source matches the actual user-visible
      7  1.1  rillig message text.
      8  1.1  rillig 
      9  1.1  rillig usage: ./check-diagnostics *.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.2  rillig   comment = string.gsub(comment, "arg%.", "argument")
     43  1.2  rillig   comment = string.gsub(comment, "bitop%.", "bitwise operation")
     44  1.2  rillig   comment = string.gsub(comment, "comb%.", "combination")
     45  1.2  rillig   comment = string.gsub(comment, "conv%.", "conversion")
     46  1.2  rillig   comment = string.gsub(comment, "decl%.", "declaration")
     47  1.2  rillig   comment = string.gsub(comment, "defn%.", "definition")
     48  1.2  rillig   comment = string.gsub(comment, "expr%.", "expression")
     49  1.2  rillig   comment = string.gsub(comment, "func%.", "function")
     50  1.2  rillig   comment = string.gsub(comment, "incomp%.", "incompatible")
     51  1.2  rillig   comment = string.gsub(comment, "init%.", "initialize")
     52  1.2  rillig   comment = string.gsub(comment, "param%.", "parameter")
     53  1.3  rillig   comment = string.gsub(comment, "req%.", "requires")
     54  1.2  rillig   comment = string.gsub(comment, "poss%.", "possibly")
     55  1.2  rillig   comment = string.gsub(comment, "trad%.", "traditional")
     56  1.2  rillig 
     57  1.1  rillig   if comment == msg then
     58  1.1  rillig     return
     59  1.1  rillig   end
     60  1.1  rillig 
     61  1.2  rillig   local prefix = comment:match("^(.-)%s*%.%.%.$")
     62  1.2  rillig   if prefix ~= nil and msg:find(prefix, 1, 1) == 1 then
     63  1.1  rillig     return
     64  1.1  rillig   end
     65  1.1  rillig 
     66  1.1  rillig   errors:add("%s:%d:   id=%-3d   msg=%-40s   comment=%s",
     67  1.1  rillig     fname, lineno, id, msg, comment)
     68  1.1  rillig end
     69  1.1  rillig 
     70  1.1  rillig 
     71  1.1  rillig local function collect_errors(fname, msgs)
     72  1.1  rillig   local errors = {}
     73  1.1  rillig   errors.add = function(self, fmt, ...)
     74  1.1  rillig     table.insert(self, string.format(fmt, ...))
     75  1.1  rillig   end
     76  1.1  rillig   local f = assert(io.open(fname, "r"))
     77  1.1  rillig   local lineno = 0
     78  1.1  rillig   local prev = ""
     79  1.1  rillig   for line in f:lines() do
     80  1.1  rillig     lineno = lineno + 1
     81  1.1  rillig 
     82  1.3  rillig     local func, id = line:match("^%s+(%w+)%((%d+)[),]")
     83  1.3  rillig     if func == "error" or func == "warning" or func == "c99ism" or
     84  1.3  rillig        func == "gnuism" or func == "message" then
     85  1.2  rillig       local comment = prev:match("^%s+/%* (.+) %*/$")
     86  1.1  rillig       if comment ~= nil then
     87  1.1  rillig         check_message(fname, lineno, tonumber(id), comment, msgs, errors)
     88  1.1  rillig       end
     89  1.1  rillig     end
     90  1.1  rillig 
     91  1.1  rillig     prev = line
     92  1.1  rillig   end
     93  1.1  rillig 
     94  1.1  rillig   f:close()
     95  1.1  rillig 
     96  1.1  rillig   return errors
     97  1.1  rillig end
     98  1.1  rillig 
     99  1.1  rillig 
    100  1.1  rillig local function check_file(fname, msgs)
    101  1.1  rillig   local errors = collect_errors(fname, msgs)
    102  1.1  rillig   for _, err in ipairs(errors) do
    103  1.1  rillig     print(err)
    104  1.1  rillig   end
    105  1.1  rillig   return #errors == 0
    106  1.1  rillig end
    107  1.1  rillig 
    108  1.1  rillig 
    109  1.1  rillig local function main(arg)
    110  1.1  rillig   local msgs = load_messages("err.c")
    111  1.1  rillig   local ok = true
    112  1.1  rillig   for _, fname in ipairs(arg) do
    113  1.1  rillig     ok = check_file(fname, msgs) and ok
    114  1.1  rillig   end
    115  1.1  rillig   return ok
    116  1.1  rillig end
    117  1.1  rillig 
    118  1.1  rillig os.exit(main(arg))
    119