xref: /netbsd-src/usr.bin/xlint/lint2/check-msgs.lua (revision 5827310fa54d5b9ae500de221a6d494531270fee)
12fe9f15dSrillig#! /usr/bin/lua
2*5827310fSrillig-- $NetBSD: check-msgs.lua,v 1.3 2024/11/30 18:17:11 rillig Exp $
32fe9f15dSrillig
42fe9f15dSrillig--[[
52fe9f15dSrillig
62fe9f15dSrilligusage: lua ./check-msgs.lua *.c
72fe9f15dSrillig
82fe9f15dSrilligCheck that the message text in the comments of the C source code matches the
92fe9f15dSrilligactual user-visible message text in msg.c.
102fe9f15dSrillig
112fe9f15dSrillig]]
122fe9f15dSrillig
132fe9f15dSrillig
142fe9f15dSrilliglocal function load_messages(fname)
1577bd660cSrillig  local msgs = {} ---@type table<number>string
162fe9f15dSrillig
172fe9f15dSrillig  local f = assert(io.open(fname, "r"))
182fe9f15dSrillig  for line in f:lines() do
19*5827310fSrillig    local msg, id = line:match("%s*\"(.+)\",%s*// (%d+)$")
202fe9f15dSrillig    if msg ~= nil then
212fe9f15dSrillig      msgs[tonumber(id)] = msg
222fe9f15dSrillig    end
232fe9f15dSrillig  end
242fe9f15dSrillig
252fe9f15dSrillig  f:close()
262fe9f15dSrillig
272fe9f15dSrillig  return msgs
282fe9f15dSrilligend
292fe9f15dSrillig
302fe9f15dSrillig
3177bd660cSrilliglocal had_errors = false
3277bd660cSrillig---@param fmt string
3377bd660cSrilligfunction print_error(fmt, ...)
3477bd660cSrillig  print(fmt:format(...))
3577bd660cSrillig  had_errors = true
3677bd660cSrilligend
3777bd660cSrillig
3877bd660cSrillig
3977bd660cSrilliglocal function check_message(fname, lineno, id, comment, msgs)
402fe9f15dSrillig  local msg = msgs[id]
412fe9f15dSrillig
422fe9f15dSrillig  if msg == nil then
4377bd660cSrillig    print_error("%s:%d: id=%d not found", fname, lineno, id)
442fe9f15dSrillig    return
452fe9f15dSrillig  end
462fe9f15dSrillig
472fe9f15dSrillig  msg = msg:gsub("/%*", "**")
482fe9f15dSrillig  msg = msg:gsub("%*/", "**")
492fe9f15dSrillig  msg = msg:gsub("\\t", "\\\\t")  -- for lint2
502fe9f15dSrillig  msg = msg:gsub("\\(.)", "%1")
512fe9f15dSrillig
522fe9f15dSrillig  if comment == msg then
532fe9f15dSrillig    return
542fe9f15dSrillig  end
552fe9f15dSrillig
562fe9f15dSrillig  local prefix = comment:match("^(.-)%s*%.%.%.$")
572fe9f15dSrillig  if prefix ~= nil and msg:find(prefix, 1, 1) == 1 then
582fe9f15dSrillig    return
592fe9f15dSrillig  end
602fe9f15dSrillig
6177bd660cSrillig  print_error("%s:%d:   id=%-3d   msg=%-40s   comment=%s",
622fe9f15dSrillig    fname, lineno, id, msg, comment)
632fe9f15dSrilligend
642fe9f15dSrillig
652fe9f15dSrillig
6677bd660cSrilliglocal function check_file(fname, msgs)
672fe9f15dSrillig  local f = assert(io.open(fname, "r"))
682fe9f15dSrillig  local lineno = 0
692fe9f15dSrillig  local prev = ""
702fe9f15dSrillig  for line in f:lines() do
712fe9f15dSrillig    lineno = lineno + 1
722fe9f15dSrillig
732fe9f15dSrillig    local func, id = line:match("^%s+(%w+)%((%d+)[),]")
742fe9f15dSrillig    id = tonumber(id)
752fe9f15dSrillig    if func == "msg" then
762fe9f15dSrillig      local comment = prev:match("^%s+/%* (.+) %*/$")
772fe9f15dSrillig      if comment ~= nil then
7877bd660cSrillig        check_message(fname, lineno, id, comment, msgs)
792fe9f15dSrillig      else
8077bd660cSrillig        print_error("%s:%d: missing comment for %d: /* %s */",
812fe9f15dSrillig          fname, lineno, id, msgs[id])
822fe9f15dSrillig      end
832fe9f15dSrillig    end
842fe9f15dSrillig
852fe9f15dSrillig    prev = line
862fe9f15dSrillig  end
872fe9f15dSrillig
882fe9f15dSrillig  f:close()
892fe9f15dSrilligend
902fe9f15dSrillig
912fe9f15dSrillig
922fe9f15dSrilliglocal function main(arg)
932fe9f15dSrillig  local msgs = load_messages("msg.c")
942fe9f15dSrillig  for _, fname in ipairs(arg) do
9577bd660cSrillig    check_file(fname, msgs)
962fe9f15dSrillig  end
972fe9f15dSrilligend
982fe9f15dSrillig
9977bd660cSrilligmain(arg)
10077bd660cSrilligos.exit(not had_errors)
101