head 1.17; access; symbols netbsd-11-0-RC4:1.17 netbsd-11-0-RC3:1.17 netbsd-11-0-RC2:1.17 netbsd-11-0-RC1:1.17 perseant-exfatfs-base-20250801:1.17 netbsd-11:1.17.0.2 netbsd-11-base:1.17 netbsd-10-1-RELEASE:1.3 perseant-exfatfs-base-20240630:1.8 perseant-exfatfs:1.8.0.2 perseant-exfatfs-base:1.8 netbsd-10-0-RELEASE:1.3 netbsd-10-0-RC6:1.3 netbsd-10-0-RC5:1.3 netbsd-10-0-RC4:1.3 netbsd-10-0-RC3:1.3 netbsd-10-0-RC2:1.3 netbsd-10-0-RC1:1.3 netbsd-10:1.3.0.2 netbsd-10-base:1.3; locks; strict; comment @# @; 1.17 date 2025.07.01.05.03.18; author rillig; state Exp; branches; next 1.16; commitid STT9OR8irTRM501G; 1.16 date 2025.07.01.04.24.20; author rillig; state Exp; branches; next 1.15; commitid 7DIMxnaJVKV3UZ0G; 1.15 date 2025.06.30.21.44.39; author rillig; state Exp; branches; next 1.14; commitid bzLgXeWQrARDGX0G; 1.14 date 2025.06.29.17.10.04; author rillig; state Exp; branches; next 1.13; commitid VzjaxANm3cF2cO0G; 1.13 date 2025.04.13.09.29.32; author rillig; state Exp; branches; next 1.12; commitid 0g6qsRhbKlSC8SQF; 1.12 date 2025.03.30.09.51.49; author rillig; state Exp; branches; next 1.11; commitid veGmSzVhPiW2G4PF; 1.11 date 2025.03.29.10.39.48; author rillig; state Exp; branches; next 1.10; commitid 22Yp9aLGm4mSZWOF; 1.10 date 2025.01.11.20.16.40; author rillig; state Exp; branches; next 1.9; commitid YNPezgKQRVB0G6FF; 1.9 date 2024.07.20.11.05.11; author rillig; state Exp; branches; next 1.8; commitid Bey1UaNE0WVGeziF; 1.8 date 2023.12.17.09.44.00; author rillig; state Exp; branches 1.8.2.1; next 1.7; commitid u1lGcnUKVqg9KNQE; 1.7 date 2023.06.23.04.41.24; author rillig; state Exp; branches; next 1.6; commitid xfOav7HpCkM2L1uE; 1.6 date 2023.06.01.20.56.35; author rillig; state Exp; branches; next 1.5; commitid j3tIvMRlxolKQhrE; 1.5 date 2023.06.01.07.27.30; author rillig; state Exp; branches; next 1.4; commitid TByDzLlWp7ZSndrE; 1.4 date 2023.05.09.19.43.12; author rillig; state Exp; branches; next 1.3; commitid 0MGmFQ2Y6SPrbkoE; 1.3 date 2022.04.15.09.33.20; author rillig; state Exp; branches; next 1.2; commitid iv2NG5kjOF3mjhAD; 1.2 date 2022.01.29.00.52.53; author rillig; state Exp; branches; next 1.1; commitid 6wm5SwNxYOMWQsqD; 1.1 date 2022.01.15.12.35.18; author rillig; state Exp; branches; next ; commitid rnyI5jQCVI0xcJoD; 1.8.2.1 date 2025.08.02.05.58.30; author perseant; state Exp; branches; next ; commitid 23j6GFaDws3O875G; desc @@ 1.17 log @tests/make: detect unintended "expect" lines in the .mk files @ text @#! /usr/bin/lua -- $NetBSD: check-expect.lua,v 1.16 2025/07/01 04:24:20 rillig Exp $ --[[ usage: lua ./check-expect.lua *.mk Check that the various 'expect' comments in the .mk files produce the expected text in the corresponding .exp file. # expect: Each must occur in the .exp file. The order in the .mk file must be the same as in the .exp file. # expect[+-]offset: Each must occur in the .exp file and refer back to the source line in the .mk file. Each such line in the .exp file must have a corresponding expect line in the .mk file. The order in the .mk file must be the same as in the .exp file. # expect-reset Search the following "expect:" and "expect[+-]offset:" comments from the top of the .exp file again. # expect-not: The must not occur as part of any line in the .exp file. # expect-not-matches: The (see https://lua.org/manual/5.4/manual.html#6.4.1) must not occur as part of any line in the .exp file. ]] local had_errors = false ---@@param fmt string local function print_error(fmt, ...) print(fmt:format(...)) had_errors = true end ---@@return nil | string[] local function load_lines(fname) local lines = {} local f = io.open(fname, "r") if f == nil then return nil end for line in f:lines() do table.insert(lines, line) end f:close() return lines end --- @@shape ExpLine --- @@field filename string | nil --- @@field lineno number | nil --- @@field text string --- @@param lines string[] --- @@return ExpLine[] local function parse_exp(lines) local exp_lines = {} for _, line in ipairs(lines) do local l_filename, l_lineno, l_text = line:match('^make: ([^:]+%.mk):(%d+):%s+(.*)') if not l_filename then l_text = line end l_text = l_text:gsub("^%s+", ""):gsub("%s+$", "") table.insert(exp_lines, { filename = l_filename, lineno = tonumber(l_lineno), text = l_text, }) end return exp_lines end ---@@param exp_lines ExpLine[] local function detect_missing_expect_lines(exp_fname, exp_lines, s, e) for i = s, e do local exp_line = exp_lines[i] if exp_line.filename then print_error("error: %s:%d requires in %s:%d: # expect+1: %s", exp_fname, i, exp_line.filename, exp_line.lineno, exp_line.text) end end end local function check_mk(mk_fname) local exp_fname = mk_fname:gsub("%.mk$", ".exp") local mk_lines = load_lines(mk_fname) local exp_raw_lines = load_lines(exp_fname) if exp_raw_lines == nil then return end local exp_lines = parse_exp(exp_raw_lines) local exp_it = 1 for mk_lineno, mk_line in ipairs(mk_lines) do local function match(pattern, action) local _, n = mk_line:gsub(pattern, action) if n > 0 then match = function() end end end match("^#%s+expect%-not:%s*(.*)", function(text) for exp_lineno, exp_line in ipairs(exp_lines) do if exp_line.text:find(text, 1, true) then print_error("error: %s:%d: %s:%d must not contain '%s'", mk_fname, mk_lineno, exp_fname, exp_lineno, text) end end end) match("^#%s+expect%-not%-matches:%s*(.*)", function(pattern) for exp_lineno, exp_line in ipairs(exp_lines) do if exp_line.text:find(pattern) then print_error("error: %s:%d: %s:%d must not match '%s'", mk_fname, mk_lineno, exp_fname, exp_lineno, pattern) end end end) match("^#%s+expect:%s*(.*)", function(text) local i = exp_it while i <= #exp_lines and text ~= exp_lines[i].text do i = i + 1 end if i <= #exp_lines then detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1) exp_lines[i].text = "" exp_it = i + 1 else print_error("error: %s:%d: '%s:%d+' must contain '%s'", mk_fname, mk_lineno, exp_fname, exp_it, text) end end) match("^#%s+expect%-reset$", function() exp_it = 1 end) match("^#%s+expect([+%-]%d+):%s*(.*)", function(offset, text) local msg_lineno = mk_lineno + tonumber(offset) local i = exp_it while i <= #exp_lines and text ~= exp_lines[i].text do i = i + 1 end if i <= #exp_lines and exp_lines[i].lineno == msg_lineno then detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1) exp_lines[i].text = "" exp_it = i + 1 elseif i <= #exp_lines then print_error("error: %s:%d: expect%+d must be expect%+d", mk_fname, mk_lineno, tonumber(offset), exp_lines[i].lineno - mk_lineno) else print_error("error: %s:%d: %s:%d+ must contain '%s'", mk_fname, mk_lineno, exp_fname, exp_it, text) end end) match("^#%s+expect[+%-:]", function() print_error("error: %s:%d: invalid \"expect\" line: %s", mk_fname, mk_lineno, mk_line) end) end detect_missing_expect_lines(exp_fname, exp_lines, exp_it, #exp_lines) end for _, fname in ipairs(arg) do check_mk(fname) end os.exit(not had_errors) @ 1.16 log @tests/make: require "expect" comments to start a line Lua's string.gmatch function doesn't allow the anchor "^"; but its string.gsub function does. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.15 2025/06/30 21:44:39 rillig Exp $ d111 8 a118 1 mk_line:gsub("^#%s+expect%-not:%s*(.*)", function(text) d127 1 a127 1 mk_line:gsub("^#%s+expect%-not%-matches:%s*(.*)", function(pattern) d136 1 a136 1 mk_line:gsub("^#%s+expect:%s*(.*)", function(text) d151 1 a151 1 if mk_line:match("^#%s*expect%-reset$") then d153 1 a153 1 end d155 1 a155 1 mk_line:gsub("^#%s+expect([+%-]%d+):%s*(.*)", function(offset, text) d176 6 @ 1.15 log @tests/make: force expected lines to be listed in execution order The diagnostics from the program to check the "expect" lines in the unit test files were hard to follow since the "out-of-order" lines were confusing. For out-of-order lines, state where they should be placed instead. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.14 2025/06/29 17:10:04 rillig Exp $ d111 1 a111 1 for text in mk_line:gmatch("#%s*expect%-not:%s*(.*)") do d118 1 a118 1 end d120 1 a120 1 for pattern in mk_line:gmatch("#%s*expect%-not%-matches:%s*(.*)") do d127 1 a127 1 end d129 1 a129 1 for text in mk_line:gmatch("#%s*expect:%s*(.*)") do d142 1 a142 1 end d148 1 a148 1 for offset, text in mk_line:gmatch("#%s*expect([+%-]%d+):%s*(.*)") do d168 1 a168 1 end @ 1.14 log @tests/make: sort missing messages using a stable algorithm Lua's table.sort does not provide a stable sort. No idea how this could go unnoticed for two years and a few days. Noticed in directive-for-escape.mk, which has several diagnostics in the same location, in the body of .for loops. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.13 2025/04/13 09:29:32 rillig Exp $ d12 7 a18 1 All of these lines must occur in the .exp file, in the same order as d20 1 d23 2 a24 6 Search the following 'expect:' comments from the top of the .exp file again. # expect[+-]offset: Each message must occur in the .exp file and refer back to the source line in the .mk file. d27 1 a27 1 The substring must not occur as part of any line of the .exp file. d30 2 a31 2 The pattern (see https://lua.org/manual/5.4/manual.html#6.4.1) must not occur as part of any line of the .exp file. d37 1 a37 1 function print_error(fmt, ...) d48 3 a50 1 if f == nil then return nil end d61 33 a93 53 ---@@param exp_lines string[] local function collect_lineno_diagnostics(exp_lines) ---@@type table local by_location = {} for _, line in ipairs(exp_lines) do ---@@type string | nil, string, string local l_fname, l_lineno, l_msg = line:match('^make: ([^:]+):(%d+): (.*)') if l_fname ~= nil then local location = ("%s:%d"):format(l_fname, l_lineno) if by_location[location] == nil then by_location[location] = {} end table.insert(by_location[location], l_msg) end end return by_location end local function missing(by_location) ---@@type {filename: string, lineno: number, location: string}[] local locations = {} for location in pairs(by_location) do local filename, lineno = location:match("^(%S+%.mk):(%d+)$") if filename then table.insert(locations, { filename = filename, lineno = tonumber(lineno), location = location }) end end table.sort(locations, function(a, b) if a.filename ~= b.filename then return a.filename < b.filename end return a.lineno < b.lineno end) ---@@type {location: string, message: string}[] local missing_expectations = {} for _, location in ipairs(locations) do for _, message in ipairs(by_location[location.location]) do if message ~= "" then table.insert(missing_expectations, { location = location.location, message = message }) end a95 2 return missing_expectations a97 1 d101 7 a107 4 local exp_lines = load_lines(exp_fname) if exp_lines == nil then return end local by_location = collect_lineno_diagnostics(exp_lines) local prev_expect_line = 0 d112 5 a116 7 local i = 1 while i <= #exp_lines and not exp_lines[i]:find(text, 1, true) do i = i + 1 end if i <= #exp_lines then print_error("error: %s:%d: %s must not contain '%s'", mk_fname, mk_lineno, exp_fname, text) d120 6 a125 8 for text in mk_line:gmatch("#%s*expect%-not%-matches:%s*(.*)") do local i = 1 while i <= #exp_lines and not exp_lines[i]:find(text) do i = i + 1 end if i <= #exp_lines then print_error("error: %s:%d: %s must not match '%s'", mk_fname, mk_lineno, exp_fname, text) d130 2 a131 6 local i = prev_expect_line -- As of 2022-04-15, some lines in the .exp files contain trailing -- whitespace. If possible, this should be avoided by rewriting the -- debug logging. When done, the trailing gsub can be removed. -- See deptgt-phony.exp lines 14 and 15. while i < #exp_lines and text ~= exp_lines[i + 1]:gsub("^%s*", ""):gsub("%s*$", "") do d134 4 a137 2 if i < #exp_lines then prev_expect_line = i + 1 d140 1 a140 1 mk_fname, mk_lineno, exp_fname, prev_expect_line + 1, text) d143 1 d145 1 a145 1 prev_expect_line = 0 a147 1 ---@@param text string d149 1 a149 1 local location = ("%s:%d"):format(mk_fname, mk_lineno + tonumber(offset)) d151 3 a153 12 local found = false if by_location[location] ~= nil then for i, message in ipairs(by_location[location]) do if message == text then by_location[location][i] = "" found = true break elseif message ~= "" then print_error("error: %s:%d: out-of-order '%s'", mk_fname, mk_lineno, message) end end d156 11 a166 3 if not found then print_error("error: %s:%d: %s must contain '%s'", mk_fname, mk_lineno, exp_fname, text) d170 1 a170 4 for _, m in ipairs(missing(by_location)) do print_error("missing: %s: # expect+1: %s", m.location, m.message) end @ 1.13 log @tests/make: add tests for POSIX mode @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.12 2025/03/30 09:51:49 rillig Exp $ d79 2 a80 2 ---@@type {filename: string, lineno: number, location: string, message: string}[] local missing_expectations = {} d82 8 a89 11 for location, messages in pairs(by_location) do for _, message in ipairs(messages) do if message ~= "" and location:find(".mk:") then local filename, lineno = location:match("^(%S+):(%d+)$") table.insert(missing_expectations, { filename = filename, lineno = tonumber(lineno), location = location, message = message }) end d92 1 a92 1 table.sort(missing_expectations, function(a, b) d98 14 @ 1.12 log @make: use '"filename" line 123' for locations instead of 'filename:123' The format 'filename:123' is commonly used for identifying a location in a file. Text editors recognize it and allow quick navigation through it. The previous format was specific to make and would have required custom support in editors. The new format was already used in stack traces, except for the first line. Now all lines use the same format. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.11 2025/03/29 10:39:48 rillig Exp $ d128 1 a128 1 while i <= #exp_lines and not exp_lines[i]:find(text, 1) do @ 1.11 log @make: in stack traces from target commands, add the command level A target can contain several commands, and these commands are likely to contain the same expressions. To distinguish them, add one more line to the stack trace, to narrow down the source of the error. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.10 2025/01/11 20:16:40 rillig Exp $ d64 1 a64 1 line:match('^make: "([^"]+)" line (%d+): (.*)') @ 1.10 log @tests/make: force correct order of expected messages @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.9 2024/07/20 11:05:11 rillig Exp $ d26 3 d126 11 d141 1 a141 1 -- debug logging. When done, the gsub can be removed. d143 1 a143 1 while i < #exp_lines and text ~= exp_lines[i + 1]:gsub("%s*$", "") do @ 1.9 log @make: don't run erroneous commands in compat mode When there is a parse or evaluation error in an expression that becomes part of the command, don't run that command, as the result of the failed evaluation typically contains garbage characters. Skip the remaining commands from that target as well, as they may depend on the erroneous command. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.8 2023/12/17 09:44:00 rillig Exp $ d154 3 @ 1.8 log @tests/make: in 'expect' lines, require the complete text of the line @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.7 2023/06/23 04:41:24 rillig Exp $ d22 4 d111 12 @ 1.8.2.1 log @Sync with HEAD @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.17 2025/07/01 05:03:18 rillig Exp $ d12 1 a12 7 Each must occur in the .exp file. The order in the .mk file must be the same as in the .exp file. # expect[+-]offset: Each must occur in the .exp file and refer back to the source line in the .mk file. Each such line in the .exp file must have a corresponding expect line a13 1 The order in the .mk file must be the same as in the .exp file. d16 2 a17 2 Search the following "expect:" and "expect[+-]offset:" comments from the top of the .exp file again. d19 3 a21 6 # expect-not: The must not occur as part of any line in the .exp file. # expect-not-matches: The (see https://lua.org/manual/5.4/manual.html#6.4.1) must not occur as part of any line in the .exp file. d27 1 a27 1 local function print_error(fmt, ...) d38 1 a38 3 if f == nil then return nil end d49 16 a64 22 --- @@shape ExpLine --- @@field filename string | nil --- @@field lineno number | nil --- @@field text string --- @@param lines string[] --- @@return ExpLine[] local function parse_exp(lines) local exp_lines = {} for _, line in ipairs(lines) do local l_filename, l_lineno, l_text = line:match('^make: ([^:]+%.mk):(%d+):%s+(.*)') if not l_filename then l_text = line end l_text = l_text:gsub("^%s+", ""):gsub("%s+$", "") table.insert(exp_lines, { filename = l_filename, lineno = tonumber(l_lineno), text = l_text, }) d66 2 a67 1 return exp_lines d70 16 a85 7 ---@@param exp_lines ExpLine[] local function detect_missing_expect_lines(exp_fname, exp_lines, s, e) for i = s, e do local exp_line = exp_lines[i] if exp_line.filename then print_error("error: %s:%d requires in %s:%d: # expect+1: %s", exp_fname, i, exp_line.filename, exp_line.lineno, exp_line.text) d88 7 d97 1 d101 4 a104 7 local exp_raw_lines = load_lines(exp_fname) if exp_raw_lines == nil then return end local exp_lines = parse_exp(exp_raw_lines) local exp_it = 1 d107 7 a113 29 local function match(pattern, action) local _, n = mk_line:gsub(pattern, action) if n > 0 then match = function() end end end match("^#%s+expect%-not:%s*(.*)", function(text) for exp_lineno, exp_line in ipairs(exp_lines) do if exp_line.text:find(text, 1, true) then print_error("error: %s:%d: %s:%d must not contain '%s'", mk_fname, mk_lineno, exp_fname, exp_lineno, text) end end end) match("^#%s+expect%-not%-matches:%s*(.*)", function(pattern) for exp_lineno, exp_line in ipairs(exp_lines) do if exp_line.text:find(pattern) then print_error("error: %s:%d: %s:%d must not match '%s'", mk_fname, mk_lineno, exp_fname, exp_lineno, pattern) end end end) match("^#%s+expect:%s*(.*)", function(text) local i = exp_it while i <= #exp_lines and text ~= exp_lines[i].text do d116 2 a117 4 if i <= #exp_lines then detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1) exp_lines[i].text = "" exp_it = i + 1 d120 1 a120 1 mk_fname, mk_lineno, exp_fname, exp_it, text) d122 4 a125 1 end) d127 13 a139 10 match("^#%s+expect%-reset$", function() exp_it = 1 end) match("^#%s+expect([+%-]%d+):%s*(.*)", function(offset, text) local msg_lineno = mk_lineno + tonumber(offset) local i = exp_it while i <= #exp_lines and text ~= exp_lines[i].text do i = i + 1 d142 3 a144 11 if i <= #exp_lines and exp_lines[i].lineno == msg_lineno then detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1) exp_lines[i].text = "" exp_it = i + 1 elseif i <= #exp_lines then print_error("error: %s:%d: expect%+d must be expect%+d", mk_fname, mk_lineno, tonumber(offset), exp_lines[i].lineno - mk_lineno) else print_error("error: %s:%d: %s:%d+ must contain '%s'", mk_fname, mk_lineno, exp_fname, exp_it, text) d146 2 a147 6 end) match("^#%s+expect[+%-:]", function() print_error("error: %s:%d: invalid \"expect\" line: %s", mk_fname, mk_lineno, mk_line) end) d149 2 a151 1 detect_missing_expect_lines(exp_fname, exp_lines, exp_it, #exp_lines) @ 1.7 log @tests/make: sort missing 'expect' comments by their location @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.6 2023/06/01 20:56:35 rillig Exp $ d134 1 a134 1 if message ~= "" and message:find(text, 1, true) then @ 1.6 log @tests/make: force line-based diagnostics to be listed in the tests This way, contradictions between the intended output and the actual output are closer together and have a better chance of being spotted. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.5 2023/06/01 07:27:30 rillig Exp $ d71 27 d149 2 a150 7 -- XXX: The messages are not sorted in any meaningful way. for location, messages in pairs(by_location) do for _, message in ipairs(messages) do if message ~= "" and location:find(".mk:") then print_error("missing: %s: # expect+1: %s", location, message) end end @ 1.5 log @tests/make: clean up comments, extend a few tests @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.4 2023/05/09 19:43:12 rillig Exp $ a21 4 # expect-all Each message from the .exp file that can be matched by an 'expect[+-]offset' comment must actually be matched. a77 1 local match_all = false a119 4 if mk_line:match("^#%s*expect%-all$") then match_all = true end d122 5 a126 8 if match_all then -- XXX: The messages are not sorted in any meaningful way. for location, messages in pairs(by_location) do for _, message in ipairs(messages) do if message ~= "" then print_error("error: %s: missing 'expect' comment for '%s'", location, message) end @ 1.4 log @make: skip syntactically wrong .for loops When a .for loop cannot be interpreted correctly, for example when there are no iteration variables or the number of words doesn't match the iteration variables, skip the body of the .for loop instead of interpreting it once. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.3 2022/04/15 09:33:20 rillig Exp $ d61 1 a61 1 line:match("^make: \"([^\"]+)\" line (%d+): (.*)") @ 1.3 log @tests/make: adjust expectations to actual behavior The bug in deptgt-silent-jobs.mk has been fixed, the debug logging for comparing conditions and for deleting global variables has changed intentionally. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.2 2022/01/29 00:52:53 rillig Exp $ d8 2 a9 6 Check that each text from an '# expect: ...' comment in the .mk source files occurs in the corresponding .exp file, in the same order as in the .mk file. Check that each text from an '# expect[+-]offset: ...' comment in the .mk source files occurs in the corresponding .exp file and refers back to the correct line in the .mk file. d11 15 d82 1 d125 16 @ 1.2 log @tests/make: extend and isolate tests for target-local variables Reusing the target var-scope-local.o for several tests made the test more difficult to understand than necessary. The test names '2' and '3' didn't convey any meaning. Instead, add more test targets that are named after what they test. Add tests for each of the 5 variable assignment operators, to demonstrate an inconsistency between '+=' and '?='. Add tests for the built-in target-local variables as well and explain the general concepts, in particular the exact point where target-local expressions are expanded. The lines in the expected output file are not generated in the same order as they appear in the makefile, so allow the 'expect' lines in non-linear order, in check-expect.lua. @ text @d2 1 a2 1 -- $NetBSD: check-expect.lua,v 1.1 2022/01/15 12:35:18 rillig Exp $ d75 5 a79 1 while i < #exp_lines and text ~= exp_lines[i + 1] do @ 1.1 log @tests/make: ensure that the 'expect' comments in tests are correct Based on tests/usr.bin/xlint/check-expect.lua. For now, this extra check needs to be run manually. @ text @d2 1 a2 1 -- $NetBSD$ d85 3 @