pkgsrc-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: pkgsrc/pkgtools/pkglint



Module Name:    pkgsrc
Committed By:   rillig
Date:           Sun Dec  4 15:28:36 UTC 2016

Modified Files:
        pkgsrc/pkgtools/pkglint: Makefile
        pkgsrc/pkgtools/pkglint/files: buildlink3.go buildlink3_test.go
            category.go dir.go distinfo.go expecter.go files.go files_test.go
            getopt.go globaldata.go globalvars.go licenses.go line.go
            line_test.go logging.go mkline.go mkline_test.go mklines_test.go
            mkparser.go package.go package_test.go patches.go pkglint.go
            plist.go plist_test.go shell.go substcontext.go toplevel.go util.go
            vartypecheck.go
Added Files:
        pkgsrc/pkgtools/pkglint/files: regex.go

Log Message:
Updated pkglint to 5.4.12.

Changes since 5.4.11:

* warn when PKGSRC_COMPILER is compared with "==", since it may be a chain
  of compilers
* warn about listing Python .egg-info files directly in PLIST files, since
  lang/python/egg.mk takes care of this
* code cleanup: unify Error{0,1,2,3} into Errorf to make understanding the
  code easier; use interface{} for MkLine data; use regular expression
  instead of handwritten matching code, since one line is easier to read
  than 50


To generate a diff of this commit:
cvs rdiff -u -r1.500 -r1.501 pkgsrc/pkgtools/pkglint/Makefile
cvs rdiff -u -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/buildlink3.go \
    pkgsrc/pkgtools/pkglint/files/buildlink3_test.go \
    pkgsrc/pkgtools/pkglint/files/files.go \
    pkgsrc/pkgtools/pkglint/files/files_test.go \
    pkgsrc/pkgtools/pkglint/files/licenses.go \
    pkgsrc/pkgtools/pkglint/files/line_test.go \
    pkgsrc/pkgtools/pkglint/files/logging.go \
    pkgsrc/pkgtools/pkglint/files/substcontext.go
cvs rdiff -u -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/category.go \
    pkgsrc/pkgtools/pkglint/files/expecter.go \
    pkgsrc/pkgtools/pkglint/files/getopt.go
cvs rdiff -u -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/dir.go \
    pkgsrc/pkgtools/pkglint/files/globalvars.go \
    pkgsrc/pkgtools/pkglint/files/mkparser.go \
    pkgsrc/pkgtools/pkglint/files/toplevel.go
cvs rdiff -u -r1.9 -r1.10 pkgsrc/pkgtools/pkglint/files/distinfo.go \
    pkgsrc/pkgtools/pkglint/files/mklines_test.go \
    pkgsrc/pkgtools/pkglint/files/plist.go
cvs rdiff -u -r1.15 -r1.16 pkgsrc/pkgtools/pkglint/files/globaldata.go
cvs rdiff -u -r1.11 -r1.12 pkgsrc/pkgtools/pkglint/files/line.go
cvs rdiff -u -r1.17 -r1.18 pkgsrc/pkgtools/pkglint/files/mkline.go
cvs rdiff -u -r1.18 -r1.19 pkgsrc/pkgtools/pkglint/files/mkline_test.go
cvs rdiff -u -r1.13 -r1.14 pkgsrc/pkgtools/pkglint/files/package.go \
    pkgsrc/pkgtools/pkglint/files/shell.go
cvs rdiff -u -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/package_test.go \
    pkgsrc/pkgtools/pkglint/files/patches.go \
    pkgsrc/pkgtools/pkglint/files/plist_test.go \
    pkgsrc/pkgtools/pkglint/files/util.go
cvs rdiff -u -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/pkglint.go
cvs rdiff -u -r0 -r1.1 pkgsrc/pkgtools/pkglint/files/regex.go
cvs rdiff -u -r1.19 -r1.20 pkgsrc/pkgtools/pkglint/files/vartypecheck.go

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: pkgsrc/pkgtools/pkglint/Makefile
diff -u pkgsrc/pkgtools/pkglint/Makefile:1.500 pkgsrc/pkgtools/pkglint/Makefile:1.501
--- pkgsrc/pkgtools/pkglint/Makefile:1.500      Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/Makefile    Sun Dec  4 15:28:36 2016
@@ -1,10 +1,10 @@
-# $NetBSD: Makefile,v 1.500 2016/11/14 01:08:23 rillig Exp $
+# $NetBSD: Makefile,v 1.501 2016/12/04 15:28:36 rillig Exp $
 
-PKGNAME=       pkglint-5.4.11
+PKGNAME=       pkglint-5.4.12
 DISTFILES=     # none
 CATEGORIES=    pkgtools
 
-OWNER=         rillig%NetBSD.org@localhost
+MAINTAINER=    rillig%NetBSD.org@localhost
 HOMEPAGE=      http://www.NetBSD.org/docs/pkgsrc/
 COMMENT=       Verifier for NetBSD packages
 LICENSE=       2-clause-bsd

Index: pkgsrc/pkgtools/pkglint/files/buildlink3.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.6 pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.7
--- pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.6     Sat Jul  9 13:16:43 2016
+++ pkgsrc/pkgtools/pkglint/files/buildlink3.go Sun Dec  4 15:28:36 2016
@@ -17,14 +17,14 @@ func ChecklinesBuildlink3Mk(mklines *MkL
                line := exp.PreviousLine()
                // See pkgtools/createbuildlink/files/createbuildlink
                if hasPrefix(line.Text, "# XXX This file was created automatically") {
-                       line.Error0("This comment indicates unfinished work (url2pkg).")
+                       line.Errorf("This comment indicates unfinished work (url2pkg).")
                }
        }
 
        exp.ExpectEmptyLine()
 
        if exp.AdvanceIfMatches(`^BUILDLINK_DEPMETHOD\.(\S+)\?=.*$`) {
-               exp.PreviousLine().Warn0("This line belongs inside the .ifdef block.")
+               exp.PreviousLine().Warnf("This line belongs inside the .ifdef block.")
                for exp.AdvanceIfEquals("") {
                }
        }
@@ -35,7 +35,7 @@ func ChecklinesBuildlink3Mk(mklines *MkL
 
        // First paragraph: Introduction of the package identifier
        if !exp.AdvanceIfMatches(`^BUILDLINK_TREE\+=\s*(\S+)$`) {
-               exp.CurrentLine().Warn0("Expected a BUILDLINK_TREE line.")
+               exp.CurrentLine().Warnf("Expected a BUILDLINK_TREE line.")
                return
        }
        pkgbase = exp.m[1]
@@ -48,13 +48,13 @@ func ChecklinesBuildlink3Mk(mklines *MkL
                        {"${PHP_PKG_PREFIX}", "php"},
                } {
                        if contains(pkgbase, pair.varuse) {
-                               pkgbaseLine.Warn2("Please use %q instead of %q (also in other variables in this file).", pair.simple, pair.varuse)
+                               pkgbaseLine.Warnf("Please use %q instead of %q (also in other variables in this file).", pair.simple, pair.varuse)
                                warned = true
                        }
                }
                if !warned {
                        if m, varuse := match1(pkgbase, `(\$\{\w+\})`); m {
-                               pkgbaseLine.Warn1("Please replace %q with a simple string (also in other variables in this file).", varuse)
+                               pkgbaseLine.Warnf("Please replace %q with a simple string (also in other variables in this file).", varuse)
                                warned = true
                        }
                }
@@ -99,7 +99,7 @@ func ChecklinesBuildlink3Mk(mklines *MkL
        indentLevel := 1 // The first .if is from the second paragraph.
        for {
                if exp.EOF() {
-                       exp.CurrentLine().Warn0("Expected .endif")
+                       exp.CurrentLine().Warnf("Expected .endif")
                        return
                }
 
@@ -149,7 +149,7 @@ func ChecklinesBuildlink3Mk(mklines *MkL
 
                        if varparam := mkline.Varparam(); varparam != "" && varparam != pkgbase {
                                if hasPrefix(varname, "BUILDLINK_") && mkline.Varcanon() != "BUILDLINK_API_DEPENDS.*" {
-                                       line.Warn2("Only buildlink variables for %q, not %q may be set in this file.", pkgbase, varparam)
+                                       line.Warnf("Only buildlink variables for %q, not %q may be set in this file.", pkgbase, varparam)
                                }
                        }
 
@@ -181,7 +181,7 @@ func ChecklinesBuildlink3Mk(mklines *MkL
                }
        }
        if apiLine == nil {
-               exp.CurrentLine().Warn0("Definition of BUILDLINK_API_DEPENDS is missing.")
+               exp.CurrentLine().Warnf("Definition of BUILDLINK_API_DEPENDS is missing.")
        }
        exp.ExpectEmptyLine()
 
@@ -191,7 +191,7 @@ func ChecklinesBuildlink3Mk(mklines *MkL
        }
 
        if !exp.EOF() {
-               exp.CurrentLine().Warn0("The file should end here.")
+               exp.CurrentLine().Warnf("The file should end here.")
        }
 
        if G.Pkg != nil {
Index: pkgsrc/pkgtools/pkglint/files/buildlink3_test.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.6 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.7
--- pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.6        Sat Jul  9 13:16:43 2016
+++ pkgsrc/pkgtools/pkglint/files/buildlink3_test.go    Sun Dec  4 15:28:36 2016
@@ -7,7 +7,7 @@ import (
 func (s *Suite) Test_ChecklinesBuildlink3Mk(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "# XXX This file was created automatically using createbuildlink-@PKGVERSION@",
                "",
                "BUILDLINK_TREE+=        Xbae",
@@ -43,7 +43,7 @@ func (s *Suite) Test_ChecklinesBuildlink
        G.Pkg.EffectivePkgbase = "X11"
        G.Pkg.EffectivePkgnameLine = NewMkLine(NewLine("Makefile", 3, "DISTNAME=\tX11-1.0", nil))
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\ths-X11",
                "",
@@ -65,7 +65,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch_multiple_inclusion(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\tpkgbase1",
                "",
@@ -86,7 +86,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch_abi_api(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\ths-X11",
                "",
@@ -108,7 +108,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_abi_api_versions(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\ths-X11",
                "",
@@ -131,7 +131,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_no_BUILDLINK_TREE_at_beginning(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                ".if !defined(HS_X11_BUILDLINK3_MK)",
                "HS_X11_BUILDLINK3_MK:=",
@@ -152,7 +152,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_no_BUILDLINK_TREE_at_end(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_DEPMETHOD.hs-X11?=\tfull",
                "",
@@ -179,7 +179,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_multiple_inclusion_wrong(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\ths-X11",
                "",
@@ -196,7 +196,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_missing_endif(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\tpkgbase1",
                "",
@@ -211,7 +211,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_unknown_dependency_patterns(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+= hs-X11",
                "",
@@ -236,7 +236,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_PKGBASE_with_variable(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\t${PYPKGPREFIX}-wxWidgets",
                "",
@@ -258,7 +258,7 @@ func (s *Suite) Test_ChecklinesBuildlink
 func (s *Suite) Test_ChecklinesBuildlink3Mk_PKGBASE_with_unknown_variable(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("buildlink3.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "BUILDLINK_TREE+=\t${LICENSE}-wxWidgets",
                "",
Index: pkgsrc/pkgtools/pkglint/files/files.go
diff -u pkgsrc/pkgtools/pkglint/files/files.go:1.6 pkgsrc/pkgtools/pkglint/files/files.go:1.7
--- pkgsrc/pkgtools/pkglint/files/files.go:1.6  Sun Jun  5 11:24:32 2016
+++ pkgsrc/pkgtools/pkglint/files/files.go      Sun Dec  4 15:28:36 2016
@@ -9,11 +9,11 @@ import (
 func LoadNonemptyLines(fname string, joinContinuationLines bool) []*Line {
        lines, err := readLines(fname, joinContinuationLines)
        if err != nil {
-               NewLineWhole(fname).Error0("Cannot be read.")
+               NewLineWhole(fname).Errorf("Cannot be read.")
                return nil
        }
        if len(lines) == 0 {
-               NewLineWhole(fname).Error0("Must not be empty.")
+               NewLineWhole(fname).Errorf("Must not be empty.")
                return nil
        }
        return lines
@@ -132,7 +132,7 @@ func convertToLogicalLines(fname string,
        }
 
        if 0 < len(rawLines) && !hasSuffix(rawLines[len(rawLines)-1].textnl, "\n") {
-               NewLineEOF(fname).Error0("File must end with a newline.")
+               NewLineEOF(fname).Errorf("File must end with a newline.")
        }
 
        return loglines
@@ -166,12 +166,12 @@ func SaveAutofixChanges(lines []*Line) (
                }
                err := ioutil.WriteFile(tmpname, []byte(text), 0666)
                if err != nil {
-                       NewLineWhole(tmpname).Error0("Cannot write.")
+                       NewLineWhole(tmpname).Errorf("Cannot write.")
                        continue
                }
                err = os.Rename(tmpname, fname)
                if err != nil {
-                       NewLineWhole(fname).Error0("Cannot overwrite with auto-fixed content.")
+                       NewLineWhole(fname).Errorf("Cannot overwrite with auto-fixed content.")
                        continue
                }
                msg := "Has been auto-fixed. Please re-run pkglint."
Index: pkgsrc/pkgtools/pkglint/files/files_test.go
diff -u pkgsrc/pkgtools/pkglint/files/files_test.go:1.6 pkgsrc/pkgtools/pkglint/files/files_test.go:1.7
--- pkgsrc/pkgtools/pkglint/files/files_test.go:1.6     Sat Jul  9 09:43:48 2016
+++ pkgsrc/pkgtools/pkglint/files/files_test.go Sun Dec  4 15:28:36 2016
@@ -65,7 +65,7 @@ func (s *Suite) Test_show_autofix(c *che
        lines := LoadExistingLines(fname, true)
 
        if !lines[1].AutofixReplaceRegexp(`.`, "X") {
-               lines[1].Warn0("Something's wrong here.") // Prints the autofix NOTE afterwards
+               lines[1].Warnf("Something's wrong here.") // Prints the autofix NOTE afterwards
        }
        SaveAutofixChanges(lines)
 
@@ -85,7 +85,7 @@ func (s *Suite) Test_autofix(c *check.C)
        lines := LoadExistingLines(fname, true)
 
        if !lines[1].AutofixReplaceRegexp(`.`, "X") {
-               lines[1].Warn0("Something's wrong here.") // Prints the autofix NOTE afterwards
+               lines[1].Warnf("Something's wrong here.") // Prints the autofix NOTE afterwards
        }
        SaveAutofixChanges(lines)
 
Index: pkgsrc/pkgtools/pkglint/files/licenses.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses.go:1.6 pkgsrc/pkgtools/pkglint/files/licenses.go:1.7
--- pkgsrc/pkgtools/pkglint/files/licenses.go:1.6       Sun Jul 10 21:24:47 2016
+++ pkgsrc/pkgtools/pkglint/files/licenses.go   Sun Dec  4 15:28:36 2016
@@ -85,7 +85,7 @@ func checkToplevelUnusedLicenses() {
                licensepath := licensedir + "/" + licensename
                if fileExists(licensepath) {
                        if !G.UsedLicenses[licensename] {
-                               NewLineWhole(licensepath).Warn0("This license seems to be unused.")
+                               NewLineWhole(licensepath).Warnf("This license seems to be unused.")
                        }
                }
        }
@@ -100,9 +100,9 @@ func (lc *LicenseChecker) Check(value st
 
        if licenses == nil {
                if op == opAssign {
-                       lc.MkLine.Line.Error1("Parse error for license condition %q.", value)
+                       lc.MkLine.Line.Errorf("Parse error for license condition %q.", value)
                } else {
-                       lc.MkLine.Line.Error1("Parse error for appended license condition %q.", value)
+                       lc.MkLine.Line.Errorf("Parse error for appended license condition %q.", value)
                }
                return
        }
@@ -130,7 +130,7 @@ func (lc *LicenseChecker) checkNode(cond
        }
 
        if !fileExists(licenseFile) {
-               lc.MkLine.Warn1("License file %s does not exist.", cleanpath(licenseFile))
+               lc.MkLine.Warnf("License file %s does not exist.", cleanpath(licenseFile))
        }
 
        switch license {
@@ -139,7 +139,7 @@ func (lc *LicenseChecker) checkNode(cond
                "no-profit",
                "no-redistribution",
                "shareware":
-               lc.MkLine.Error1("License %q must not be used.", license)
+               lc.MkLine.Errorf("License %q must not be used.", license)
                Explain(
                        "Instead of using these deprecated licenses, extract the actual",
                        "license from the package into the pkgsrc/licenses/ directory",
@@ -148,7 +148,7 @@ func (lc *LicenseChecker) checkNode(cond
        }
 
        if len(cond.And) > 0 && len(cond.Or) > 0 {
-               lc.MkLine.Line.Error0("AND and OR operators in license conditions can only be combined using parentheses.")
+               lc.MkLine.Line.Errorf("AND and OR operators in license conditions can only be combined using parentheses.")
                Explain(
                        "Examples for valid license conditions are:",
                        "",
Index: pkgsrc/pkgtools/pkglint/files/line_test.go
diff -u pkgsrc/pkgtools/pkglint/files/line_test.go:1.6 pkgsrc/pkgtools/pkglint/files/line_test.go:1.7
--- pkgsrc/pkgtools/pkglint/files/line_test.go:1.6      Sat Jul  9 09:43:48 2016
+++ pkgsrc/pkgtools/pkglint/files/line_test.go  Sun Dec  4 15:28:36 2016
@@ -70,7 +70,7 @@ func (s *Suite) Test_Line_show_autofix_A
                29, "after\n"))
 
        if !line.AutofixReplace("old", "new") {
-               line.Warn0("Using \"old\" is deprecated.")
+               line.Warnf("Using \"old\" is deprecated.")
        }
 
        c.Check(s.Output(), equals, ""+
@@ -88,7 +88,7 @@ func (s *Suite) Test_Line_show_autofix_A
        line := NewLine("Makefile", 30, "original", s.NewRawLines(30, "original\n"))
 
        if !line.AutofixInsertBefore("inserted") {
-               line.Warn0("Dummy")
+               line.Warnf("Dummy")
        }
 
        c.Check(s.Output(), equals, ""+
@@ -104,7 +104,7 @@ func (s *Suite) Test_Line_show_autofix_A
        line := NewLine("Makefile", 30, "to be deleted", s.NewRawLines(30, "to be deleted\n"))
 
        if !line.AutofixDelete() {
-               line.Warn0("Dummy")
+               line.Warnf("Dummy")
        }
 
        c.Check(s.Output(), equals, ""+
Index: pkgsrc/pkgtools/pkglint/files/logging.go
diff -u pkgsrc/pkgtools/pkglint/files/logging.go:1.6 pkgsrc/pkgtools/pkglint/files/logging.go:1.7
--- pkgsrc/pkgtools/pkglint/files/logging.go:1.6        Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/logging.go    Sun Dec  4 15:28:36 2016
@@ -113,9 +113,5 @@ func Explain(explanation ...string) {
        }
        G.explanationsAvailable = true
 }
-func Explain1(e1 string)             { Explain(e1) }
-func Explain2(e1, e2 string)         { Explain(e1, e2) }
-func Explain3(e1, e2, e3 string)     { Explain(e1, e2, e3) }
-func Explain4(e1, e2, e3, e4 string) { Explain(e1, e2, e3, e4) }
 
 type pkglintFatal struct{}
Index: pkgsrc/pkgtools/pkglint/files/substcontext.go
diff -u pkgsrc/pkgtools/pkglint/files/substcontext.go:1.6 pkgsrc/pkgtools/pkglint/files/substcontext.go:1.7
--- pkgsrc/pkgtools/pkglint/files/substcontext.go:1.6   Thu Jul  7 12:09:27 2016
+++ pkgsrc/pkgtools/pkglint/files/substcontext.go       Sun Dec  4 15:28:36 2016
@@ -23,10 +23,10 @@ func (ctx *SubstContext) Varassign(mklin
        if varname == "SUBST_CLASSES" || hasPrefix(varname, "SUBST_CLASSES.") {
                classes := splitOnSpace(value)
                if len(classes) > 1 {
-                       mkline.Warn0("Please add only one class at a time to SUBST_CLASSES.")
+                       mkline.Warnf("Please add only one class at a time to SUBST_CLASSES.")
                }
                if ctx.id != "" && ctx.id != classes[0] {
-                       mkline.Warn0("SUBST_CLASSES should only appear once in a SUBST block.")
+                       mkline.Warnf("SUBST_CLASSES should only appear once in a SUBST block.")
                }
                ctx.id = classes[0]
                return
@@ -35,13 +35,13 @@ func (ctx *SubstContext) Varassign(mklin
        m, varbase, varparam := match2(varname, `^(SUBST_(?:STAGE|MESSAGE|FILES|SED|VARS|FILTER_CMD))\.([\-\w_]+)$`)
        if !m {
                if ctx.id != "" {
-                       mkline.Warn1("Foreign variable %q in SUBST block.", varname)
+                       mkline.Warnf("Foreign variable %q in SUBST block.", varname)
                }
                return
        }
 
        if ctx.id == "" {
-               mkline.Warn1("SUBST_CLASSES should come before the definition of %q.", varname)
+               mkline.Warnf("SUBST_CLASSES should come before the definition of %q.", varname)
                ctx.id = varparam
        }
 
@@ -55,7 +55,7 @@ func (ctx *SubstContext) Varassign(mklin
                        // but from a technically viewpoint, it is incorrect.
                        ctx.id = varparam
                } else {
-                       mkline.Warn2("Variable %q does not match SUBST class %q.", varname, ctx.id)
+                       mkline.Warnf("Variable %q does not match SUBST class %q.", varname, ctx.id)
                }
                return
        }
@@ -74,7 +74,7 @@ func (ctx *SubstContext) Varassign(mklin
        case "SUBST_VARS":
                ctx.duplist(mkline, &ctx.vars, varname, op, value)
        default:
-               mkline.Warn1("Foreign variable %q in SUBST block.", varname)
+               mkline.Warnf("Foreign variable %q in SUBST block.", varname)
        }
 }
 
@@ -90,10 +90,10 @@ func (ctx *SubstContext) Finish(mkline *
                return
        }
        if ctx.stage == "" {
-               mkline.Warn1("Incomplete SUBST block: %s missing.", ctx.varname("SUBST_STAGE"))
+               mkline.Warnf("Incomplete SUBST block: %s missing.", ctx.varname("SUBST_STAGE"))
        }
        if len(ctx.files) == 0 {
-               mkline.Warn1("Incomplete SUBST block: %s missing.", ctx.varname("SUBST_FILES"))
+               mkline.Warnf("Incomplete SUBST block: %s missing.", ctx.varname("SUBST_FILES"))
        }
        if len(ctx.sed) == 0 && len(ctx.vars) == 0 && ctx.filterCmd == "" {
                mkline.Line.Warnf("Incomplete SUBST block: %s, %s or %s missing.",
@@ -109,8 +109,6 @@ func (ctx *SubstContext) Finish(mkline *
 }
 
 func (ctx *SubstContext) varname(varbase string) string {
-       switch { // prevent inlining
-       }
        if ctx.id != "" {
                return varbase + "." + ctx.id
        } else {
@@ -120,14 +118,14 @@ func (ctx *SubstContext) varname(varbase
 
 func (ctx *SubstContext) dup(mkline *MkLine, pstr *string, varname, value string) {
        if *pstr != "" {
-               mkline.Warn1("Duplicate definition of %q.", varname)
+               mkline.Warnf("Duplicate definition of %q.", varname)
        }
        *pstr = value
 }
 
 func (ctx *SubstContext) duplist(mkline *MkLine, plist *[]string, varname string, op MkOperator, value string) {
        if len(*plist) > 0 && op != opAssignAppend {
-               mkline.Warn1("All but the first %q lines should use the \"+=\" operator.", varname)
+               mkline.Warnf("All but the first %q lines should use the \"+=\" operator.", varname)
        }
        *plist = append(*plist, value)
 }

Index: pkgsrc/pkgtools/pkglint/files/category.go
diff -u pkgsrc/pkgtools/pkglint/files/category.go:1.5 pkgsrc/pkgtools/pkglint/files/category.go:1.6
--- pkgsrc/pkgtools/pkglint/files/category.go:1.5       Sun Jun  5 11:24:32 2016
+++ pkgsrc/pkgtools/pkglint/files/category.go   Sun Dec  4 15:28:36 2016
@@ -25,7 +25,7 @@ func CheckdirCategory() {
        if exp.AdvanceIfMatches(`^COMMENT=\t*(.*)`) {
                mklines.mklines[exp.index-1].CheckValidCharactersInValue(`[- '(),/0-9A-Za-z]`)
        } else {
-               exp.CurrentLine().Error0("COMMENT= line expected.")
+               exp.CurrentLine().Errorf("COMMENT= line expected.")
        }
        exp.ExpectEmptyLine()
 
@@ -51,17 +51,17 @@ func CheckdirCategory() {
                if m, commentFlag, indentation, name, comment := match4(text, `^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$`); m {
                        commentedOut := commentFlag == "#"
                        if commentedOut && comment == "" {
-                               line.Warn1("%q commented out without giving a reason.", name)
+                               line.Warnf("%q commented out without giving a reason.", name)
                        }
 
                        if indentation != "\t" {
-                               line.Warn0("Indentation should be a single tab character.")
+                               line.Warnf("Indentation should be a single tab character.")
                        }
 
                        if name == prevSubdir {
-                               line.Error1("%q must only appear once.", name)
+                               line.Errorf("%q must only appear once.", name)
                        } else if name < prevSubdir {
-                               line.Warn2("%q should come before %q.", name, prevSubdir)
+                               line.Warnf("%q should come before %q.", name, prevSubdir)
                        } else {
                                // correctly ordered
                        }
@@ -72,7 +72,7 @@ func CheckdirCategory() {
 
                } else {
                        if line.Text != "" {
-                               line.Error0("SUBDIR+= line or empty line expected.")
+                               line.Errorf("SUBDIR+= line or empty line expected.")
                        }
                        break
                }
@@ -127,7 +127,7 @@ func CheckdirCategory() {
                if !fAtend && (mAtend || fCurrent < mCurrent) {
                        if !mCheck[fCurrent] {
                                if !line.AutofixInsertBefore("SUBDIR+=\t" + fCurrent) {
-                                       line.Error1("%q exists in the file system, but not in the Makefile.", fCurrent)
+                                       line.Errorf("%q exists in the file system, but not in the Makefile.", fCurrent)
                                }
                        }
                        fNeednext = true
@@ -135,7 +135,7 @@ func CheckdirCategory() {
                } else if !mAtend && (fAtend || mCurrent < fCurrent) {
                        if !fCheck[mCurrent] {
                                if !line.AutofixDelete() {
-                                       line.Error1("%q exists in the Makefile, but not in the file system.", mCurrent)
+                                       line.Errorf("%q exists in the Makefile, but not in the file system.", mCurrent)
                                }
                        }
                        mNeednext = true
@@ -158,7 +158,7 @@ func CheckdirCategory() {
        exp.ExpectEmptyLine()
        exp.ExpectText(".include \"../mk/misc/category.mk\"")
        if !exp.EOF() {
-               exp.CurrentLine().Error0("The file should end here.")
+               exp.CurrentLine().Errorf("The file should end here.")
        }
 
        SaveAutofixChanges(lines)
Index: pkgsrc/pkgtools/pkglint/files/expecter.go
diff -u pkgsrc/pkgtools/pkglint/files/expecter.go:1.5 pkgsrc/pkgtools/pkglint/files/expecter.go:1.6
--- pkgsrc/pkgtools/pkglint/files/expecter.go:1.5       Sat Jul  9 09:43:48 2016
+++ pkgsrc/pkgtools/pkglint/files/expecter.go   Sun Dec  4 15:28:36 2016
@@ -75,7 +75,7 @@ func (exp *Expecter) ExpectEmptyLine() b
 
        if G.opts.WarnSpace {
                if !exp.CurrentLine().AutofixInsertBefore("") {
-                       exp.CurrentLine().Note0("Empty line expected.")
+                       exp.CurrentLine().Notef("Empty line expected.")
                }
        }
        return false
@@ -88,6 +88,6 @@ func (exp *Expecter) ExpectText(text str
                return true
        }
 
-       exp.CurrentLine().Warn1("This line should contain the following text: %s", text)
+       exp.CurrentLine().Warnf("This line should contain the following text: %s", text)
        return false
 }
Index: pkgsrc/pkgtools/pkglint/files/getopt.go
diff -u pkgsrc/pkgtools/pkglint/files/getopt.go:1.5 pkgsrc/pkgtools/pkglint/files/getopt.go:1.6
--- pkgsrc/pkgtools/pkglint/files/getopt.go:1.5 Sun Jun  5 11:24:32 2016
+++ pkgsrc/pkgtools/pkglint/files/getopt.go     Sun Dec  4 15:28:36 2016
@@ -19,8 +19,6 @@ func NewOptions() *Options {
 }
 
 func (o *Options) AddFlagGroup(shortName rune, longName, argDescription, description string) *FlagGroup {
-       switch { // prevent inlining
-       }
        grp := new(FlagGroup)
        opt := &option{shortName, longName, argDescription, description, grp}
        o.options = append(o.options, opt)
@@ -28,8 +26,6 @@ func (o *Options) AddFlagGroup(shortName
 }
 
 func (o *Options) AddFlagVar(shortName rune, longName string, pflag *bool, defval bool, description string) {
-       switch { // prevent inlining
-       }
        *pflag = defval
        opt := &option{shortName, longName, "", description, pflag}
        o.options = append(o.options, opt)
@@ -194,8 +190,6 @@ type FlagGroup struct {
 }
 
 func (fg *FlagGroup) AddFlagVar(name string, flag *bool, defval bool, help string) {
-       switch { // prevent inlining
-       }
        opt := &groupFlag{name, flag, help}
        fg.flags = append(fg.flags, opt)
        *flag = defval

Index: pkgsrc/pkgtools/pkglint/files/dir.go
diff -u pkgsrc/pkgtools/pkglint/files/dir.go:1.4 pkgsrc/pkgtools/pkglint/files/dir.go:1.5
--- pkgsrc/pkgtools/pkglint/files/dir.go:1.4    Sun Jun  5 11:24:32 2016
+++ pkgsrc/pkgtools/pkglint/files/dir.go        Sun Dec  4 15:28:36 2016
@@ -24,7 +24,7 @@ func CheckDirent(fname string) {
        G.Infrastructure = matches(absCurrentDir, `/mk/|/mk$`)
        G.CurPkgsrcdir = findPkgsrcTopdir(G.CurrentDir)
        if G.CurPkgsrcdir == "" {
-               NewLineWhole(fname).Error1("Cannot determine the pkgsrc root directory for %q.", G.CurrentDir)
+               NewLineWhole(fname).Errorf("Cannot determine the pkgsrc root directory for %q.", G.CurrentDir)
                return
        }
 
@@ -44,6 +44,6 @@ func CheckDirent(fname string) {
        case ".":
                CheckdirToplevel()
        default:
-               NewLineWhole(fname).Error0("Cannot check directories outside a pkgsrc tree.")
+               NewLineWhole(fname).Errorf("Cannot check directories outside a pkgsrc tree.")
        }
 }
Index: pkgsrc/pkgtools/pkglint/files/globalvars.go
diff -u pkgsrc/pkgtools/pkglint/files/globalvars.go:1.4 pkgsrc/pkgtools/pkglint/files/globalvars.go:1.5
--- pkgsrc/pkgtools/pkglint/files/globalvars.go:1.4     Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/globalvars.go Sun Dec  4 15:28:36 2016
@@ -35,7 +35,7 @@ type GlobalVars struct {
        logErr                io.Writer
        debugOut              io.Writer
 
-       res       map[string]*regexp.Regexp // Compiled regular expressions
+       res       map[RegexPattern]*regexp.Regexp // Compiled regular expressions
        rematch   *Histogram
        renomatch *Histogram
        retime    *Histogram // Total time taken by matching a regular expression
Index: pkgsrc/pkgtools/pkglint/files/mkparser.go
diff -u pkgsrc/pkgtools/pkglint/files/mkparser.go:1.4 pkgsrc/pkgtools/pkglint/files/mkparser.go:1.5
--- pkgsrc/pkgtools/pkglint/files/mkparser.go:1.4       Sun Jul 10 21:24:47 2016
+++ pkgsrc/pkgtools/pkglint/files/mkparser.go   Sun Dec  4 15:28:36 2016
@@ -59,7 +59,7 @@ func (p *MkParser) VarUse() *MkVarUse {
                varname := p.Varname()
                if varname != "" {
                        if usingRoundParen && p.EmitWarnings {
-                               p.Line.Warn1("Please use curly braces {} instead of round parentheses () for %s.", varname)
+                               p.Line.Warnf("Please use curly braces {} instead of round parentheses () for %s.", varname)
                        }
                        modifiers := p.VarUseModifiers(varname, closing)
                        if repl.AdvanceStr(closing) {
@@ -89,7 +89,7 @@ func (p *MkParser) VarUse() *MkVarUse {
        if repl.PeekByte() == '$' && repl.AdvanceRegexp(`^\$(\w)`) {
                varname := repl.m[1]
                if p.EmitWarnings {
-                       p.Line.Warn1("$%[1]s is ambiguous. Use ${%[1]s} if you mean a Makefile variable or $$%[1]s if you mean a shell variable.", varname)
+                       p.Line.Warnf("$%[1]s is ambiguous. Use ${%[1]s} if you mean a Makefile variable or $$%[1]s if you mean a shell variable.", varname)
                }
                return &MkVarUse{varname, nil}
        }
@@ -158,7 +158,7 @@ func (p *MkParser) VarUseModifiers(varna
                                for p.VarUse() != nil || repl.AdvanceRegexp(RegexPattern(`^([^$:@`+closing+`\\]|\$\$|\\.)+`)) {
                                }
                                if !repl.AdvanceStr("@") && p.EmitWarnings {
-                                       p.Line.Warn2("Modifier ${%s:@%s@...@} is missing the final \"@\".", varname, loopvar)
+                                       p.Line.Warnf("Modifier ${%s:@%s@...@} is missing the final \"@\".", varname, loopvar)
                                }
                                modifiers = append(modifiers, repl.Since(modifierMark))
                                continue
Index: pkgsrc/pkgtools/pkglint/files/toplevel.go
diff -u pkgsrc/pkgtools/pkglint/files/toplevel.go:1.4 pkgsrc/pkgtools/pkglint/files/toplevel.go:1.5
--- pkgsrc/pkgtools/pkglint/files/toplevel.go:1.4       Sun Jun  5 11:24:32 2016
+++ pkgsrc/pkgtools/pkglint/files/toplevel.go   Sun Dec  4 15:28:36 2016
@@ -37,11 +37,11 @@ func CheckdirToplevel() {
 
 func (ctx *Toplevel) checkSubdir(line *Line, commentedOut bool, indentation, subdir, comment string) {
        if commentedOut && comment == "" {
-               line.Warn1("%q commented out without giving a reason.", subdir)
+               line.Warnf("%q commented out without giving a reason.", subdir)
        }
 
        if indentation != "\t" {
-               line.Warn0("Indentation should be a single tab character.")
+               line.Warnf("Indentation should be a single tab character.")
        }
 
        if contains(subdir, "$") || !fileExists(G.CurrentDir+"/"+subdir+"/Makefile") {
@@ -53,11 +53,11 @@ func (ctx *Toplevel) checkSubdir(line *L
        case subdir > prev:
                // Correctly ordered
        case subdir == prev:
-               line.Error0("Each subdir must only appear once.")
+               line.Errorf("Each subdir must only appear once.")
        case subdir == "archivers" && prev == "x11":
                // This exception is documented in the top-level Makefile.
        default:
-               line.Warn2("%s should come before %s", subdir, prev)
+               line.Warnf("%s should come before %s", subdir, prev)
        }
        ctx.previousSubdir = subdir
 

Index: pkgsrc/pkgtools/pkglint/files/distinfo.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo.go:1.9 pkgsrc/pkgtools/pkglint/files/distinfo.go:1.10
--- pkgsrc/pkgtools/pkglint/files/distinfo.go:1.9       Fri Sep 30 18:27:37 2016
+++ pkgsrc/pkgtools/pkglint/files/distinfo.go   Sun Dec  4 15:28:36 2016
@@ -48,7 +48,7 @@ type distinfoLinesChecker struct {
 func (ck *distinfoLinesChecker) checkLines(lines []*Line) {
        lines[0].CheckRcsid(``, "")
        if 1 < len(lines) && lines[1].Text != "" {
-               lines[1].Note0("Empty line expected.")
+               lines[1].Notef("Empty line expected.")
        }
 
        for i, line := range lines {
@@ -57,7 +57,7 @@ func (ck *distinfoLinesChecker) checkLin
                }
                m, alg, filename, hash := match3(line.Text, `^(\w+) \((\w[^)]*)\) = (.*)(?: bytes)?$`)
                if !m {
-                       line.Error0("Invalid line.")
+                       line.Errorf("Invalid line.")
                        continue
                }
 
@@ -78,10 +78,10 @@ func (ck *distinfoLinesChecker) onFilena
                algorithms := strings.Join(ck.algorithms, ", ")
                if ck.isPatch {
                        if algorithms != "SHA1" {
-                               line.Error2("Expected SHA1 hash for %s, got %s.", currentFname, algorithms)
+                               line.Errorf("Expected SHA1 hash for %s, got %s.", currentFname, algorithms)
                        }
                } else if hasPrefix(currentFname, "patch-") && algorithms == "SHA1" {
-                       ck.currentFirstLine.Warn2("Patch file %q does not exist in directory %q.", currentFname, cleanpath(ck.patchdir))
+                       ck.currentFirstLine.Warnf("Patch file %q does not exist in directory %q.", currentFname, cleanpath(ck.patchdir))
                        Explain(
                                "If the patches directory looks correct, the patch may have been",
                                "removed without updating the distinfo file.  In such a case please",
@@ -89,7 +89,7 @@ func (ck *distinfoLinesChecker) onFilena
                                "",
                                "If the patches directory looks wrong, pkglint needs to be improved.")
                } else if algorithms != "SHA1, RMD160, Size" && algorithms != "SHA1, RMD160, SHA512, Size" {
-                       line.Error2("Expected SHA1, RMD160, SHA512, Size checksums for %q, got %s.", currentFname, algorithms)
+                       line.Errorf("Expected SHA1, RMD160, SHA512, Size checksums for %q, got %s.", currentFname, algorithms)
                }
        }
 
@@ -102,7 +102,7 @@ func (ck *distinfoLinesChecker) onFilena
 func (ck *distinfoLinesChecker) checkPatchSha1(line *Line, patchFname, distinfoSha1Hex string) {
        patchBytes, err := ioutil.ReadFile(G.CurrentDir + "/" + patchFname)
        if err != nil {
-               line.Error1("%s does not exist.", patchFname)
+               line.Errorf("%s does not exist.", patchFname)
                return
        }
 
@@ -158,7 +158,7 @@ func (ck *distinfoLinesChecker) checkUnc
        if ck.isPatch {
                patchFname := ck.patchdir + "/" + patchName
                if ck.distinfoIsCommitted && !isCommitted(G.CurrentDir+"/"+patchFname) {
-                       line.Warn1("%s is registered in distinfo but not added to CVS.", patchFname)
+                       line.Warnf("%s is registered in distinfo but not added to CVS.", patchFname)
                }
                ck.checkPatchSha1(line, patchFname, sha1Hash)
                ck.patches[patchName] = true
Index: pkgsrc/pkgtools/pkglint/files/mklines_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.9 pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.10
--- pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.9   Tue Nov  1 21:40:25 2016
+++ pkgsrc/pkgtools/pkglint/files/mklines_test.go       Sun Dec  4 15:28:36 2016
@@ -10,7 +10,7 @@ func (s *Suite) Test_MkLines_Check__auto
        s.UseCommandLine(c, "--autofix", "-Wspace")
        tmpfile := s.CreateTmpFile(c, "fname.mk", "")
        mklines := s.NewMkLines(tmpfile,
-               "# $"+"NetBSD$",
+               mkrcsid,
                ".if defined(A)",
                ".for a in ${A}",
                ".if defined(C)",
@@ -38,7 +38,7 @@ func (s *Suite) Test_MkLines_Check__auto
 
 func (s *Suite) Test_MkLines_Check__unusual_target(c *check.C) {
        mklines := s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "echo: echo.c",
                "\tcc -o ${.TARGET} ${.IMPSRC}")
@@ -63,7 +63,7 @@ func (s *Suite) Test_MkLines_quoting_LDF
        G.globalData.InitVartypes()
        G.Pkg = NewPackage("category/pkgbase")
        mklines := s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "GNU_CONFIGURE=\tyes",
                "CONFIGURE_ENV+=\tX_LIBS=${X11_LDFLAGS:Q}")
 
@@ -77,7 +77,7 @@ func (s *Suite) Test_MkLines_quoting_LDF
 func (s *Suite) Test_MkLines__variable_alignment_advanced(c *check.C) {
        s.UseCommandLine(c, "-Wspace")
        fname := s.CreateTmpFileLines(c, "Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "VAR= \\", // In continuation lines, indenting with spaces is ok
                "\tvalue",
@@ -151,7 +151,7 @@ func (s *Suite) Test_MkLines__variable_a
 func (s *Suite) Test_MkLines__variable_alignment_space_and_tab(c *check.C) {
        s.UseCommandLine(c, "-Wspace")
        mklines := s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "VAR=    space",
                "VAR=\ttab ${VAR}")
@@ -167,7 +167,7 @@ func (s *Suite) Test_MkLines__for_loop_m
        s.RegisterTool(&Tool{Name: "find", Varname: "FIND", Predefined: true})
        s.RegisterTool(&Tool{Name: "pax", Varname: "PAX", Predefined: true})
        mklines := s.NewMkLines("audio/squeezeboxserver/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                ".for _list_ _dir_ in ${SBS_COPY}",
                "\tcd ${WRKSRC} && ${FIND} ${${_list_}} -type f ! -name '*.orig' 2>/dev/null "+
@@ -186,8 +186,10 @@ func (s *Suite) Test_MkLines__comparing_
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("databases/gdbm_compat/builtin.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                ".if ${USE_BUILTIN.gdbm} == \"no\"",
+               ".endif",
+               ".if ${USE_BUILTIN.gdbm:tu} == \"no\"", // Can never be true, since "no" is not uppercase.
                ".endif")
 
        mklines.Check()
@@ -200,7 +202,7 @@ func (s *Suite) Test_MkLines__varuse_sh_
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("lang/qore/module.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "qore-version=\tqore --short-version | ${SED} -e s/-.*//",
                "PLIST_SUBST+=\tQORE_VERSION=\"${qore-version:sh}\"")
 
@@ -221,7 +223,7 @@ func (s *Suite) Test_MkLines__varuse_par
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("converters/wv2/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "CONFIGURE_ARGS+=\t\t${CONFIGURE_ARGS.${ICONV_TYPE}-iconv}",
                "CONFIGURE_ARGS.gnu-iconv=\t--with-libiconv=${BUILDLINK_PREFIX.iconv}")
 
@@ -234,7 +236,7 @@ func (s *Suite) Test_MkLines__loop_modif
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("chat/xchat/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "GCONF_SCHEMAS=\tapps_xchat_url_handler.schemas",
                "post-install:",
                "\t${GCONF_SCHEMAS:@.s.@"+
@@ -251,7 +253,7 @@ func (s *Suite) Test_MkLines__loop_modif
 func (s *Suite) Test_MkLines__PKG_SKIP_REASON_depending_on_OPSYS(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "PKG_SKIP_REASON+=\t\"Fails everywhere\"",
                ".if ${OPSYS} == \"Cygwin\"",
                "PKG_SKIP_REASON+=\t\"Fails on Cygwin\"",
@@ -266,7 +268,7 @@ func (s *Suite) Test_MkLines__PKG_SKIP_R
 func (s *Suite) Test_MkLines__indirect_variables(c *check.C) {
        s.UseCommandLine(c, "-Wall")
        mklines := s.NewMkLines("net/uucp/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "post-configure:",
                ".for var in MAIL_PROGRAM CMDPATH",
@@ -316,7 +318,7 @@ func (s *Suite) Test_MkLines_Check__abso
 func (s *Suite) Test_MkLines_checkForUsedComment(c *check.C) {
        s.UseCommandLine(c, "--show-autofix")
        s.NewMkLines("Makefile.common",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "# used by sysutils/mc",
        ).checkForUsedComment("sysutils/mc")
@@ -328,20 +330,20 @@ func (s *Suite) Test_MkLines_checkForUse
        c.Check(s.Output(), equals, "")
 
        s.NewMkLines("Makefile.common",
-               "# $"+"NetBSD$",
+               mkrcsid,
        ).checkForUsedComment("category/package")
 
        c.Check(s.Output(), equals, "")
 
        s.NewMkLines("Makefile.common",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
        ).checkForUsedComment("category/package")
 
        c.Check(s.Output(), equals, "")
 
        s.NewMkLines("Makefile.common",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "VARNAME=\tvalue",
        ).checkForUsedComment("category/package")
@@ -351,7 +353,7 @@ func (s *Suite) Test_MkLines_checkForUse
                "AUTOFIX: Makefile.common:2: Inserting a line \"# used by category/package\" before this line.\n")
 
        s.NewMkLines("Makefile.common",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "#",
                "#",
        ).checkForUsedComment("category/package")
Index: pkgsrc/pkgtools/pkglint/files/plist.go
diff -u pkgsrc/pkgtools/pkglint/files/plist.go:1.9 pkgsrc/pkgtools/pkglint/files/plist.go:1.10
--- pkgsrc/pkgtools/pkglint/files/plist.go:1.9  Tue Nov  1 21:40:25 2016
+++ pkgsrc/pkgtools/pkglint/files/plist.go      Sun Dec  4 15:28:36 2016
@@ -14,7 +14,7 @@ func ChecklinesPlist(lines []*Line) {
        lines[0].CheckRcsid(`@comment `, "@comment ")
 
        if len(lines) == 1 {
-               lines[0].Warn0("PLIST files shouldn't be empty.")
+               lines[0].Warnf("PLIST files shouldn't be empty.")
                Explain(
                        "One reason for empty PLISTs is that this is a newly created package",
                        "and that the author didn't run \"bmake print-PLIST\" after installing",
@@ -124,7 +124,7 @@ func (ck *PlistChecker) checkline(pline 
        } else if hasPrefix(text, "$") {
                ck.checkpath(pline)
        } else {
-               pline.line.Warn0("Unknown line type.")
+               pline.line.Warnf("Unknown line type.")
        }
 }
 
@@ -140,8 +140,8 @@ func (ck *PlistChecker) checkpath(pline 
        }
        if hasPrefix(text, "${PKGMANDIR}/") {
                if !line.AutofixReplace("${PKGMANDIR}/", "man/") {
-                       line.Note0("PLIST files should mention \"man/\" instead of \"${PKGMANDIR}\".")
-                       Explain2(
+                       line.Notef("PLIST files should mention \"man/\" instead of \"${PKGMANDIR}\".")
+                       Explain(
                                "The pkgsrc infrastructure takes care of replacing the correct value",
                                "when generating the actual PLIST for the package.")
                }
@@ -156,7 +156,7 @@ func (ck *PlistChecker) checkpath(pline 
        case "bin":
                ck.checkpathBin(pline, dirname, basename)
        case "doc":
-               line.Error0("Documentation must be installed under share/doc, not doc.")
+               line.Errorf("Documentation must be installed under share/doc, not doc.")
        case "etc":
                ck.checkpathEtc(pline, dirname, basename)
        case "info":
@@ -172,29 +172,32 @@ func (ck *PlistChecker) checkpath(pline 
        }
 
        if contains(text, "${PKGLOCALEDIR}") && G.Pkg != nil && G.Pkg.vardef["USE_PKGLOCALEDIR"] == nil {
-               line.Warn0("PLIST contains ${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found.")
+               line.Warnf("PLIST contains ${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found.")
        }
 
        if contains(text, "/CVS/") {
-               line.Warn0("CVS files should not be in the PLIST.")
+               line.Warnf("CVS files should not be in the PLIST.")
        }
        if hasSuffix(text, ".orig") {
-               line.Warn0(".orig files should not be in the PLIST.")
+               line.Warnf(".orig files should not be in the PLIST.")
        }
        if hasSuffix(text, "/perllocal.pod") {
-               line.Warn0("perllocal.pod files should not be in the PLIST.")
-               Explain2(
+               line.Warnf("perllocal.pod files should not be in the PLIST.")
+               Explain(
                        "This file is handled automatically by the INSTALL/DEINSTALL scripts,",
                        "since its contents changes frequently.")
        }
+       if contains(text, ".egg-info/") {
+               line.Warnf("Include \"../../lang/python/egg.mk\" instead of listing .egg-info files directly.")
+       }
 }
 
 func (ck *PlistChecker) checkSorted(pline *PlistLine) {
        if text := pline.text; G.opts.WarnPlistSort && hasAlnumPrefix(text) && !containsVarRef(text) {
                if ck.lastFname != "" {
                        if ck.lastFname > text && !G.opts.Autofix {
-                               pline.line.Warn2("%q should be sorted before %q.", text, ck.lastFname)
-                               Explain2(
+                               pline.line.Warnf("%q should be sorted before %q.", text, ck.lastFname)
+                               Explain(
                                        "The files in the PLIST should be sorted alphabetically.",
                                        "To fix this, run \"pkglint -F PLIST\".")
                        }
@@ -210,7 +213,7 @@ func (ck *PlistChecker) checkSorted(plin
 
 func (ck *PlistChecker) checkpathBin(pline *PlistLine, dirname, basename string) {
        if contains(dirname, "/") {
-               pline.line.Warn0("The bin/ directory should not have subdirectories.")
+               pline.line.Warnf("The bin/ directory should not have subdirectories.")
                return
        }
 
@@ -218,7 +221,7 @@ func (ck *PlistChecker) checkpathBin(pli
                ck.allFiles["man/man1/"+basename+".1"] == nil &&
                ck.allFiles["man/man6/"+basename+".6"] == nil &&
                ck.allFiles["${IMAKE_MAN_DIR}/"+basename+".${IMAKE_MANNEWSUFFIX}"] == nil {
-               pline.line.Warn1("Manual page missing for bin/%s.", basename)
+               pline.line.Warnf("Manual page missing for bin/%s.", basename)
                Explain(
                        "All programs that can be run directly by the user should have a",
                        "manual page for quick reference.  The programs in the bin/ directory",
@@ -230,22 +233,22 @@ func (ck *PlistChecker) checkpathBin(pli
 
 func (ck *PlistChecker) checkpathEtc(pline *PlistLine, dirname, basename string) {
        if hasPrefix(pline.text, "etc/rc.d/") {
-               pline.line.Error0("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework.")
+               pline.line.Errorf("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework.")
                return
        }
 
-       pline.line.Error0("Configuration files must not be registered in the PLIST. " +
+       pline.line.Errorf("Configuration files must not be registered in the PLIST. " +
                "Please use the CONF_FILES framework, which is described in mk/pkginstall/bsd.pkginstall.mk.")
 }
 
 func (ck *PlistChecker) checkpathInfo(pline *PlistLine, dirname, basename string) {
        if pline.text == "info/dir" {
-               pline.line.Error0("\"info/dir\" must not be listed. Use install-info to add/remove an entry.")
+               pline.line.Errorf("\"info/dir\" must not be listed. Use install-info to add/remove an entry.")
                return
        }
 
        if G.Pkg != nil && G.Pkg.vardef["INFO_FILES"] == nil {
-               pline.line.Warn0("Packages that install info files should set INFO_FILES.")
+               pline.line.Warnf("Packages that install info files should set INFO_FILES.")
        }
 }
 
@@ -255,22 +258,22 @@ func (ck *PlistChecker) checkpathLib(pli
                return
 
        case pline.text == "lib/charset.alias" && (G.Pkg == nil || G.Pkg.Pkgpath != "converters/libiconv"):
-               pline.line.Error0("Only the libiconv package may install lib/charset.alias.")
+               pline.line.Errorf("Only the libiconv package may install lib/charset.alias.")
                return
 
        case hasPrefix(pline.text, "lib/locale/"):
-               pline.line.Error0("\"lib/locale\" must not be listed. Use ${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead.")
+               pline.line.Errorf("\"lib/locale\" must not be listed. Use ${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead.")
                return
        }
 
        switch ext := path.Ext(basename); ext {
        case ".a", ".la", ".so":
                if G.opts.WarnExtra && dirname == "lib" && !hasPrefix(basename, "lib") {
-                       pline.line.Warn1("Library filename %q should start with \"lib\".", basename)
+                       pline.line.Warnf("Library filename %q should start with \"lib\".", basename)
                }
                if ext == "la" {
                        if G.Pkg != nil && G.Pkg.vardef["USE_LIBTOOL"] == nil {
-                               pline.line.Warn0("Packages that install libtool libraries should define USE_LIBTOOL.")
+                               pline.line.Warnf("Packages that install libtool libraries should define USE_LIBTOOL.")
                        }
                }
        }
@@ -278,7 +281,7 @@ func (ck *PlistChecker) checkpathLib(pli
        if contains(basename, ".a") || contains(basename, ".so") {
                if m, noext := match1(pline.text, `^(.*)(?:\.a|\.so[0-9.]*)$`); m {
                        if laLine := ck.allFiles[noext+".la"]; laLine != nil {
-                               pline.line.Warn1("Redundant library found. The libtool library is in %s.", laLine.line.ReferenceFrom(pline.line))
+                               pline.line.Warnf("Redundant library found. The libtool library is in %s.", laLine.line.ReferenceFrom(pline.line))
                        }
                }
        }
@@ -289,31 +292,31 @@ func (ck *PlistChecker) checkpathMan(pli
 
        m, catOrMan, section, manpage, ext, gz := match5(pline.text, `^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$`)
        if !m {
-               // maybe: line.warn1("Invalid filename %q for manual page.", text)
+               // maybe: line.Warnf("Invalid filename %q for manual page.", text)
                return
        }
 
        if !matches(section, `^[\dln]$`) {
-               line.Warn1("Unknown section %q for manual page.", section)
+               line.Warnf("Unknown section %q for manual page.", section)
        }
 
        if catOrMan == "cat" && ck.allFiles["man/man"+section+"/"+manpage+"."+section] == nil {
-               line.Warn0("Preformatted manual page without unformatted one.")
+               line.Warnf("Preformatted manual page without unformatted one.")
        }
 
        if catOrMan == "cat" {
                if ext != "0" {
-                       line.Warn0("Preformatted manual pages should end in \".0\".")
+                       line.Warnf("Preformatted manual pages should end in \".0\".")
                }
        } else {
                if !hasPrefix(ext, section) {
-                       line.Warn2("Mismatch between the section (%s) and extension (%s) of the manual page.", section, ext)
+                       line.Warnf("Mismatch between the section (%s) and extension (%s) of the manual page.", section, ext)
                }
        }
 
        if gz != "" {
-               line.Note0("The .gz extension is unnecessary for manual pages.")
-               Explain4(
+               line.Notef("The .gz extension is unnecessary for manual pages.")
+               Explain(
                        "Whether the manual pages are installed in compressed form or not is",
                        "configured by the pkgsrc user.  Compression and decompression takes",
                        "place automatically, no matter if the .gz extension is mentioned in",
@@ -325,7 +328,7 @@ func (ck *PlistChecker) checkpathSbin(pl
        binname := pline.text[5:]
 
        if ck.allFiles["man/man8/"+binname+".8"] == nil && G.opts.WarnExtra {
-               pline.line.Warn1("Manual page missing for sbin/%s.", binname)
+               pline.line.Warnf("Manual page missing for sbin/%s.", binname)
                Explain(
                        "All programs that can be run directly by the user should have a",
                        "manual page for quick reference.  The programs in the sbin/",
@@ -342,8 +345,8 @@ func (ck *PlistChecker) checkpathShare(p
        case false && hasPrefix(text, "share/applications/") && hasSuffix(text, ".desktop"):
                f := "../../sysutils/desktop-file-utils/desktopdb.mk"
                if G.opts.WarnExtra && G.Pkg != nil && G.Pkg.included[f] == nil {
-                       line.Warn1("Packages that install a .desktop entry should .include %q.", f)
-                       Explain3(
+                       line.Warnf("Packages that install a .desktop entry should .include %q.", f)
+                       Explain(
                                "If *.desktop files contain MimeType keys, the global MIME type",
                                "registry must be updated by desktop-file-utils.  Otherwise, this",
                                "warning is harmless.")
@@ -352,21 +355,21 @@ func (ck *PlistChecker) checkpathShare(p
        case hasPrefix(text, "share/icons/hicolor/") && G.Pkg != nil && G.Pkg.Pkgpath != "graphics/hicolor-icon-theme":
                f := "../../graphics/hicolor-icon-theme/buildlink3.mk"
                if G.Pkg.included[f] == nil {
-                       line.Error1("Packages that install hicolor icons must include %q in the Makefile.", f)
+                       line.Errorf("Packages that install hicolor icons must include %q in the Makefile.", f)
                }
 
        case hasPrefix(text, "share/icons/gnome") && G.Pkg != nil && G.Pkg.Pkgpath != "graphics/gnome-icon-theme":
                f := "../../graphics/gnome-icon-theme/buildlink3.mk"
                if G.Pkg.included[f] == nil {
-                       line.Error1("The package Makefile must include %q.", f)
-                       Explain2(
+                       line.Errorf("The package Makefile must include %q.", f)
+                       Explain(
                                "Packages that install GNOME icons must maintain the icon theme",
                                "cache.")
                }
 
        case hasPrefix(text, "share/doc/html/"):
                if G.opts.WarnPlistDepr {
-                       line.Warn0("Use of \"share/doc/html\" is deprecated. Use \"share/doc/${PKGBASE}\" instead.")
+                       line.Warnf("Use of \"share/doc/html\" is deprecated. Use \"share/doc/${PKGBASE}\" instead.")
                }
 
        case G.Pkg != nil && G.Pkg.EffectivePkgbase != "" && (hasPrefix(text, "share/doc/"+G.Pkg.EffectivePkgbase+"/") ||
@@ -374,29 +377,29 @@ func (ck *PlistChecker) checkpathShare(p
                // Fine.
 
        case text == "share/icons/hicolor/icon-theme.cache" && G.Pkg != nil && G.Pkg.Pkgpath != "graphics/hicolor-icon-theme":
-               line.Error0("This file must not appear in any PLIST file.")
-               Explain3(
+               line.Errorf("This file must not appear in any PLIST file.")
+               Explain(
                        "Remove this line and add the following line to the package Makefile.",
                        "",
                        ".include \"../../graphics/hicolor-icon-theme/buildlink3.mk\"")
 
        case hasPrefix(text, "share/info/"):
-               line.Warn0("Info pages should be installed into info/, not share/info/.")
-               Explain1(
+               line.Warnf("Info pages should be installed into info/, not share/info/.")
+               Explain(
                        "To fix this, you should add INFO_FILES=yes to the package Makefile.")
 
        case hasPrefix(text, "share/locale/") && hasSuffix(text, ".mo"):
                // Fine.
 
        case hasPrefix(text, "share/man/"):
-               line.Warn0("Man pages should be installed into man/, not share/man/.")
+               line.Warnf("Man pages should be installed into man/, not share/man/.")
        }
 }
 
 func (pline *PlistLine) CheckTrailingWhitespace() {
        if hasSuffix(pline.text, " ") || hasSuffix(pline.text, "\t") {
-               pline.line.Error0("pkgsrc does not support filenames ending in white-space.")
-               Explain1(
+               pline.line.Errorf("pkgsrc does not support filenames ending in white-space.")
+               Explain(
                        "Each character in the PLIST is relevant, even trailing white-space.")
        }
 }
@@ -407,7 +410,7 @@ func (pline *PlistLine) CheckDirective(c
        if cmd == "unexec" {
                if m, arg := match1(arg, `^(?:rmdir|\$\{RMDIR\} \%D/)(.*)`); m {
                        if !contains(arg, "true") && !contains(arg, "${TRUE}") {
-                               pline.line.Warn0("Please remove this line. It is no longer necessary.")
+                               pline.line.Warnf("Please remove this line. It is no longer necessary.")
                        }
                }
        }
@@ -417,17 +420,17 @@ func (pline *PlistLine) CheckDirective(c
                switch {
                case contains(arg, "install-info"),
                        contains(arg, "${INSTALL_INFO}"):
-                       line.Warn0("@exec/unexec install-info is deprecated.")
+                       line.Warnf("@exec/unexec install-info is deprecated.")
                case contains(arg, "ldconfig") && !contains(arg, "/usr/bin/true"):
-                       pline.line.Error0("ldconfig must be used with \"||/usr/bin/true\".")
+                       pline.line.Errorf("ldconfig must be used with \"||/usr/bin/true\".")
                }
 
        case "comment":
                // Nothing to do.
 
        case "dirrm":
-               line.Warn0("@dirrm is obsolete. Please remove this line.")
-               Explain3(
+               line.Warnf("@dirrm is obsolete. Please remove this line.")
+               Explain(
                        "Directories are removed automatically when they are empty.",
                        "When a package needs an empty directory, it can use the @pkgdir",
                        "command in the PLIST")
@@ -436,7 +439,7 @@ func (pline *PlistLine) CheckDirective(c
                args := splitOnSpace(arg)
                switch {
                case len(args) != 3:
-                       line.Warn0("Invalid number of arguments for imake-man.")
+                       line.Warnf("Invalid number of arguments for imake-man.")
                case args[2] == "${IMAKE_MANNEWSUFFIX}":
                        pline.warnImakeMannewsuffix()
                }
@@ -445,12 +448,12 @@ func (pline *PlistLine) CheckDirective(c
                // Nothing to check.
 
        default:
-               line.Warn1("Unknown PLIST directive \"@%s\".", cmd)
+               line.Warnf("Unknown PLIST directive \"@%s\".", cmd)
        }
 }
 
 func (pline *PlistLine) warnImakeMannewsuffix() {
-       pline.line.Warn0("IMAKE_MANNEWSUFFIX is not meant to appear in PLISTs.")
+       pline.line.Warnf("IMAKE_MANNEWSUFFIX is not meant to appear in PLISTs.")
        Explain(
                "This is the result of a print-PLIST call that has not been edited",
                "manually by the package maintainer.  Please replace the",

Index: pkgsrc/pkgtools/pkglint/files/globaldata.go
diff -u pkgsrc/pkgtools/pkglint/files/globaldata.go:1.15 pkgsrc/pkgtools/pkglint/files/globaldata.go:1.16
--- pkgsrc/pkgtools/pkglint/files/globaldata.go:1.15    Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/globaldata.go Sun Dec  4 15:28:36 2016
@@ -236,10 +236,10 @@ func parselinesSuggestedUpdates(lines []
                                if m, pkgbase, pkgversion := match2(pkgname, rePkgname); m {
                                        updates = append(updates, SuggestedUpdate{line, pkgbase, pkgversion, comment})
                                } else {
-                                       line.Warn1("Invalid package name %q", pkgname)
+                                       line.Warnf("Invalid package name %q", pkgname)
                                }
                        } else {
-                               line.Warn1("Invalid line format %q", text)
+                               line.Warnf("Invalid line format %q", text)
                        }
                }
        }
@@ -292,8 +292,8 @@ func (gd *GlobalData) loadDocChangesFrom
                if change := parseChange(line); change != nil {
                        changes = append(changes, change)
                } else if len(line.Text) >= 2 && line.Text[0] == '\t' && 'A' <= line.Text[1] && line.Text[1] <= 'Z' {
-                       line.Warn1("Unknown doc/CHANGES line: %q", line.Text)
-                       Explain1("See mk/misc/developer.mk for the rules.")
+                       line.Warnf("Unknown doc/CHANGES line: %q", line.Text)
+                       Explain("See mk/misc/developer.mk for the rules.")
                }
        }
        return changes

Index: pkgsrc/pkgtools/pkglint/files/line.go
diff -u pkgsrc/pkgtools/pkglint/files/line.go:1.11 pkgsrc/pkgtools/pkglint/files/line.go:1.12
--- pkgsrc/pkgtools/pkglint/files/line.go:1.11  Sat Jul  9 09:43:48 2016
+++ pkgsrc/pkgtools/pkglint/files/line.go       Sun Dec  4 15:28:36 2016
@@ -130,27 +130,18 @@ func (line *Line) Errorf(format string, 
        logs(llError, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...))
        line.logAutofix()
 }
-func (line *Line) Error0(format string)             { line.Errorf(format) }
-func (line *Line) Error1(format, arg1 string)       { line.Errorf(format, arg1) }
-func (line *Line) Error2(format, arg1, arg2 string) { line.Errorf(format, arg1, arg2) }
 
 func (line *Line) Warnf(format string, args ...interface{}) {
        line.printSource(G.logOut)
        logs(llWarn, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...))
        line.logAutofix()
 }
-func (line *Line) Warn0(format string)             { line.Warnf(format) }
-func (line *Line) Warn1(format, arg1 string)       { line.Warnf(format, arg1) }
-func (line *Line) Warn2(format, arg1, arg2 string) { line.Warnf(format, arg1, arg2) }
 
 func (line *Line) Notef(format string, args ...interface{}) {
        line.printSource(G.logOut)
        logs(llNote, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...))
        line.logAutofix()
 }
-func (line *Line) Note0(format string)             { line.Notef(format) }
-func (line *Line) Note1(format, arg1 string)       { line.Notef(format, arg1) }
-func (line *Line) Note2(format, arg1, arg2 string) { line.Notef(format, arg1, arg2) }
 
 func (line *Line) String() string {
        return line.Fname + ":" + line.linenos() + ": " + line.Text
@@ -251,7 +242,7 @@ func (line *Line) CheckAbsolutePathname(
 func (line *Line) CheckLength(maxlength int) {
        if len(line.Text) > maxlength {
                line.Warnf("Line too long (should be no more than %d characters).", maxlength)
-               Explain3(
+               Explain(
                        "Back in the old time, terminals with 80x25 characters were common.",
                        "And this is still the default size of many terminal emulators.",
                        "Moderately short lines also make reading easier.")
@@ -265,15 +256,15 @@ func (line *Line) CheckValidCharacters(r
                for _, c := range rest {
                        uni += fmt.Sprintf(" %U", c)
                }
-               line.Warn1("Line contains invalid characters (%s).", uni[1:])
+               line.Warnf("Line contains invalid characters (%s).", uni[1:])
        }
 }
 
 func (line *Line) CheckTrailingWhitespace() {
        if hasSuffix(line.Text, " ") || hasSuffix(line.Text, "\t") {
                if !line.AutofixReplaceRegexp(`\s+\n$`, "\n") {
-                       line.Note0("Trailing white-space.")
-                       Explain2(
+                       line.Notef("Trailing white-space.")
+                       Explain(
                                "When a line ends with some white-space, that space is in most cases",
                                "irrelevant and can be removed.")
                }
@@ -290,8 +281,8 @@ func (line *Line) CheckRcsid(prefixRe Re
        }
 
        if !line.AutofixInsertBefore(suggestedPrefix + "$" + "NetBSD$") {
-               line.Error1("Expected %q.", suggestedPrefix+"$"+"NetBSD$")
-               Explain3(
+               line.Errorf("Expected %q.", suggestedPrefix+"$"+"NetBSD$")
+               Explain(
                        "Several files in pkgsrc must contain the CVS Id, so that their",
                        "current version can be traced back later from a binary package.",
                        "This is to ensure reproducible builds, for example for finding bugs.")

Index: pkgsrc/pkgtools/pkglint/files/mkline.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline.go:1.17 pkgsrc/pkgtools/pkglint/files/mkline.go:1.18
--- pkgsrc/pkgtools/pkglint/files/mkline.go:1.17        Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/mkline.go     Sun Dec  4 15:28:36 2016
@@ -11,10 +11,8 @@ import (
 )
 
 type MkLine struct {
-       Line *Line
-
-       xtype uint8
-       data  interface{} // One of the following mkLine* types
+       *Line
+       data interface{} // One of the following mkLine* types
 }
 type mkLineAssign struct {
        varname    string
@@ -28,6 +26,8 @@ type mkLineAssign struct {
 type mkLineShell struct {
        command string
 }
+type mkLineComment struct{}
+type mkLineEmpty struct{}
 type mkLineConditional struct {
        indent    string
        directive string
@@ -35,6 +35,7 @@ type mkLineConditional struct {
 }
 type mkLineInclude struct {
        mustexist     bool
+       sys           bool
        indent        string
        includeFile   string
        conditionVars string // (filled in later)
@@ -44,21 +45,14 @@ type mkLineDependency struct {
        sources string
 }
 
-func (mkline *MkLine) Error1(format, arg1 string)      { mkline.Line.Error1(format, arg1) }
-func (mkline *MkLine) Warn0(format string)             { mkline.Line.Warn0(format) }
-func (mkline *MkLine) Warn1(format, arg1 string)       { mkline.Line.Warn1(format, arg1) }
-func (mkline *MkLine) Warn2(format, arg1, arg2 string) { mkline.Line.Warn2(format, arg1, arg2) }
-func (mkline *MkLine) Note0(format string)             { mkline.Line.Note0(format) }
-func (mkline *MkLine) Note2(format, arg1, arg2 string) { mkline.Line.Note2(format, arg1, arg2) }
-
 func NewMkLine(line *Line) (mkline *MkLine) {
        mkline = &MkLine{Line: line}
 
        text := line.Text
 
        if hasPrefix(text, " ") {
-               mkline.Warn0("Makefile lines should not start with space characters.")
-               Explain3(
+               mkline.Warnf("Makefile lines should not start with space characters.")
+               Explain(
                        "If you want this line to contain a shell program, use a tab",
                        "character for indentation.  Otherwise please remove the leading",
                        "white-space.")
@@ -73,7 +67,7 @@ func NewMkLine(line *Line) (mkline *MkLi
                                break
                        default:
                                if !line.AutofixReplace(varname+spaceAfterVarname+op, varname+op) {
-                                       line.Warn1("Unnecessary space after variable name %q.", varname)
+                                       line.Warnf("Unnecessary space after variable name %q.", varname)
                                }
                        }
                }
@@ -81,7 +75,6 @@ func NewMkLine(line *Line) (mkline *MkLi
                value = strings.Replace(value, "\\#", "#", -1)
                varparam := varnameParam(varname)
 
-               mkline.xtype = 1
                mkline.data = mkLineAssign{
                        varname,
                        varnameCanon(varname),
@@ -96,45 +89,40 @@ func NewMkLine(line *Line) (mkline *MkLi
 
        if hasPrefix(text, "\t") {
                shellcmd := text[1:]
-               mkline.xtype = 2
                mkline.data = mkLineShell{shellcmd}
                mkline.Tokenize(shellcmd)
                return
        }
 
        if index := strings.IndexByte(text, '#'); index != -1 && strings.TrimSpace(text[:index]) == "" {
-               mkline.xtype = 3
+               mkline.data = mkLineComment{}
                return
        }
 
        if strings.TrimSpace(text) == "" {
-               mkline.xtype = 4
+               mkline.data = mkLineEmpty{}
                return
        }
 
        if m, indent, directive, args := matchMkCond(text); m {
-               mkline.xtype = 5
                mkline.data = mkLineConditional{indent, directive, args}
                return
        }
 
        if m, indent, directive, includefile := MatchMkInclude(text); m {
-               mkline.xtype = 6
-               mkline.data = mkLineInclude{directive == "include", indent, includefile, ""}
+               mkline.data = mkLineInclude{directive == "include", false, indent, includefile, ""}
                return
        }
 
        if m, indent, directive, includefile := match3(text, `^\.(\s*)(s?include)\s+<([^>]+)>\s*(?:#.*)?$`); m {
-               mkline.xtype = 7
-               mkline.data = mkLineInclude{directive == "include", indent, includefile, ""}
+               mkline.data = mkLineInclude{directive == "include", true, indent, includefile, ""}
                return
        }
 
        if m, targets, whitespace, sources := match3(text, `^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$`); m {
-               mkline.xtype = 8
                mkline.data = mkLineDependency{targets, sources}
                if whitespace != "" {
-                       line.Warn0("Space before colon in dependency line.")
+                       line.Warnf("Space before colon in dependency line.")
                }
                return
        }
@@ -143,21 +131,27 @@ func NewMkLine(line *Line) (mkline *MkLi
                return
        }
 
-       line.Error0("Unknown Makefile line format.")
+       line.Errorf("Unknown Makefile line format.")
        return mkline
 }
 
 func (mkline *MkLine) String() string {
        return fmt.Sprintf("%s:%s", mkline.Line.Fname, mkline.Line.linenos())
 }
-func (mkline *MkLine) IsVarassign() bool        { return mkline.xtype == 1 }
-func (mkline *MkLine) IsShellcmd() bool         { return mkline.xtype == 2 }
-func (mkline *MkLine) IsComment() bool          { return mkline.xtype == 3 }
-func (mkline *MkLine) IsEmpty() bool            { return mkline.xtype == 4 }
-func (mkline *MkLine) IsCond() bool             { return mkline.xtype == 5 }
-func (mkline *MkLine) IsInclude() bool          { return mkline.xtype == 6 }
-func (mkline *MkLine) IsSysinclude() bool       { return mkline.xtype == 7 }
-func (mkline *MkLine) IsDependency() bool       { return mkline.xtype == 8 }
+func (mkline *MkLine) IsVarassign() bool { _, ok := mkline.data.(mkLineAssign); return ok }
+func (mkline *MkLine) IsShellcmd() bool  { _, ok := mkline.data.(mkLineShell); return ok }
+func (mkline *MkLine) IsComment() bool   { _, ok := mkline.data.(mkLineComment); return ok }
+func (mkline *MkLine) IsEmpty() bool     { _, ok := mkline.data.(mkLineEmpty); return ok }
+func (mkline *MkLine) IsCond() bool      { _, ok := mkline.data.(mkLineConditional); return ok }
+func (mkline *MkLine) IsInclude() bool {
+       incl, ok := mkline.data.(mkLineInclude)
+       return ok && !incl.sys
+}
+func (mkline *MkLine) IsSysinclude() bool {
+       incl, ok := mkline.data.(mkLineInclude)
+       return ok && incl.sys
+}
+func (mkline *MkLine) IsDependency() bool       { _, ok := mkline.data.(mkLineDependency); return ok }
 func (mkline *MkLine) Varname() string          { return mkline.data.(mkLineAssign).varname }
 func (mkline *MkLine) Varcanon() string         { return mkline.data.(mkLineAssign).varcanon }
 func (mkline *MkLine) Varparam() string         { return mkline.data.(mkLineAssign).varparam }
@@ -195,7 +189,7 @@ func (mkline *MkLine) Check() {
 
        case mkline.IsComment():
                if hasPrefix(mkline.Line.Text, "# url2pkg-marker") {
-                       mkline.Line.Error0("This comment indicates unfinished work (url2pkg).")
+                       mkline.Line.Errorf("This comment indicates unfinished work (url2pkg).")
                }
 
        case mkline.IsInclude():
@@ -221,8 +215,8 @@ func (mkline *MkLine) checkInclude() {
 
        switch {
        case hasSuffix(includefile, "/Makefile"):
-               mkline.Line.Error0("Other Makefiles must not be included directly.")
-               Explain4(
+               mkline.Line.Errorf("Other Makefiles must not be included directly.")
+               Explain(
                        "If you want to include portions of another Makefile, extract",
                        "the common parts and put them into a Makefile.common.  After",
                        "that, both this one and the other package should include the",
@@ -230,7 +224,7 @@ func (mkline *MkLine) checkInclude() {
 
        case includefile == "../../mk/bsd.prefs.mk":
                if path.Base(mkline.Line.Fname) == "buildlink3.mk" {
-                       mkline.Note0("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk.")
+                       mkline.Notef("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk.")
                }
                if G.Pkg != nil {
                        G.Pkg.setSeenBsdPrefsMk()
@@ -242,16 +236,16 @@ func (mkline *MkLine) checkInclude() {
                }
 
        case hasSuffix(includefile, "/x11-links/buildlink3.mk"):
-               mkline.Error1("%s must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead.", includefile)
+               mkline.Errorf("%s must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead.", includefile)
 
        case hasSuffix(includefile, "/jpeg/buildlink3.mk"):
-               mkline.Error1("%s must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead.", includefile)
+               mkline.Errorf("%s must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead.", includefile)
 
        case hasSuffix(includefile, "/intltool/buildlink3.mk"):
-               mkline.Warn0("Please write \"USE_TOOLS+= intltool\" instead of this line.")
+               mkline.Warnf("Please write \"USE_TOOLS+= intltool\" instead of this line.")
 
        case hasSuffix(includefile, "/builtin.mk"):
-               mkline.Line.Error2("%s must not be included directly. Include \"%s/buildlink3.mk\" instead.", includefile, path.Dir(includefile))
+               mkline.Line.Errorf("%s must not be included directly. Include \"%s/buildlink3.mk\" instead.", includefile, path.Dir(includefile))
        }
 }
 
@@ -265,7 +259,7 @@ func (mkline *MkLine) checkCond(forVars 
                if indentation.Len() > 1 {
                        indentation.Pop()
                } else {
-                       mkline.Error1("Unmatched .%s.", directive)
+                       mkline.Errorf("Unmatched .%s.", directive)
                }
        }
 
@@ -284,11 +278,11 @@ func (mkline *MkLine) checkCond(forVars 
        needsArgument := matches(directive, `^(?:if|ifdef|ifndef|elif|for|undef)$`)
        if needsArgument != (args != "") {
                if needsArgument {
-                       mkline.Error1("\".%s\" requires arguments.", directive)
+                       mkline.Errorf("\".%s\" requires arguments.", directive)
                } else {
-                       mkline.Error1("\".%s\" does not take arguments.", directive)
+                       mkline.Errorf("\".%s\" does not take arguments.", directive)
                        if directive == "else" {
-                               mkline.Note0("If you meant \"else if\", use \".elif\".")
+                               mkline.Notef("If you meant \"else if\", use \".elif\".")
                        }
                }
 
@@ -303,15 +297,15 @@ func (mkline *MkLine) checkCond(forVars 
                if m, vars, values := match2(args, `^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$`); m {
                        for _, forvar := range splitOnSpace(vars) {
                                if !G.Infrastructure && hasPrefix(forvar, "_") {
-                                       mkline.Warn1("Variable names starting with an underscore (%s) are reserved for internal pkgsrc use.", forvar)
+                                       mkline.Warnf("Variable names starting with an underscore (%s) are reserved for internal pkgsrc use.", forvar)
                                }
 
                                if matches(forvar, `^[_a-z][_a-z0-9]*$`) {
                                        // Fine.
                                } else if matches(forvar, `[A-Z]`) {
-                                       mkline.Warn0(".for variable names should not contain uppercase letters.")
+                                       mkline.Warnf(".for variable names should not contain uppercase letters.")
                                } else {
-                                       mkline.Error1("Invalid variable name %q.", forvar)
+                                       mkline.Errorf("Invalid variable name %q.", forvar)
                                }
 
                                forVars[forvar] = true
@@ -338,7 +332,7 @@ func (mkline *MkLine) checkCond(forVars 
        } else if directive == "undef" && args != "" {
                for _, uvar := range splitOnSpace(args) {
                        if forVars[uvar] {
-                               mkline.Note0("Using \".undef\" after a \".for\" loop is unnecessary.")
+                               mkline.Notef("Using \".undef\" after a \".for\" loop is unnecessary.")
                        }
                }
        }
@@ -378,8 +372,8 @@ func (mkline *MkLine) checkDependencyRul
                        // TODO: Check for spelling mistakes.
 
                } else if !allowedTargets[target] {
-                       mkline.Warn1("Unusual target %q.", target)
-                       Explain3(
+                       mkline.Warnf("Unusual target %q.", target)
+                       Explain(
                                "If you want to define your own targets, you can \"declare\"",
                                "them by inserting a \".PHONY: my-target\" line before this line.  This",
                                "will tell make(1) to not interpret this target's name as a filename.")
@@ -395,7 +389,7 @@ func (mkline *MkLine) Tokenize(s string)
        p := NewMkParser(mkline.Line, s, true)
        tokens := p.MkTokens()
        if p.Rest() != "" {
-               mkline.Warn1("Pkglint parse error in MkLine.Tokenize at %q.", p.Rest())
+               mkline.Warnf("Pkglint parse error in MkLine.Tokenize at %q.", p.Rest())
        }
        return tokens
 }
@@ -453,7 +447,7 @@ func (mkline *MkLine) checkVarassignDefP
                        mkline.Line.Warnf("The variable %s may not be %s by any package.",
                                varname, needed.HumanString())
                }
-               Explain4(
+               Explain(
                        "The allowed actions for a variable are determined based on the file",
                        "name in which the variable is used or defined.  The exact rules are",
                        "hard-coded into pkglint.  If they seem to be incorrect, please ask",
@@ -477,7 +471,7 @@ func (mkline *MkLine) CheckVaruse(varuse
                !varIsUsed(varname) &&
                !(G.Mk != nil && G.Mk.forVars[varname]) &&
                !containsVarRef(varname) {
-               mkline.Warn1("%s is used but not defined. Spelling mistake?", varname)
+               mkline.Warnf("%s is used but not defined. Spelling mistake?", varname)
        }
 
        mkline.CheckVarusePermissions(varname, vartype, vuc)
@@ -497,7 +491,7 @@ func (mkline *MkLine) CheckVaruse(varuse
        }
 
        if G.globalData.UserDefinedVars[varname] != nil && !G.globalData.SystemBuildDefs[varname] && !G.Mk.buildDefs[varname] {
-               mkline.Warn1("The user-defined variable %s is used but not added to BUILD_DEFS.", varname)
+               mkline.Warnf("The user-defined variable %s is used but not added to BUILD_DEFS.", varname)
                Explain(
                        "When a pkgsrc package is built, many things can be configured by the",
                        "pkgsrc user in the mk.conf file.  All these configurations should be",
@@ -553,7 +547,7 @@ func (mkline *MkLine) CheckVarusePermiss
                done = tool.Predefined && (G.Mk == nil || G.Mk.SeenBsdPrefsMk || G.Pkg == nil || G.Pkg.SeenBsdPrefsMk)
 
                if !done && G.Pkg != nil && !G.Pkg.SeenBsdPrefsMk && G.Mk != nil && !G.Mk.SeenBsdPrefsMk {
-                       mkline.Warn1("To use the tool %q at load time, bsd.prefs.mk has to be included before.", varname)
+                       mkline.Warnf("To use the tool %q at load time, bsd.prefs.mk has to be included before.", varname)
                        done = true
                }
 
@@ -563,14 +557,14 @@ func (mkline *MkLine) CheckVarusePermiss
                                done = true
                        }
                        if defined && !usable {
-                               mkline.Warn1("To use the tool %q at load time, it has to be added to USE_TOOLS before including bsd.prefs.mk.", varname)
+                               mkline.Warnf("To use the tool %q at load time, it has to be added to USE_TOOLS before including bsd.prefs.mk.", varname)
                                done = true
                        }
                }
        }
 
        if !done && isLoadTime && !isIndirect {
-               mkline.Warn1("%s should not be evaluated at load time.", varname)
+               mkline.Warnf("%s should not be evaluated at load time.", varname)
                Explain(
                        "Many variables, especially lists of something, get their values",
                        "incrementally.  Therefore it is generally unsafe to rely on their",
@@ -585,8 +579,8 @@ func (mkline *MkLine) CheckVarusePermiss
        }
 
        if !done && isLoadTime && isIndirect {
-               mkline.Warn1("%s should not be evaluated indirectly at load time.", varname)
-               Explain4(
+               mkline.Warnf("%s should not be evaluated indirectly at load time.", varname)
+               Explain(
                        "The variable on the left-hand side may be evaluated at load time,",
                        "but the variable on the right-hand side may not.  Because of the",
                        "assignment in this line, the variable might be used indirectly",
@@ -601,12 +595,12 @@ func (mkline *MkLine) CheckVarusePermiss
                }
                alternativeFiles := vartype.AllowedFiles(needed)
                if alternativeFiles != "" {
-                       mkline.Warn2("%s may not be used in this file; it would be ok in %s.",
+                       mkline.Warnf("%s may not be used in this file; it would be ok in %s.",
                                varname, alternativeFiles)
                } else {
-                       mkline.Warn1("%s may not be used in any file; it is a write-only variable.", varname)
+                       mkline.Warnf("%s may not be used in any file; it is a write-only variable.", varname)
                }
-               Explain4(
+               Explain(
                        "The allowed actions for a variable are determined based on the file",
                        "name in which the variable is used or defined.  The exact rules are",
                        "hard-coded into pkglint.  If they seem to be incorrect, please ask",
@@ -615,7 +609,7 @@ func (mkline *MkLine) CheckVarusePermiss
 }
 
 func (mkline *MkLine) WarnVaruseLocalbase() {
-       mkline.Warn0("The LOCALBASE variable should not be used by packages.")
+       mkline.Warnf("The LOCALBASE variable should not be used by packages.")
        Explain(
                // from jlam via private mail.
                "Currently, LOCALBASE is typically used in these cases:",
@@ -654,8 +648,8 @@ func (mkline *MkLine) checkVaruseFor(var
                vartype != nil &&
                vartype.kindOfList != lkSpace &&
                needsQuoting != nqDoesntMatter {
-               mkline.Warn1("The variable %s should not be used in .for loops.", varname)
-               Explain4(
+               mkline.Warnf("The variable %s should not be used in .for loops.", varname)
+               Explain(
                        "The .for loop splits its argument at sequences of white-space, as",
                        "opposed to all other places in make(1), which act like the shell.",
                        "Therefore only variables that are split at whitespace or don't",
@@ -682,7 +676,7 @@ func (mkline *MkLine) CheckVaruseShellwo
        }
 
        if mod == ":M*:Q" && !needMstar {
-               mkline.Line.Note0("The :M* modifier is not needed here.")
+               mkline.Line.Notef("The :M* modifier is not needed here.")
 
        } else if needsQuoting == nqYes {
                correctMod := strippedMod + ifelseStr(needMstar, ":M*:Q", ":Q")
@@ -715,7 +709,7 @@ func (mkline *MkLine) CheckVaruseShellwo
                                mkline.Line.Warnf("Please use ${%s%s} instead of ${%s%s} and make sure"+
                                        " the variable appears outside of any quoting characters.", varname, correctMod, varname, mod)
                        }
-                       Explain1(
+                       Explain(
                                "See the pkgsrc guide, section \"quoting guideline\", for details.")
 
                } else if vuc.quoting != vucQuotPlain {
@@ -738,11 +732,11 @@ func (mkline *MkLine) CheckVaruseShellwo
                needExplain := false
                if needsQuoting == nqNo && !mkline.Line.AutofixReplace(bad, good) {
                        needExplain = true
-                       mkline.Warn1("The :Q operator should not be used for ${%s} here.", varname)
+                       mkline.Warnf("The :Q operator should not be used for ${%s} here.", varname)
                }
                if needsQuoting == nqDoesntMatter && !mkline.Line.AutofixReplace(bad, good) {
                        needExplain = true
-                       mkline.Line.Note1("The :Q operator isn't necessary for ${%s} here.", varname)
+                       mkline.Line.Notef("The :Q operator isn't necessary for ${%s} here.", varname)
                }
                if needExplain {
                        Explain(
@@ -770,7 +764,7 @@ func (mkline *MkLine) checkVarassignPyth
        for i, strversion := range strversions {
                iver, err := strconv.Atoi(strversion)
                if err != nil || !(iver > 0) {
-                       mkline.Error1("All values for %s must be positive integers.", varname)
+                       mkline.Errorf("All values for %s must be positive integers.", varname)
                        return
                }
                intversions[i] = iver
@@ -778,8 +772,8 @@ func (mkline *MkLine) checkVarassignPyth
 
        for i, ver := range intversions {
                if i > 0 && ver >= intversions[i-1] {
-                       mkline.Warn1("The values for %s should be in decreasing order.", varname)
-                       Explain2(
+                       mkline.Warnf("The values for %s should be in decreasing order.", varname)
+                       Explain(
                                "If they aren't, it may be possible that needless versions of",
                                "packages are installed.")
                }
@@ -816,7 +810,7 @@ func (mkline *MkLine) checkVarassign() {
                } else if deprecated := G.globalData.Deprecated; deprecated[varname] != "" || deprecated[varcanon] != "" {
                        // Ok
                } else {
-                       mkline.Warn1("%s is defined but not used. Spelling mistake?", varname)
+                       mkline.Warnf("%s is defined but not used. Spelling mistake?", varname)
                }
        }
 
@@ -852,9 +846,9 @@ func (mkline *MkLine) checkVarassign() {
        }
 
        if fix := G.globalData.Deprecated[varname]; fix != "" {
-               mkline.Warn2("Definition of %s is deprecated. %s", varname, fix)
+               mkline.Warnf("Definition of %s is deprecated. %s", varname, fix)
        } else if fix := G.globalData.Deprecated[varcanon]; fix != "" {
-               mkline.Warn2("Definition of %s is deprecated. %s", varname, fix)
+               mkline.Warnf("Definition of %s is deprecated. %s", varname, fix)
        }
 
        mkline.checkVarassignPlistComment(varname, value)
@@ -931,11 +925,11 @@ func (mkline *MkLine) checkVarassignSpec
        value := mkline.Value()
 
        if contains(value, "/etc/rc.d") {
-               mkline.Warn0("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.")
+               mkline.Warnf("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.")
        }
 
        if hasPrefix(varname, "_") && !G.Infrastructure {
-               mkline.Warn1("Variable names starting with an underscore (%s) are reserved for internal pkgsrc use.", varname)
+               mkline.Warnf("Variable names starting with an underscore (%s) are reserved for internal pkgsrc use.", varname)
        }
 
        if varname == "PERL5_PACKLIST" && G.Pkg != nil {
@@ -944,14 +938,14 @@ func (mkline *MkLine) checkVarassignSpec
 
                        ucvalue, ucguess := strings.ToUpper(value), strings.ToUpper(guess)
                        if ucvalue != ucguess && ucvalue != "${PERL5_SITEARCH}/"+ucguess {
-                               mkline.Warn1("Unusual value for PERL5_PACKLIST -- %q expected.", guess)
+                               mkline.Warnf("Unusual value for PERL5_PACKLIST -- %q expected.", guess)
                        }
                }
        }
 
        if varname == "CONFIGURE_ARGS" && contains(value, "=${PREFIX}/share/kde") {
-               mkline.Note0("Please .include \"../../meta-pkgs/kde3/kde3.mk\" instead of this line.")
-               Explain3(
+               mkline.Notef("Please .include \"../../meta-pkgs/kde3/kde3.mk\" instead of this line.")
+               Explain(
                        "That file does many things automatically and consistently that this",
                        "package also does.  When using kde3.mk, you can probably also leave",
                        "out some explicit dependencies.")
@@ -962,7 +956,7 @@ func (mkline *MkLine) checkVarassignSpec
        }
 
        if mkline.VarassignComment() == "# defined" && !hasSuffix(varname, "_MK") && !hasSuffix(varname, "_COMMON") {
-               mkline.Note0("Please use \"# empty\", \"# none\" or \"yes\" instead of \"# defined\".")
+               mkline.Notef("Please use \"# empty\", \"# none\" or \"yes\" instead of \"# defined\".")
                Explain(
                        "The value #defined says something about the state of the variable,",
                        "but not what that _means_.  In some cases a variable that is defined",
@@ -978,11 +972,11 @@ func (mkline *MkLine) checkVarassignSpec
        }
 
        if hasPrefix(varname, "SITES_") {
-               mkline.Warn0("SITES_* is deprecated. Please use SITES.* instead.")
+               mkline.Warnf("SITES_* is deprecated. Please use SITES.* instead.")
        }
 
        if varname == "PKG_SKIP_REASON" && G.Mk.indentation.DependsOn("OPSYS") {
-               mkline.Note0("Consider defining NOT_FOR_PLATFORM instead of setting PKG_SKIP_REASON depending on ${OPSYS}.")
+               mkline.Notef("Consider defining NOT_FOR_PLATFORM instead of setting PKG_SKIP_REASON depending on ${OPSYS}.")
        }
 }
 
@@ -993,7 +987,7 @@ func (mkline *MkLine) checkVarassignBsdP
                        return
                }
 
-               mkline.Warn0("Please include \"../../mk/bsd.prefs.mk\" before using \"?=\".")
+               mkline.Warnf("Please include \"../../mk/bsd.prefs.mk\" before using \"?=\".")
                Explain(
                        "The ?= operator is used to provide a default value to a variable.",
                        "In pkgsrc, many variables can be set by the pkgsrc user in the",
@@ -1010,7 +1004,7 @@ func (mkline *MkLine) checkVarassignBsdP
 func (mkline *MkLine) checkVarassignPlistComment(varname, value string) {
        if false && // This is currently neither correct nor helpful
                contains(value, "@comment") && !matches(value, `="@comment "`) {
-               mkline.Warn1("Please don't use @comment in %s.", varname)
+               mkline.Warnf("Please don't use @comment in %s.", varname)
                Explain(
                        "If you are defining a PLIST conditional here, use one of the",
                        "following patterns instead:",
@@ -1048,7 +1042,7 @@ func (mkline *MkLine) CheckVartype(varna
 
        if op == opAssignAppend {
                if vartype != nil && !vartype.MayBeAppendedTo() {
-                       mkline.Warn0("The \"+=\" operator should only be used with lists.")
+                       mkline.Warnf("The \"+=\" operator should only be used with lists.")
                }
        }
 
@@ -1111,7 +1105,7 @@ func (mkline *MkLine) checkText(text str
        }
 
        if contains(text, "${WRKSRC}/..") {
-               mkline.Warn0("Building the package should take place entirely inside ${WRKSRC}, not \"${WRKSRC}/..\".")
+               mkline.Warnf("Building the package should take place entirely inside ${WRKSRC}, not \"${WRKSRC}/..\".")
                Explain(
                        "WRKSRC should be defined so that there is no need to do anything",
                        "outside of this directory.",
@@ -1128,7 +1122,7 @@ func (mkline *MkLine) checkText(text str
 
        // Note: A simple -R is not detected, as the rate of false positives is too high.
        if m, flag := match1(text, `\b(-Wl,--rpath,|-Wl,-rpath-link,|-Wl,-rpath,|-Wl,-R)\b`); m {
-               mkline.Warn1("Please use ${COMPILER_RPATH_FLAG} instead of %q.", flag)
+               mkline.Warnf("Please use ${COMPILER_RPATH_FLAG} instead of %q.", flag)
        }
 
        rest := text
@@ -1147,7 +1141,7 @@ func (mkline *MkLine) checkText(text str
                        instead = G.globalData.Deprecated[varcanon]
                }
                if instead != "" {
-                       mkline.Warn2("Use of %q is deprecated. %s", varname, instead)
+                       mkline.Warnf("Use of %q is deprecated. %s", varname, instead)
                }
        }
 }
@@ -1160,7 +1154,7 @@ func (mkline *MkLine) CheckCond() {
        p := NewMkParser(mkline.Line, mkline.Args(), false)
        cond := p.MkCond()
        if !p.EOF() {
-               mkline.Warn1("Invalid conditional %q.", mkline.Args())
+               mkline.Warnf("Invalid conditional %q.", mkline.Args())
                return
        }
 
@@ -1168,7 +1162,7 @@ func (mkline *MkLine) CheckCond() {
                varuse := node.args[0].(MkVarUse)
                varname := varuse.varname
                if matches(varname, `^\$.*:[MN]`) {
-                       mkline.Warn0("The empty() function takes a variable name as parameter, not a variable expression.")
+                       mkline.Warnf("The empty() function takes a variable name as parameter, not a variable expression.")
                        Explain(
                                "Instead of empty(${VARNAME:Mpattern}), you should write either",
                                "of the following:",
@@ -1195,15 +1189,7 @@ func (mkline *MkLine) CheckCond() {
                varmods := varuse.modifiers
                value := node.args[2].(string)
                if len(varmods) == 0 {
-                       mkline.CheckVartype(varname, opUse, value, "")
-                       if varname == "PKGSRC_COMPILER" {
-                               op := node.args[1].(string)
-                               mkline.Line.Warnf("Use ${PKGSRC_COMPILER:%s%s} instead of the %s operator.", ifelseStr(op == "==", "M", "N"), value, op)
-                               Explain(
-                                       "The PKGSRC_COMPILER can be a list of chained compilers, e.g. \"ccache",
-                                       "distcc clang\".  Therefore, comparing it using == or != leads to",
-                                       "wrong results in these cases.")
-                       }
+                       mkline.checkCompareVarStr(varname, node.args[1].(string), value)
                } else if len(varmods) == 1 && matches(varmods[0], `^[MN]`) && value != "" {
                        mkline.CheckVartype(varname, opUseMatch, value, "")
                }
@@ -1212,6 +1198,18 @@ func (mkline *MkLine) CheckCond() {
        mkline.rememberUsedVariables(cond)
 }
 
+func (mkline *MkLine) checkCompareVarStr(varname, op, value string) {
+       mkline.CheckVartype(varname, opUseCompare, value, "")
+
+       if varname == "PKGSRC_COMPILER" {
+               mkline.Line.Warnf("Use ${PKGSRC_COMPILER:%s%s} instead of the %s operator.", ifelseStr(op == "==", "M", "N"), value, op)
+               Explain(
+                       "The PKGSRC_COMPILER can be a list of chained compilers, e.g. \"ccache",
+                       "distcc clang\".  Therefore, comparing it using == or != leads to",
+                       "wrong results in these cases.")
+       }
+}
+
 func (mkline *MkLine) rememberUsedVariables(cond *Tree) {
        if G.Mk == nil {
                return
@@ -1245,12 +1243,12 @@ func (mkline *MkLine) CheckValidCharacte
                for _, c := range rest {
                        uni += fmt.Sprintf(" %U", c)
                }
-               mkline.Warn2("%s contains invalid characters (%s).", mkline.Varname(), uni[1:])
+               mkline.Warnf("%s contains invalid characters (%s).", mkline.Varname(), uni[1:])
        }
 }
 
 func (mkline *MkLine) explainRelativeDirs() {
-       Explain3(
+       Explain(
                "Directories in the form \"../../category/package\" make it easier to",
                "move a package around in pkgsrc, for example from pkgsrc-wip to the",
                "main pkgsrc repository.")
@@ -1262,12 +1260,12 @@ func (mkline *MkLine) CheckRelativePkgdi
 
        if m, otherpkgpath := match1(pkgdir, `^(?:\./)?\.\./\.\./([^/]+/[^/]+)$`); m {
                if !fileExists(G.globalData.Pkgsrcdir + "/" + otherpkgpath + "/Makefile") {
-                       mkline.Error1("There is no package in %q.", otherpkgpath)
+                       mkline.Errorf("There is no package in %q.", otherpkgpath)
                }
 
        } else if !containsVarRef(pkgdir) {
-               mkline.Warn1("%q is not a valid relative package directory.", pkgdir)
-               Explain3(
+               mkline.Warnf("%q is not a valid relative package directory.", pkgdir)
+               Explain(
                        "A relative pathname always starts with \"../../\", followed",
                        "by a category, a slash and a the directory name of the package.",
                        "For example, \"../../misc/screen\" is a valid relative pathname.")
@@ -1276,7 +1274,7 @@ func (mkline *MkLine) CheckRelativePkgdi
 
 func (mkline *MkLine) CheckRelativePath(path string, mustExist bool) {
        if !G.Wip && contains(path, "/wip/") {
-               mkline.Line.Error0("A main pkgsrc package must not depend on a pkgsrc-wip package.")
+               mkline.Line.Errorf("A main pkgsrc package must not depend on a pkgsrc-wip package.")
        }
 
        resolvedPath := resolveVarsInRelativePath(path, true)
@@ -1290,7 +1288,7 @@ func (mkline *MkLine) CheckRelativePath(
        }
        if _, err := os.Stat(abs); err != nil {
                if mustExist {
-                       mkline.Error1("%q does not exist.", resolvedPath)
+                       mkline.Errorf("%q does not exist.", resolvedPath)
                }
                return
        }
@@ -1299,7 +1297,7 @@ func (mkline *MkLine) CheckRelativePath(
                !matches(path, `^\.\./\.\./[^/]+/[^/]`) &&
                !(G.CurPkgsrcdir == ".." && hasPrefix(path, "../mk/")) && // For category Makefiles.
                !hasPrefix(path, "../../mk/") {
-               mkline.Warn1("Invalid relative path %q.", path)
+               mkline.Warnf("Invalid relative path %q.", path)
        }
 }
 
@@ -1750,3 +1748,7 @@ func (ind *Indentation) Varnames() strin
        }
        return varnames
 }
+
+func MatchMkInclude(text string) (m bool, indentation, directive, filename string) {
+       return match3(text, `^\.(\s*)(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$`)
+}

Index: pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.18 pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.19
--- pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.18   Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/mkline_test.go        Sun Dec  4 15:28:36 2016
@@ -323,7 +323,7 @@ func (s *Suite) Test_MkLine_checkVarassi
        G.globalData.InitVartypes()
 
        G.Mk = s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "ac_cv_libpari_libs+=\t-L${BUILDLINK_PREFIX.pari}/lib") // From math/clisp-pari/Makefile, rev. 1.8
 
        G.Mk.mklines[1].checkVarassign()
@@ -375,7 +375,7 @@ func (s *Suite) Test_MkLine_CheckVaruseP
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("options.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "COMMENT=\t${GAMES_USER}",
                "COMMENT:=\t${PKGBASE}",
                "PYPKGPREFIX=${PKGBASE}")
@@ -397,7 +397,7 @@ func (s *Suite) Test_MkLine_CheckVaruseP
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("options.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "WRKSRC:=${.CURDIR}")
 
        mklines.Check()
@@ -418,7 +418,7 @@ func (s *Suite) Test_MkLines_Check__extr
        G.globalData.InitVartypes()
        G.Pkg = NewPackage("category/pkgbase")
        G.Mk = s.NewMkLines("options.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                ".for word in ${PKG_FAIL_REASON}",
                "PYTHON_VERSIONS_ACCEPTED=\t27 35 30",
                "CONFIGURE_ARGS+=\t--sharedir=${PREFIX}/share/kde",
@@ -529,7 +529,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.RegisterTool(&Tool{Name: "sort", Varname: "SORT", Predefined: true})
        G.Pkg = NewPackage("category/pkgbase")
        G.Mk = s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "GENERATE_PLIST= cd ${DESTDIR}${PREFIX}; ${FIND} * \\( -type f -or -type l \\) | ${SORT};")
 
        G.Mk.determineDefinedVariables()
@@ -543,7 +543,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "EGDIR=\t${EGDIR}/${MACHINE_GNU_PLATFORM}")
 
        G.Mk.mklines[1].Check()
@@ -563,7 +563,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.RegisterTool(&Tool{Name: "bash", Varname: "BASH", Predefined: true})
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5:Q} ; ${ECHO} ) | ${BASH} ./install",
                "\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5} ; ${ECHO} ) | ${BASH} ./install")
 
@@ -580,7 +580,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "MASTER_SITES=${HOMEPAGE}archive/")
 
        G.Mk.mklines[1].Check()
@@ -599,7 +599,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.RegisterTool(&Tool{Name: "awk", Varname: "AWK", Predefined: true})
        s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true})
        G.Mk = s.NewMkLines("xpi.mk",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "\t id=$$(${AWK} '{print}' < ${WRKSRC}/idfile) && echo \"$$id\"",
                "\t id=`${AWK} '{print}' < ${WRKSRC}/idfile` && echo \"$$id\"")
 
@@ -616,7 +616,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("x11/mlterm/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& ${LDFLAGS:M*:Q}|g'",
                "SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& '${LDFLAGS:M*:Q}'|g'")
 
@@ -631,7 +631,7 @@ func (s *Suite) Test_MkLines_Check__MAST
        s.RegisterMasterSite("MASTER_SITE_GITHUB", "https://github.com/";)
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("devel/catch/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "HOMEPAGE=\t${MASTER_SITE_GITHUB:=philsquared/Catch/}",
                "HOMEPAGE=\t${MASTER_SITE_GITHUB}",
                "HOMEPAGE=\t${MASTER_SITES}",
@@ -652,7 +652,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.RegisterTool(&Tool{Name: "sh", Varname: "SH", Predefined: true})
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("x11/labltk/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "CONFIGURE_ARGS+=\t-tklibs \"`${SH} -c '${ECHO} $$TK_LD_FLAGS'`\"")
 
        G.Mk.mklines[1].Check()
@@ -687,7 +687,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("audio/jack-rack/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "LADSPA_PLUGIN_PATH?=\t${PREFIX}/lib/ladspa",
                "CPPFLAGS+=\t\t-DLADSPA_PATH=\"\\\"${LADSPA_PLUGIN_PATH}\\\"\"")
 
@@ -700,7 +700,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("x11/eterm/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "DISTFILES=\t${DEFAULT_DISTFILES} ${PIXMAP_FILES}")
 
        G.Mk.Check()
@@ -713,7 +713,7 @@ func (s *Suite) Test_MkLine_variableNeed
        s.RegisterMasterSite("MASTER_SITE_GNOME", "http://ftp.gnome.org/";)
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("x11/gtk3/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "MASTER_SITES=\tftp://ftp.gtk.org/${PKGNAME}/ ${MASTER_SITE_GNOME:=subdir/}")
 
        G.Mk.mklines[1].checkVarassignVaruse()
@@ -728,7 +728,7 @@ func (s *Suite) Test_MkLine_variableNeed
        G.globalData.Tools.RegisterVarname("tar", "TAR")
 
        mklines := s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "CONFIGURE_ENV+=\tSYS_TAR_COMMAND_PATH=${TOOLS_TAR:Q}")
 
@@ -754,7 +754,7 @@ func (s *Suite) Test_MkLine_CheckCond_co
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("security/openssl/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                ".if ${PKGSRC_COMPILER} == \"gcc\" && ${CC} == \"cc\"",
                ".endif")
 
@@ -781,7 +781,7 @@ func (s *Suite) Test_MkLine_Pkgmandir(c 
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("chat/ircII/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/man",
                "CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/${PKGMANDIR}")
 
@@ -794,7 +794,7 @@ func (s *Suite) Test_MkLine_Check_CFLAGS
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        G.Mk = s.NewMkLines("chat/pidgin-icb/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "CFLAGS+=\t`pkg-config pidgin --cflags`")
        mkline := G.Mk.mklines[1]
 
@@ -812,7 +812,7 @@ func (s *Suite) Test_MkLine_Check_VERSIO
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("geography/viking/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=viking/}${VERSION}/")
 
        mklines.Check()
@@ -825,7 +825,7 @@ func (s *Suite) Test_MkLine_Check_shell_
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("x11/lablgtk1/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "CONFIGURE_ENV+=\tCC=${CC}")
 
        mklines.Check()
@@ -839,7 +839,7 @@ func (s *Suite) Test_MkLine_shell_varuse
        s.UseCommandLine(c, "-Wall")
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("x11/motif/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "post-patch:",
                "\tfiles=`${GREP} -l \".fB$${name}.fP(3)\" *.3`")
 
@@ -863,7 +863,7 @@ func (s *Suite) Test_MkLine_getVariableT
 func (s *Suite) Test_MkLine_CheckVartype_CFLAGS(c *check.C) {
        G.globalData.InitVartypes()
        mklines := s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "CPPFLAGS.SunOS+=\t-DPIPECOMMAND=\\\"/usr/sbin/sendmail -bs %s\\\"")
 
        mklines.Check()

Index: pkgsrc/pkgtools/pkglint/files/package.go
diff -u pkgsrc/pkgtools/pkglint/files/package.go:1.13 pkgsrc/pkgtools/pkglint/files/package.go:1.14
--- pkgsrc/pkgtools/pkglint/files/package.go:1.13       Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/package.go    Sun Dec  4 15:28:36 2016
@@ -106,7 +106,7 @@ func (pkg *Package) checkPossibleDowngra
                changeVersion := regcomp(`nb\d+$`).ReplaceAllString(change.Version, "")
                if pkgverCmp(pkgversion, changeVersion) < 0 {
                        mkline.Line.Warnf("The package is being downgraded from %s (see %s) to %s", change.Version, change.Line.ReferenceFrom(mkline.Line), pkgversion)
-                       Explain4(
+                       Explain(
                                "The files in doc/CHANGES-*, in which all version changes are",
                                "recorded, have a higher version number than what the package says.",
                                "This is unusual, since packages are typically upgraded instead of",
@@ -128,7 +128,7 @@ func (pkg *Package) checklinesBuildlink3
                        if m, bl3 := match1(file, `^\.\./\.\./(.*)/buildlink3\.mk`); m {
                                includedFiles[bl3] = mkline
                                if pkg.bl3[bl3] == nil {
-                                       mkline.Warn1("%s/buildlink3.mk is included by this file but not by the package.", bl3)
+                                       mkline.Warnf("%s/buildlink3.mk is included by this file but not by the package.", bl3)
                                }
                        }
                }
@@ -205,12 +205,12 @@ func checkdirPackage(pkgpath string) {
 
        if G.opts.CheckDistinfo && G.opts.CheckPatches {
                if havePatches && !haveDistinfo {
-                       NewLineWhole(G.CurrentDir+"/"+pkg.DistinfoFile).Warn1("File not found. Please run \"%s makepatchsum\".", confMake)
+                       NewLineWhole(G.CurrentDir+"/"+pkg.DistinfoFile).Warnf("File not found. Please run \"%s makepatchsum\".", confMake)
                }
        }
 
        if !isEmptyDir(G.CurrentDir + "/scripts") {
-               NewLineWhole(G.CurrentDir + "/scripts").Warn0("This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's 
Makefile.")
+               NewLineWhole(G.CurrentDir + "/scripts").Warnf("This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's 
Makefile.")
        }
 }
 
@@ -286,7 +286,7 @@ func (pkg *Package) readMakefile(fname s
                        includeFile = resolveVariableRefs(resolveVarsInRelativePath(inc, true))
                        if containsVarRef(includeFile) {
                                if !contains(fname, "/mk/") {
-                                       line.Note1("Skipping include file %q. This may result in false warnings.", includeFile)
+                                       line.Notef("Skipping include file %q. This may result in false warnings.", includeFile)
                                }
                                includeFile = ""
                        }
@@ -308,7 +308,7 @@ func (pkg *Package) readMakefile(fname s
                        G.Pkg.included[includeFile] = line
 
                        if matches(includeFile, `^\.\./[^./][^/]*/[^/]+`) {
-                               mkline.Warn0("References to other packages should look like \"../../category/package\", not \"../package\".")
+                               mkline.Warnf("References to other packages should look like \"../../category/package\", not \"../package\".")
                                mkline.explainRelativeDirs()
                        }
 
@@ -331,7 +331,7 @@ func (pkg *Package) readMakefile(fname s
                                        if dirname != G.CurrentDir { // Prevent unnecessary syscalls
                                                dirname = G.CurrentDir
                                                if !fileExists(dirname + "/" + includeFile) {
-                                                       line.Error1("Cannot read %q.", dirname+"/"+includeFile)
+                                                       line.Errorf("Cannot read %q.", dirname+"/"+includeFile)
                                                        return false
                                                }
                                        }
@@ -377,25 +377,25 @@ func (pkg *Package) checkfilePackageMake
                vardef["META_PACKAGE"] == nil &&
                !fileExists(G.CurrentDir+"/"+pkg.Pkgdir+"/PLIST") &&
                !fileExists(G.CurrentDir+"/"+pkg.Pkgdir+"/PLIST.common") {
-               NewLineWhole(fname).Warn0("Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?")
+               NewLineWhole(fname).Warnf("Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?")
        }
 
        if (vardef["NO_CHECKSUM"] != nil || vardef["META_PACKAGE"] != nil) && isEmptyDir(G.CurrentDir+"/"+pkg.Patchdir) {
                if distinfoFile := G.CurrentDir + "/" + pkg.DistinfoFile; fileExists(distinfoFile) {
-                       NewLineWhole(distinfoFile).Warn0("This file should not exist if NO_CHECKSUM or META_PACKAGE is set.")
+                       NewLineWhole(distinfoFile).Warnf("This file should not exist if NO_CHECKSUM or META_PACKAGE is set.")
                }
        } else {
                if distinfoFile := G.CurrentDir + "/" + pkg.DistinfoFile; !containsVarRef(distinfoFile) && !fileExists(distinfoFile) {
-                       NewLineWhole(distinfoFile).Warn1("File not found. Please run \"%s makesum\".", confMake)
+                       NewLineWhole(distinfoFile).Warnf("File not found. Please run \"%s makesum\".", confMake)
                }
        }
 
        if perlLine, noconfLine := vardef["REPLACE_PERL"], vardef["NO_CONFIGURE"]; perlLine != nil && noconfLine != nil {
-               perlLine.Warn1("REPLACE_PERL is ignored when NO_CONFIGURE is set (in %s)", noconfLine.Line.ReferenceFrom(perlLine.Line))
+               perlLine.Warnf("REPLACE_PERL is ignored when NO_CONFIGURE is set (in %s)", noconfLine.Line.ReferenceFrom(perlLine.Line))
        }
 
        if vardef["LICENSE"] == nil && vardef["META_PACKAGE"] == nil {
-               NewLineWhole(fname).Error0("Each package must define its LICENSE.")
+               NewLineWhole(fname).Errorf("Each package must define its LICENSE.")
        }
 
        if gnuLine, useLine := vardef["GNU_CONFIGURE"], vardef["USE_LANGUAGES"]; gnuLine != nil && useLine != nil {
@@ -405,7 +405,7 @@ func (pkg *Package) checkfilePackageMake
                        // really not needed.
 
                } else if !matches(useLine.Value(), `(?:^|\s+)(?:c|c99|objc)(?:\s+|$)`) {
-                       gnuLine.Warn1("GNU_CONFIGURE almost always needs a C compiler, but \"c\" is not added to USE_LANGUAGES in %s.",
+                       gnuLine.Warnf("GNU_CONFIGURE almost always needs a C compiler, but \"c\" is not added to USE_LANGUAGES in %s.",
                                useLine.Line.ReferenceFrom(gnuLine.Line))
                }
        }
@@ -414,12 +414,12 @@ func (pkg *Package) checkfilePackageMake
        pkg.checkPossibleDowngrade()
 
        if vardef["COMMENT"] == nil {
-               NewLineWhole(fname).Warn0("No COMMENT given.")
+               NewLineWhole(fname).Warnf("No COMMENT given.")
        }
 
        if imake, x11 := vardef["USE_IMAKE"], vardef["USE_X11"]; imake != nil && x11 != nil {
                if !hasSuffix(x11.Line.Fname, "/mk/x11.buildlink3.mk") {
-                       imake.Line.Note1("USE_IMAKE makes USE_X11 in %s superfluous.", x11.Line.ReferenceFrom(imake.Line))
+                       imake.Line.Notef("USE_IMAKE makes USE_X11 in %s superfluous.", x11.Line.ReferenceFrom(imake.Line))
                }
        }
 
@@ -459,11 +459,11 @@ func (pkg *Package) determineEffectivePk
        }
 
        if pkgname != "" && pkgname == distname && pkgnameLine.VarassignComment() == "" {
-               pkgnameLine.Note0("PKGNAME is ${DISTNAME} by default. You probably don't need to define PKGNAME.")
+               pkgnameLine.Notef("PKGNAME is ${DISTNAME} by default. You probably don't need to define PKGNAME.")
        }
 
        if pkgname == "" && distname != "" && !containsVarRef(distname) && !matches(distname, rePkgname) {
-               distnameLine.Warn0("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.")
+               distnameLine.Warnf("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.")
        }
 
        if pkgname != "" && !containsVarRef(pkgname) {
@@ -546,14 +546,14 @@ func (pkg *Package) checkUpdate() {
                        cmp := pkgverCmp(pkg.EffectivePkgversion, suggver)
                        switch {
                        case cmp < 0:
-                               pkgnameLine.Warn2("This package should be updated to %s%s.", sugg.Version, comment)
-                               Explain2(
+                               pkgnameLine.Warnf("This package should be updated to %s%s.", sugg.Version, comment)
+                               Explain(
                                        "The wishlist for package updates in doc/TODO mentions that a newer",
                                        "version of this package is available.")
                        case cmp > 0:
-                               pkgnameLine.Note2("This package is newer than the update request to %s%s.", suggver, comment)
+                               pkgnameLine.Notef("This package is newer than the update request to %s%s.", suggver, comment)
                        default:
-                               pkgnameLine.Note2("The update request to %s from doc/TODO%s has been done.", suggver, comment)
+                               pkgnameLine.Notef("The update request to %s from doc/TODO%s has been done.", suggver, comment)
                        }
                }
        }
@@ -698,9 +698,9 @@ func (pkg *Package) ChecklinesPackageMak
 
                        if belowText, exists := below[varcanon]; exists {
                                if belowText != "" {
-                                       line.Warn2("%s appears too late. Please put it below %s.", varcanon, belowText)
+                                       line.Warnf("%s appears too late. Please put it below %s.", varcanon, belowText)
                                } else {
-                                       line.Warn1("%s appears too late. It should be the very first definition.", varcanon)
+                                       line.Warnf("%s appears too late. It should be the very first definition.", varcanon)
                                }
                                lineno++
                                continue
@@ -716,12 +716,12 @@ func (pkg *Package) ChecklinesPackageMak
                        switch {
                        case !(varindex < len(vars)):
                                if sections[sectindex].count != optional {
-                                       line.Warn0("Empty line expected.")
+                                       line.Warnf("Empty line expected.")
                                }
                                nextSection = true
 
                        case varcanon != vars[varindex].varname:
-                               line.Warn2("Expected %s, but found %s.", vars[varindex].varname, varcanon)
+                               line.Warnf("Expected %s, but found %s.", vars[varindex].varname, varcanon)
                                lineno++
 
                        default:
@@ -736,7 +736,7 @@ func (pkg *Package) ChecklinesPackageMak
                default:
                        for varindex < len(vars) {
                                if vars[varindex].count == once && !maySkipSection {
-                                       line.Warn1("The canonical position for the required variable %s is here.", vars[varindex].varname)
+                                       line.Warnf("The canonical position for the required variable %s is here.", vars[varindex].varname)
                                        Explain(
                                                "In simple package Makefiles, some common variables should be",
                                                "arranged in a specific order.",
@@ -776,7 +776,7 @@ func (mklines *MkLines) checkForUsedComm
 
        insertLine := lines[i]
        if !insertLine.AutofixInsertBefore(expected) {
-               insertLine.Warn1("Please add a line %q here.", expected)
+               insertLine.Warnf("Please add a line %q here.", expected)
                Explain(
                        "Since Makefile.common files usually don't have any comments and",
                        "therefore not a clearly defined interface, they should at least",
@@ -820,14 +820,14 @@ func (pkg *Package) checkLocallyModified
 
        if isLocallyModified(fname) {
                if owner != "" {
-                       NewLineWhole(fname).Warn1("Don't commit changes to this file without asking the OWNER, %s.", owner)
-                       Explain2(
+                       NewLineWhole(fname).Warnf("Don't commit changes to this file without asking the OWNER, %s.", owner)
+                       Explain(
                                "See the pkgsrc guide, section \"Package components\",",
                                "keyword \"owner\", for more information.")
                }
                if maintainer != "" {
-                       NewLineWhole(fname).Note1("Please only commit changes that %s would approve.", maintainer)
-                       Explain2(
+                       NewLineWhole(fname).Notef("Please only commit changes that %s would approve.", maintainer)
+                       Explain(
                                "See the pkgsrc guide, section \"Package components\",",
                                "keyword \"maintainer\", for more information.")
                }
Index: pkgsrc/pkgtools/pkglint/files/shell.go
diff -u pkgsrc/pkgtools/pkglint/files/shell.go:1.13 pkgsrc/pkgtools/pkglint/files/shell.go:1.14
--- pkgsrc/pkgtools/pkglint/files/shell.go:1.13 Tue Sep  6 20:54:21 2016
+++ pkgsrc/pkgtools/pkglint/files/shell.go      Sun Dec  4 15:28:36 2016
@@ -44,10 +44,10 @@ func (shline *ShellLine) CheckWord(token
        }
 
        if matches(token, `\$\{PREFIX\}/man(?:$|/)`) {
-               line.Warn0("Please use ${PKGMANDIR} instead of \"man\".")
+               line.Warnf("Please use ${PKGMANDIR} instead of \"man\".")
        }
        if contains(token, "etc/rc.d") {
-               line.Warn0("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.")
+               line.Warnf("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.")
        }
 
        parser := NewMkParser(line, token, false)
@@ -89,7 +89,7 @@ outer:
                                repl.AdvanceRegexp(`^\$\$(\$)\$`):
                                shvarname := repl.m[1]
                                if G.opts.WarnQuoting && checkQuoting && shline.variableNeedsQuoting(shvarname) {
-                                       line.Warn1("Unquoted shell variable %q.", shvarname)
+                                       line.Warnf("Unquoted shell variable %q.", shvarname)
                                        Explain(
                                                "When a shell variable contains white-space, it is expanded (split",
                                                "into multiple words) when it is written as $variable in a shell",
@@ -106,20 +106,20 @@ outer:
                                                "\t# copies one file, as intended")
                                }
                        case repl.AdvanceStr("$@"):
-                               line.Warn2("Please use %q instead of %q.", "${.TARGET}", "$@")
-                               Explain2(
+                               line.Warnf("Please use %q instead of %q.", "${.TARGET}", "$@")
+                               Explain(
                                        "It is more readable and prevents confusion with the shell variable of",
                                        "the same name.")
 
                        case repl.AdvanceStr("$$@"):
-                               line.Warn0("The $@ shell variable should only be used in double quotes.")
+                               line.Warnf("The $@ shell variable should only be used in double quotes.")
 
                        case repl.AdvanceStr("$$?"):
-                               line.Warn0("The $? shell variable is often not available in \"set -e\" mode.")
+                               line.Warnf("The $? shell variable is often not available in \"set -e\" mode.")
 
                        case repl.AdvanceStr("$$("):
-                               line.Warn0("Invoking subshells via $(...) is not portable enough.")
-                               Explain2(
+                               line.Warnf("Invoking subshells via $(...) is not portable enough.")
+                               Explain(
                                        "The Solaris /bin/sh does not know this way to execute a command in a",
                                        "subshell.  Please use backticks (`...`) as a replacement.")
 
@@ -158,7 +158,7 @@ outer:
                                repl.AdvanceRegexp(`^\$\$(?:\w+|[!#?@]|\$\$)`):
                                break
                        case repl.AdvanceStr("$$"):
-                               line.Warn0("Unescaped $ or strange shell variable found.")
+                               line.Warnf("Unescaped $ or strange shell variable found.")
                        default:
                                break outer
                        }
@@ -182,8 +182,8 @@ func (shline *ShellLine) checkVaruseToke
        varname := varuse.varname
 
        if varname == "@" {
-               shline.line.Warn0("Please use \"${.TARGET}\" instead of \"$@\".")
-               Explain2(
+               shline.line.Warnf("Please use \"${.TARGET}\" instead of \"$@\".")
+               Explain(
                        "The variable $@ can easily be confused with the shell variable of",
                        "the same name, which has a completely different meaning.")
                varname = ".TARGET"
@@ -198,8 +198,8 @@ func (shline *ShellLine) checkVaruseToke
        case (quoting == shqSquot || quoting == shqDquot) && matches(varname, `^(?:.*DIR|.*FILE|.*PATH|.*_VAR|PREFIX|.*BASE|PKGNAME)$`):
                // This is ok if we don't allow these variables to have embedded [\$\\\"\'\`].
        case quoting == shqDquot && varuse.IsQ():
-               shline.line.Warn0("Please don't use the :Q operator in double quotes.")
-               Explain2(
+               shline.line.Warnf("Please don't use the :Q operator in double quotes.")
+               Explain(
                        "Either remove the :Q or the double quotes.  In most cases, it is",
                        "more appropriate to remove the double quotes.")
        }
@@ -237,12 +237,12 @@ func (shline *ShellLine) unescapeBacktic
                        unescaped += repl.m[1]
 
                case repl.AdvanceStr("\\"):
-                       line.Warn0("Backslashes should be doubled inside backticks.")
+                       line.Warnf("Backslashes should be doubled inside backticks.")
                        unescaped += "\\"
 
                case quoting == shqDquotBackt && repl.AdvanceStr("\""):
-                       line.Warn0("Double quotes inside backticks inside double quotes are error prone.")
-                       Explain4(
+                       line.Warnf("Double quotes inside backticks inside double quotes are error prone.")
+                       Explain(
                                "According to the SUSv3, they produce undefined results.",
                                "",
                                "See the paragraph starting \"Within the backquoted ...\" in",
@@ -255,7 +255,7 @@ func (shline *ShellLine) unescapeBacktic
                        line.Errorf("Internal pkglint error in ShellLine.unescapeBackticks at %q (rest=%q)", shellword, repl.rest)
                }
        }
-       line.Error1("Unfinished backquotes: rest=%q", repl.rest)
+       line.Errorf("Unfinished backquotes: rest=%q", repl.rest)
        return unescaped, quoting
 }
 
@@ -277,7 +277,7 @@ func (shline *ShellLine) CheckShellComma
        line := shline.line
 
        if contains(shelltext, "${SED}") && contains(shelltext, "${MV}") {
-               line.Note0("Please use the SUBST framework instead of ${SED} and ${MV}.")
+               line.Notef("Please use the SUBST framework instead of ${SED} and ${MV}.")
                Explain(
                        "Using the SUBST framework instead of explicit commands is easier",
                        "to understand, since all the complexity of using sed and mv is",
@@ -300,7 +300,7 @@ func (shline *ShellLine) CheckShellComma
        }
 
        if m, cmd := match1(shelltext, `^@*-(.*(?:MKDIR|INSTALL.*-d|INSTALL_.*_DIR).*)`); m {
-               line.Note1("You don't need to use \"-\" before %q.", cmd)
+               line.Notef("You don't need to use \"-\" before %q.", cmd)
        }
 
        repl := NewPrefixReplacer(shelltext)
@@ -325,7 +325,7 @@ func (shline *ShellLine) CheckShellComma
 
        program, err := parseShellProgram(shline.line, shellcmd)
        if err != nil && contains(shellcmd, "$$(") { // Hack until the shell parser can handle subshells.
-               shline.line.Warn0("Invoking subshells via $(...) is not portable enough.")
+               shline.line.Warnf("Invoking subshells via $(...) is not portable enough.")
                return
        }
        if err != nil {
@@ -363,7 +363,7 @@ func (shline *ShellLine) CheckShellComma
        setE := true
        shline.CheckShellCommand(shellcmds, &setE)
        if !hasSuffix(shellcmds, ";") {
-               shline.line.Warn0("This shell command list should end with a semicolon.")
+               shline.line.Warnf("This shell command list should end with a semicolon.")
        }
 }
 
@@ -396,7 +396,7 @@ func (shline *ShellLine) checkHiddenAndS
                                "${WARNING_CAT}", "${WARNING_MSG}":
                                break
                        default:
-                               shline.line.Warn1("The shell command %q should not be hidden.", cmd)
+                               shline.line.Warnf("The shell command %q should not be hidden.", cmd)
                                Explain(
                                        "Hidden shell commands do not appear on the terminal or in the log",
                                        "file when they are executed.  When they fail, the error message",
@@ -410,8 +410,8 @@ func (shline *ShellLine) checkHiddenAndS
        }
 
        if contains(hiddenAndSuppress, "-") {
-               shline.line.Warn0("Using a leading \"-\" to suppress errors is deprecated.")
-               Explain2(
+               shline.line.Warnf("Using a leading \"-\" to suppress errors is deprecated.")
+               Explain(
                        "If you really want to ignore any errors from this command, append",
                        "\"|| ${TRUE}\" to the command.")
        }
@@ -459,8 +459,8 @@ func (scc *SimpleCommandChecker) checkCo
        case scc.handleComment():
        default:
                if G.opts.WarnExtra && !(G.Mk != nil && G.Mk.indentation.DependsOn("OPSYS")) {
-                       scc.shline.line.Warn1("Unknown shell command %q.", shellword)
-                       Explain3(
+                       scc.shline.line.Warnf("Unknown shell command %q.", shellword)
+                       Explain(
                                "If you want your package to be portable to all platforms that pkgsrc",
                                "supports, you should only use shell commands that are covered by the",
                                "tools framework.")
@@ -483,11 +483,11 @@ func (scc *SimpleCommandChecker) handleT
        }
 
        if !localTool && !G.Mk.tools[shellword] && !G.Mk.tools["g"+shellword] {
-               scc.shline.line.Warn1("The %q tool is used but not added to USE_TOOLS.", shellword)
+               scc.shline.line.Warnf("The %q tool is used but not added to USE_TOOLS.", shellword)
        }
 
        if tool.MustUseVarForm {
-               scc.shline.line.Warn2("Please use \"${%s}\" instead of %q.", tool.Varname, shellword)
+               scc.shline.line.Warnf("Please use \"${%s}\" instead of %q.", tool.Varname, shellword)
        }
 
        scc.shline.checkCommandUse(shellword)
@@ -502,8 +502,8 @@ func (scc *SimpleCommandChecker) handleF
        shellword := scc.strcmd.Name
        switch path.Base(shellword) {
        case "ktrace", "mktexlsr", "strace", "texconfig", "truss":
-               scc.shline.line.Error1("%q must not be used in Makefiles.", shellword)
-               Explain3(
+               scc.shline.line.Errorf("%q must not be used in Makefiles.", shellword)
+               Explain(
                        "This command must appear in INSTALL scripts, not in the package",
                        "Makefile, so that the package also works if it is installed as a binary",
                        "package via pkg_add.")
@@ -522,7 +522,7 @@ func (scc *SimpleCommandChecker) handleC
 
                if tool := G.globalData.Tools.byVarname[varname]; tool != nil {
                        if !G.Mk.tools[tool.Name] {
-                               scc.shline.line.Warn1("The %q tool is used but not added to USE_TOOLS.", tool.Name)
+                               scc.shline.line.Warnf("The %q tool is used but not added to USE_TOOLS.", tool.Name)
                        }
                        scc.shline.checkCommandUse(shellword)
                        return true
@@ -560,10 +560,10 @@ func (scc *SimpleCommandChecker) handleC
        multiline := scc.shline.line.IsMultiline()
 
        if semicolon {
-               scc.shline.line.Warn0("A shell comment should not contain semicolons.")
+               scc.shline.line.Warnf("A shell comment should not contain semicolons.")
        }
        if multiline {
-               scc.shline.line.Warn0("A shell comment does not stop at the end of line.")
+               scc.shline.line.Warnf("A shell comment does not stop at the end of line.")
        }
 
        if semicolon || multiline {
@@ -596,8 +596,8 @@ func (scc *SimpleCommandChecker) checkAb
                        scc.shline.line.CheckAbsolutePathname(arg)
                }
                if false && isSubst && !matches(arg, `"^[\"\'].*[\"\']$`) {
-                       scc.shline.line.Warn1("Substitution commands like %q should always be quoted.", arg)
-                       Explain3(
+                       scc.shline.line.Warnf("Substitution commands like %q should always be quoted.", arg)
+                       Explain(
                                "Usually these substitution commands contain characters like '*' or",
                                "other shell metacharacters that might lead to lookup of matching",
                                "filenames and then expand to more than one word.")
@@ -626,7 +626,7 @@ func (scc *SimpleCommandChecker) checkAu
        for _, arg := range scc.strcmd.Args {
                if !contains(arg, "$$") && !matches(arg, `\$\{[_.]*[a-z]`) {
                        if m, dirname := match1(arg, `^(?:\$\{DESTDIR\})?\$\{PREFIX(?:|:Q)\}/(.*)`); m {
-                               scc.shline.line.Note2("You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= %s\" instead of %q.", dirname, cmdname)
+                               scc.shline.line.Notef("You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= %s\" instead of %q.", dirname, cmdname)
                                Explain(
                                        "Many packages include a list of all needed directories in their",
                                        "PLIST file.  In such a case, you can just set AUTO_MKDIRS=yes and",
@@ -660,8 +660,8 @@ func (scc *SimpleCommandChecker) checkIn
                                break
                        default:
                                if prevdir != "" {
-                                       scc.shline.line.Warn0("The INSTALL_*_DIR commands can only handle one directory at a time.")
-                                       Explain2(
+                                       scc.shline.line.Warnf("The INSTALL_*_DIR commands can only handle one directory at a time.")
+                                       Explain(
                                                "Many implementations of install(1) can handle more, but pkgsrc aims",
                                                "at maximum portability.")
                                        return
@@ -678,8 +678,8 @@ func (scc *SimpleCommandChecker) checkPa
        }
 
        if scc.strcmd.Name == "${PAX}" && scc.strcmd.HasOption("-pe") {
-               scc.shline.line.Warn0("Please use the -pp option to pax(1) instead of -pe.")
-               Explain3(
+               scc.shline.line.Warnf("Please use the -pp option to pax(1) instead of -pe.")
+               Explain(
                        "The -pe option tells pax to preserve the ownership of the files, which",
                        "means that the installed files will belong to the user that has built",
                        "the package.")
@@ -692,7 +692,7 @@ func (scc *SimpleCommandChecker) checkEc
        }
 
        if scc.strcmd.Name == "${ECHO}" && scc.strcmd.HasOption("-n") {
-               scc.shline.line.Warn0("Please use ${ECHO_N} instead of \"echo -n\".")
+               scc.shline.line.Warnf("Please use ${ECHO_N} instead of \"echo -n\".")
        }
 }
 
@@ -718,8 +718,8 @@ func (spc *ShellProgramChecker) checkCon
 
        checkConditionalCd := func(cmd *MkShSimpleCommand) {
                if NewStrCommand(cmd).Name == "cd" {
-                       spc.shline.line.Error0("The Solaris /bin/sh cannot handle \"cd\" inside conditionals.")
-                       Explain3(
+                       spc.shline.line.Errorf("The Solaris /bin/sh cannot handle \"cd\" inside conditionals.")
+                       Explain(
                                "When the Solaris shell is in \"set -e\" mode and \"cd\" fails, the",
                                "shell will exit, no matter if it is protected by an \"if\" or the",
                                "\"||\" operator.")
@@ -766,7 +766,7 @@ func (scc *ShellProgramChecker) checkPip
        }
 
        if G.opts.WarnExtra && len(pipeline.Cmds) > 1 {
-               line.Warn0("The exitcode of the left-hand-side command of the pipe operator is ignored.")
+               line.Warnf("The exitcode of the left-hand-side command of the pipe operator is ignored.")
                Explain(
                        "In a shell command like \"cat *.txt | grep keyword\", if the command",
                        "on the left side of the \"|\" fails, this failure is ignored.",
@@ -784,7 +784,7 @@ func (scc *ShellProgramChecker) checkSet
        // Disabled until the shell parser can recognize "command || exit 1" reliably.
        if false && G.opts.WarnExtra && !*eflag && "the current token" == ";" {
                *eflag = true
-               scc.shline.line.Warn1("Please switch to \"set -e\" mode before using a semicolon (the one after %q) to separate commands.", "previous token")
+               scc.shline.line.Warnf("Please switch to \"set -e\" mode before using a semicolon (the one after %q) to separate commands.", "previous token")
                Explain(
                        "Normally, when a shell command fails (returns non-zero), the",
                        "remaining commands are still executed.  For example, the following",
@@ -826,14 +826,14 @@ func (shline *ShellLine) checkCommandUse
 
        case "sed", "${SED}",
                "tr", "${TR}":
-               line.Warn1("The shell command %q should not be used in the install phase.", shellcmd)
-               Explain3(
+               line.Warnf("The shell command %q should not be used in the install phase.", shellcmd)
+               Explain(
                        "In the install phase, the only thing that should be done is to",
                        "install the prepared files to their final location.  The file's",
                        "contents should not be changed anymore.")
 
        case "cp", "${CP}":
-               line.Warn0("${CP} should not be used to install files.")
+               line.Warnf("${CP} should not be used to install files.")
                Explain(
                        "The ${CP} command is highly platform dependent and cannot overwrite",
                        "read-only files.  Please use ${PAX} instead.",

Index: pkgsrc/pkgtools/pkglint/files/package_test.go
diff -u pkgsrc/pkgtools/pkglint/files/package_test.go:1.10 pkgsrc/pkgtools/pkglint/files/package_test.go:1.11
--- pkgsrc/pkgtools/pkglint/files/package_test.go:1.10  Tue Nov  1 21:40:25 2016
+++ pkgsrc/pkgtools/pkglint/files/package_test.go       Sun Dec  4 15:28:36 2016
@@ -26,7 +26,7 @@ func (s *Suite) Test_Package_ChecklinesP
        pkg := NewPackage("x11/9term")
 
        pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "DISTNAME=9term",
                "CATEGORIES=x11"))
@@ -34,7 +34,7 @@ func (s *Suite) Test_Package_ChecklinesP
        c.Check(s.Output(), equals, "")
 
        pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "DISTNAME=9term",
                "CATEGORIES=x11",
@@ -114,7 +114,7 @@ func (s *Suite) Test_checkdirPackage(c *
 
 func (s *Suite) Test_checkdirPackage__meta_package_without_license(c *check.C) {
        s.CreateTmpFileLines(c, "Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "META_PACKAGE=\tyes")
        G.CurrentDir = s.tmpdir
@@ -151,7 +151,7 @@ func (s *Suite) Test_Package__varuse_at_
                "# dummy")
 
        s.CreateTmpFileLines(c, "category/pkgbase/Makefile",
-               "# $"+"NetBSD$",
+               mkrcsid,
                "",
                "COMMENT= Unit test",
                "LICENSE= bsd-2",
Index: pkgsrc/pkgtools/pkglint/files/patches.go
diff -u pkgsrc/pkgtools/pkglint/files/patches.go:1.10 pkgsrc/pkgtools/pkglint/files/patches.go:1.11
--- pkgsrc/pkgtools/pkglint/files/patches.go:1.10       Sat Jul  9 09:43:48 2016
+++ pkgsrc/pkgtools/pkglint/files/patches.go    Sun Dec  4 15:28:36 2016
@@ -56,7 +56,7 @@ func (ck *PatchChecker) Check() {
                        patchedFile := ck.exp.m[1]
                        if ck.exp.AdvanceIfMatches(rePatchUniFileDel) {
                                ck.checkBeginDiff(line, patchedFiles)
-                               ck.exp.PreviousLine().Warn0("Unified diff headers should be first ---, then +++.")
+                               ck.exp.PreviousLine().Warnf("Unified diff headers should be first ---, then +++.")
                                ck.checkUnifiedDiff(patchedFile)
                                patchedFiles++
                                continue
@@ -68,7 +68,7 @@ func (ck *PatchChecker) Check() {
                if ck.exp.AdvanceIfMatches(`^\*\*\*\s(\S+)(.*)$`) {
                        if ck.exp.AdvanceIfMatches(`^---\s(\S+)(.*)$`) {
                                ck.checkBeginDiff(line, patchedFiles)
-                               line.Warn0("Please use unified diffs (diff -u) for patches.")
+                               line.Warnf("Please use unified diffs (diff -u) for patches.")
                                return
                        }
 
@@ -85,7 +85,7 @@ func (ck *PatchChecker) Check() {
        if patchedFiles > 1 {
                NewLineWhole(ck.lines[0].Fname).Warnf("Contains patches for %d files, should be only one.", patchedFiles)
        } else if patchedFiles == 0 {
-               NewLineWhole(ck.lines[0].Fname).Error0("Contains no patch.")
+               NewLineWhole(ck.lines[0].Fname).Errorf("Contains no patch.")
        }
 
        ChecklinesTrailingEmptyLines(ck.lines)
@@ -133,19 +133,19 @@ func (ck *PatchChecker) checkUnifiedDiff
                        case hasPrefix(text, "\\"):
                                // \ No newline at end of file
                        default:
-                               line.Error0("Invalid line in unified patch hunk")
+                               line.Errorf("Invalid line in unified patch hunk")
                                return
                        }
                }
        }
        if !hasHunks {
-               ck.exp.CurrentLine().Error1("No patch hunks for %q.", patchedFile)
+               ck.exp.CurrentLine().Errorf("No patch hunks for %q.", patchedFile)
        }
        if !ck.exp.EOF() {
                line := ck.exp.CurrentLine()
                if !ck.isEmptyLine(line.Text) && !matches(line.Text, rePatchUniFileDel) {
-                       line.Warn0("Empty line or end of file expected.")
-                       Explain3(
+                       line.Warnf("Empty line or end of file expected.")
+                       Explain(
                                "This empty line makes the end of the patch clearly visible.",
                                "Otherwise the reader would have to count lines to see where",
                                "the patch ends.")
@@ -159,7 +159,7 @@ func (ck *PatchChecker) checkBeginDiff(l
        }
 
        if !ck.seenDocumentation && patchedFiles == 0 {
-               line.Error0("Each patch must be documented.")
+               line.Errorf("Each patch must be documented.")
                Explain(
                        "Pkgsrc tries to have as few patches as possible.  Therefore, each",
                        "patch must document why it is necessary.  Typical reasons are",
@@ -175,7 +175,7 @@ func (ck *PatchChecker) checkBeginDiff(l
        }
        if G.opts.WarnSpace && !ck.previousLineEmpty {
                if !line.AutofixInsertBefore("") {
-                       line.Note0("Empty line expected.")
+                       line.Notef("Empty line expected.")
                }
        }
 }
@@ -209,8 +209,8 @@ func (ck *PatchChecker) checklineAdded(a
                checklineSourceAbsolutePathname(line, addedText)
        case ftConfigure:
                if hasSuffix(addedText, ": Avoid regenerating within pkgsrc") {
-                       line.Error0("This code must not be included in patches.")
-                       Explain4(
+                       line.Errorf("This code must not be included in patches.")
+                       Explain(
                                "It is generated automatically by pkgsrc after the patch phase.",
                                "",
                                "For more details, look for \"configure-scripts-override\" in",
@@ -229,8 +229,8 @@ func (ck *PatchChecker) checktextUniHunk
        line := ck.exp.PreviousLine()
        if hasSuffix(line.Text, "\r") {
                if !line.AutofixReplace("\r\n", "\n") {
-                       line.Error0("The hunk header must not end with a CR character.")
-                       Explain1(
+                       line.Errorf("The hunk header must not end with a CR character.")
+                       Explain(
                                "The MacOS X patch utility cannot handle these.")
                }
        }
@@ -242,9 +242,9 @@ func (ck *PatchChecker) checktextRcsid(t
        }
        if m, tagname := match1(text, `\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|NetBSD)(?::[^\$]*)?\$`); m {
                if matches(text, rePatchUniHunk) {
-                       ck.exp.PreviousLine().Warn1("Found RCS tag \"$%s$\". Please remove it.", tagname)
+                       ck.exp.PreviousLine().Warnf("Found RCS tag \"$%s$\". Please remove it.", tagname)
                } else {
-                       ck.exp.PreviousLine().Warn1("Found RCS tag \"$%s$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".", tagname)
+                       ck.exp.PreviousLine().Warnf("Found RCS tag \"$%s$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".", tagname)
                }
        }
 }
@@ -329,7 +329,7 @@ func checkwordAbsolutePathname(line *Lin
                // Probably a sed(1) command
        case matches(word, `^/(?:[a-z]|\$[({])`):
                // Absolute paths probably start with a lowercase letter.
-               line.Warn1("Found absolute pathname: %s", word)
+               line.Warnf("Found absolute pathname: %s", word)
                Explain(
                        "Absolute pathnames are often an indicator for unportable code.  As",
                        "pkgsrc aims to be a portable system, absolute pathnames should be",
Index: pkgsrc/pkgtools/pkglint/files/plist_test.go
diff -u pkgsrc/pkgtools/pkglint/files/plist_test.go:1.10 pkgsrc/pkgtools/pkglint/files/plist_test.go:1.11
--- pkgsrc/pkgtools/pkglint/files/plist_test.go:1.10    Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/plist_test.go Sun Dec  4 15:28:36 2016
@@ -178,6 +178,16 @@ func (s *Suite) TestPlistChecker_checkpa
        c.Check(s.Output(), equals, "NOTE: PLIST:2: PLIST files should mention \"man/\" instead of \"${PKGMANDIR}\".\n")
 }
 
+func (s *Suite) TestPlistChecker_checkpath__python_egg(c *check.C) {
+       lines := s.NewLines("PLIST",
+               "@comment $"+"NetBSD$",
+               "${PYSITELIB}/gdspy-${PKGVERSION}-py${PYVERSSUFFIX}.egg-info/PKG-INFO")
+
+       ChecklinesPlist(lines)
+
+       c.Check(s.Output(), equals, "WARN: PLIST:2: Include \"../../lang/python/egg.mk\" instead of listing .egg-info files directly.\n")
+}
+
 func (s *Suite) Test_PlistChecker__autofix(c *check.C) {
        s.UseCommandLine(c, "-Wall")
 
Index: pkgsrc/pkgtools/pkglint/files/util.go
diff -u pkgsrc/pkgtools/pkglint/files/util.go:1.10 pkgsrc/pkgtools/pkglint/files/util.go:1.11
--- pkgsrc/pkgtools/pkglint/files/util.go:1.10  Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/util.go       Sun Dec  4 15:28:36 2016
@@ -201,110 +201,6 @@ func dirExists(fname string) bool {
        return err == nil && st.Mode().IsDir()
 }
 
-type RegexPattern string
-
-var res = make(map[RegexPattern]*regexp.Regexp)
-
-func regcomp(re RegexPattern) *regexp.Regexp {
-       cre := res[re]
-       if cre == nil {
-               cre = regexp.MustCompile(string(re))
-               res[re] = cre
-       }
-       return cre
-}
-
-func match(s string, re RegexPattern) []string {
-       if !G.opts.Profiling {
-               return regcomp(re).FindStringSubmatch(s)
-       }
-
-       before := time.Now()
-       immediatelyBefore := time.Now()
-       m := regcomp(re).FindStringSubmatch(s)
-       after := time.Now()
-
-       delay := immediatelyBefore.UnixNano() - before.UnixNano()
-       timeTaken := after.UnixNano() - immediatelyBefore.UnixNano() - delay
-
-       G.retime.Add(string(re), int(timeTaken))
-       if m != nil {
-               G.rematch.Add(string(re), 1)
-       } else {
-               G.renomatch.Add(string(re), 1)
-       }
-       return m
-}
-
-func matches(s string, re RegexPattern) bool {
-       matches := regcomp(re).MatchString(s)
-       if G.opts.Profiling {
-               if matches {
-                       G.rematch.Add(string(re), 1)
-               } else {
-                       G.renomatch.Add(string(re), 1)
-               }
-       }
-       return matches
-}
-
-func matchn(s string, re RegexPattern, n int) []string {
-       if m := match(s, re); m != nil {
-               if len(m) != 1+n {
-                       panic(fmt.Sprintf("expected match%d, got match%d for %q", len(m)-1, n, re))
-               }
-               return m
-       }
-       return nil
-}
-
-func match1(s string, re RegexPattern) (matched bool, m1 string) {
-       if m := matchn(s, re, 1); m != nil {
-               return true, m[1]
-       }
-       return
-}
-func match2(s string, re RegexPattern) (matched bool, m1, m2 string) {
-       if m := matchn(s, re, 2); m != nil {
-               return true, m[1], m[2]
-       }
-       return
-}
-func match3(s string, re RegexPattern) (matched bool, m1, m2, m3 string) {
-       if m := matchn(s, re, 3); m != nil {
-               return true, m[1], m[2], m[3]
-       }
-       return
-}
-func match4(s string, re RegexPattern) (matched bool, m1, m2, m3, m4 string) {
-       if m := matchn(s, re, 4); m != nil {
-               return true, m[1], m[2], m[3], m[4]
-       }
-       return
-}
-func match5(s string, re RegexPattern) (matched bool, m1, m2, m3, m4, m5 string) {
-       if m := matchn(s, re, 5); m != nil {
-               return true, m[1], m[2], m[3], m[4], m[5]
-       }
-       return
-}
-
-func replaceFirst(s string, re RegexPattern, replacement string) ([]string, string) {
-       if G.opts.Debug {
-               defer tracecall(s, re, replacement)()
-       }
-
-       if m := regcomp(re).FindStringSubmatchIndex(s); m != nil {
-               replaced := s[:m[0]] + replacement + s[m[1]:]
-               mm := make([]string, len(m)/2)
-               for i := 0; i < len(m); i += 2 {
-                       mm[i/2] = s[negToZero(m[i]):negToZero(m[i+1])]
-               }
-               return mm, replaced
-       }
-       return nil, s
-}
-
 type PrefixReplacerMark string
 
 type PrefixReplacer struct {
@@ -471,13 +367,9 @@ func traceStep(format string, args ...in
        }
 }
 func traceStep1(format string, arg0 string) {
-       switch { // Prevent inlining
-       }
        traceStep(format, arg0)
 }
 func traceStep2(format string, arg0, arg1 string) {
-       switch { //Prevent inlining
-       }
        traceStep(format, arg0, arg1)
 }
 
@@ -502,23 +394,15 @@ func tracecallInternal(args ...interface
        }
 }
 func tracecall0() func() {
-       switch { // prevent inlining, for code size and performance
-       }
        return tracecallInternal()
 }
 func tracecall1(arg1 string) func() {
-       switch { // prevent inlining, for code size and performance
-       }
        return tracecallInternal(arg1)
 }
 func tracecall2(arg1, arg2 string) func() {
-       switch { // prevent inlining, for code size and performance
-       }
        return tracecallInternal(arg1, arg2)
 }
 func tracecall(args ...interface{}) func() {
-       switch { // prevent inlining, for code size and performance
-       }
        return tracecallInternal(args...)
 }
 

Index: pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint.go:1.14 pkgsrc/pkgtools/pkglint/files/pkglint.go:1.15
--- pkgsrc/pkgtools/pkglint/files/pkglint.go:1.14       Mon Nov 14 01:08:23 2016
+++ pkgsrc/pkgtools/pkglint/files/pkglint.go    Sun Dec  4 15:28:36 2016
@@ -90,7 +90,7 @@ func ChecklinesDescr(lines []*Line) {
                line.CheckTrailingWhitespace()
                line.CheckValidCharacters(`[\t -~]`)
                if contains(line.Text, "${") {
-                       line.Note0("Variables are not expanded in the DESCR file.")
+                       line.Notef("Variables are not expanded in the DESCR file.")
                }
        }
        ChecklinesTrailingEmptyLines(lines)
@@ -99,7 +99,7 @@ func ChecklinesDescr(lines []*Line) {
                line := lines[maxlines]
 
                line.Warnf("File too long (should be no more than %d lines).", maxlines)
-               Explain3(
+               Explain(
                        "The DESCR file should fit on a traditional terminal of 80x25",
                        "characters.  It is also intended to give a _brief_ summary about",
                        "the package's contents.")
@@ -114,7 +114,7 @@ func ChecklinesMessage(lines []*Line) {
        }
 
        explainMessage := func() {
-               Explain4(
+               Explain(
                        "A MESSAGE file should consist of a header line, having 75 \"=\"",
                        "characters, followed by a line containing only the RCS Id, then an",
                        "empty line, your text and finally the footer line, which is the",
@@ -123,14 +123,14 @@ func ChecklinesMessage(lines []*Line) {
 
        if len(lines) < 3 {
                lastLine := lines[len(lines)-1]
-               lastLine.Warn0("File too short.")
+               lastLine.Warnf("File too short.")
                explainMessage()
                return
        }
 
        hline := strings.Repeat("=", 75)
        if line := lines[0]; line.Text != hline {
-               line.Warn0("Expected a line of exactly 75 \"=\" characters.")
+               line.Warnf("Expected a line of exactly 75 \"=\" characters.")
                explainMessage()
        }
        lines[1].CheckRcsid(``, "")
@@ -140,7 +140,7 @@ func ChecklinesMessage(lines []*Line) {
                line.CheckValidCharacters(`[\t -~]`)
        }
        if lastLine := lines[len(lines)-1]; lastLine.Text != hline {
-               lastLine.Warn0("Expected a line of exactly 75 \"=\" characters.")
+               lastLine.Warnf("Expected a line of exactly 75 \"=\" characters.")
                explainMessage()
        }
        ChecklinesTrailingEmptyLines(lines)
@@ -168,7 +168,7 @@ func Checkfile(fname string) {
        basename := path.Base(fname)
        if hasPrefix(basename, "work") || hasSuffix(basename, "~") || hasSuffix(basename, ".orig") || hasSuffix(basename, ".rej") {
                if G.opts.Import {
-                       NewLineWhole(fname).Error0("Must be cleaned up before committing the package.")
+                       NewLineWhole(fname).Errorf("Must be cleaned up before committing the package.")
                }
                return
        }
@@ -181,8 +181,8 @@ func Checkfile(fname string) {
 
        if st.Mode().IsRegular() && st.Mode().Perm()&0111 != 0 && !isCommitted(fname) {
                line := NewLine(fname, 0, "", nil)
-               line.Warn0("Should not be executable.")
-               Explain4(
+               line.Warnf("Should not be executable.")
+               Explain(
                        "No package file should ever be executable.  Even the INSTALL and",
                        "DEINSTALL scripts are usually not usable in the form they have in",
                        "the package, as the pathnames get adjusted during installation.",
@@ -197,16 +197,16 @@ func Checkfile(fname string) {
                case matches(fname, `(?:^|/)files/[^/]*$`):
                        // Ok
                case !isEmptyDir(fname):
-                       NewLineWhole(fname).Warn0("Unknown directory name.")
+                       NewLineWhole(fname).Warnf("Unknown directory name.")
                }
 
        case st.Mode()&os.ModeSymlink != 0:
                if !hasPrefix(basename, "work") {
-                       NewLineWhole(fname).Warn0("Unknown symlink name.")
+                       NewLineWhole(fname).Warnf("Unknown symlink name.")
                }
 
        case !st.Mode().IsRegular():
-               NewLineWhole(fname).Error0("Only files and directories are allowed in pkgsrc.")
+               NewLineWhole(fname).Errorf("Only files and directories are allowed in pkgsrc.")
 
        case basename == "ALTERNATIVES":
                if G.opts.CheckAlternatives {
@@ -259,7 +259,7 @@ func Checkfile(fname string) {
                }
 
        case matches(fname, `(?:^|/)patches/[^/]*$`):
-               NewLineWhole(fname).Warn0("Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only.")
+               NewLineWhole(fname).Warnf("Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only.")
 
        case matches(basename, `^(?:.*\.mk|Makefile.*)$`) && !matches(fname, `files/`) && !matches(fname, `patches/`):
                if G.opts.CheckMk {
@@ -287,7 +287,7 @@ func Checkfile(fname string) {
                // Ok in regression tests
 
        default:
-               NewLineWhole(fname).Warn0("Unexpected file found.")
+               NewLineWhole(fname).Warnf("Unexpected file found.")
                if G.opts.CheckExtra {
                        CheckfileExtra(fname)
                }
@@ -301,7 +301,7 @@ func ChecklinesTrailingEmptyLines(lines 
                last--
        }
        if last != max {
-               lines[last].Note0("Trailing empty lines.")
+               lines[last].Notef("Trailing empty lines.")
        }
 }
 
@@ -385,66 +385,6 @@ func MatchVarassign(text string) (m bool
        return
 }
 
-func MatchMkInclude(text string) (bool, string, string, string) {
-       goto start
-fail:
-       return false, "", "", ""
-
-start:
-       len := len(text)
-       if len == 0 || text[0] != '.' {
-               goto fail
-       }
-
-       i := 1
-
-       spaceStart := i
-       for i < len && (text[i] == ' ' || text[i] == '\t') {
-               i++
-       }
-       spaceEnd := i
-
-       directiveStart := i
-       if i < len && text[i] == 's' {
-               i++
-       }
-       if !(i+7 < len && text[i] == 'i' && text[i+1] == 'n' && text[i+2] == 'c' && text[i+3] == 'l' && text[i+4] == 'u' && text[i+5] == 'd' && text[i+6] == 'e') {
-               goto fail
-       }
-       i += 7
-       directiveEnd := i
-
-       for i < len && (text[i] == ' ' || text[i] == '\t') {
-               i++
-       }
-       if !(i < len && text[i] == '"') {
-               goto fail
-       }
-       i++
-
-       pathStart := i
-       for i < len && text[i] != '"' {
-               i++
-       }
-       pathEnd := i
-       if !(pathStart < pathEnd) {
-               goto fail
-       }
-
-       if !(i < len && text[i] == '"') {
-               goto fail
-       }
-       i++
-
-       for i < len && (text[i] == ' ' || text[i] == '\t') {
-               i++
-       }
-       if !(i == len || i < len && text[i] == '#') {
-               goto fail
-       }
-       return true, text[spaceStart:spaceEnd], text[directiveStart:directiveEnd], text[pathStart:pathEnd]
-}
-
 type DependencyPattern struct {
        pkgbase  string // "freeciv-client", "{gcc48,gcc48-libs}", "${EMACS_REQD}"
        lowerOp  string // ">=", ">"

Index: pkgsrc/pkgtools/pkglint/files/vartypecheck.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.19 pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.20
--- pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.19  Tue Sep  6 20:54:21 2016
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck.go       Sun Dec  4 15:28:36 2016
@@ -25,8 +25,8 @@ const (
        opAssignEval                      // :=
        opAssignAppend                    // +=
        opAssignDefault                   // ?=
-       opUse                             //
-       opUseMatch                        // Used in the :M operator
+       opUseCompare                      // A variable is compared to a value, e.g. in a conditional.
+       opUseMatch                        // A variable is matched using the :M or :N modifier.
 )
 
 func NewMkOperator(op string) MkOperator {
@@ -120,7 +120,7 @@ func (cv *VartypeCheck) BasicRegularExpr
 
 func (cv *VartypeCheck) BuildlinkDepmethod() {
        if !containsVarRef(cv.Value) && cv.Value != "build" && cv.Value != "full" {
-               cv.Line.Warn1("Invalid dependency method %q. Valid methods are \"build\" or \"full\".", cv.Value)
+               cv.Line.Warnf("Invalid dependency method %q. Valid methods are \"build\" or \"full\".", cv.Value)
        }
 }
 
@@ -142,7 +142,7 @@ func (cv *VartypeCheck) Category() {
                "windowmaker",
                "xmms":
        default:
-               cv.Line.Error1("Invalid category %q.", cv.Value)
+               cv.Line.Errorf("Invalid category %q.", cv.Value)
        }
 }
 
@@ -163,9 +163,9 @@ func (cv *VartypeCheck) CFlag() {
                containsVarRef(cflag):
                return
        case hasPrefix(cflag, "-"):
-               cv.Line.Warn1("Unknown compiler flag %q.", cflag)
+               cv.Line.Warnf("Unknown compiler flag %q.", cflag)
        default:
-               cv.Line.Warn1("Compiler flag %q should start with a hyphen.", cflag)
+               cv.Line.Warnf("Compiler flag %q should start with a hyphen.", cflag)
        }
 }
 
@@ -174,19 +174,19 @@ func (cv *VartypeCheck) Comment() {
        line, value := cv.Line, cv.Value
 
        if value == "TODO: Short description of the package" { // See pkgtools/url2pkg/files/url2pkg.pl, keyword "COMMENT".
-               line.Error0("COMMENT must be set.")
+               line.Errorf("COMMENT must be set.")
        }
        if m, first := match1(value, `^(?i)(a|an)\s`); m {
-               line.Warn1("COMMENT should not begin with %q.", first)
+               line.Warnf("COMMENT should not begin with %q.", first)
        }
        if matches(value, `^[a-z]`) {
-               line.Warn0("COMMENT should start with a capital letter.")
+               line.Warnf("COMMENT should start with a capital letter.")
        }
        if hasSuffix(value, ".") {
-               line.Warn0("COMMENT should not end with a period.")
+               line.Warnf("COMMENT should not end with a period.")
        }
        if len(value) > 70 {
-               line.Warn0("COMMENT should not be longer than 70 characters.")
+               line.Warnf("COMMENT should not be longer than 70 characters.")
        }
 }
 
@@ -196,15 +196,15 @@ func (cv *VartypeCheck) Dependency() {
        parser := NewParser(line, value, false)
        deppat := parser.Dependency()
        if deppat != nil && deppat.wildcard == "" && (parser.Rest() == "{,nb*}" || parser.Rest() == "{,nb[0-9]*}") {
-               line.Warn0("Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.")
-               Explain4(
+               line.Warnf("Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.")
+               Explain(
                        "The \"{,nb*}\" extension is only necessary for dependencies of the",
                        "form \"pkgbase-1.2\", since the pattern \"pkgbase-1.2\" doesn't match",
                        "the version \"pkgbase-1.2nb5\".  For dependency patterns using the",
                        "comparison operators, this is not necessary.")
 
        } else if deppat == nil || !parser.EOF() {
-               line.Warn1("Unknown dependency pattern %q.", value)
+               line.Warnf("Unknown dependency pattern %q.", value)
                Explain(
                        "Typical dependencies have the following forms:",
                        "",
@@ -218,34 +218,34 @@ func (cv *VartypeCheck) Dependency() {
        wildcard := deppat.wildcard
        if m, inside := match1(wildcard, `^\[(.*)\]\*$`); m {
                if inside != "0-9" {
-                       line.Warn0("Only [0-9]* is allowed in the numeric part of a dependency.")
+                       line.Warnf("Only [0-9]* is allowed in the numeric part of a dependency.")
                }
 
        } else if m, ver, suffix := match2(wildcard, `^(\d\w*(?:\.\w+)*)(\.\*|\{,nb\*\}|\{,nb\[0-9\]\*\}|\*|)$`); m {
                if suffix == "" {
-                       line.Warn2("Please use %q instead of %q as the version pattern.", ver+"{,nb*}", ver)
-                       Explain3(
+                       line.Warnf("Please use %q instead of %q as the version pattern.", ver+"{,nb*}", ver)
+                       Explain(
                                "Without the \"{,nb*}\" suffix, this version pattern only matches",
                                "package versions that don't have a PKGREVISION (which is the part",
                                "after the \"nb\").")
                }
                if suffix == "*" {
-                       line.Warn2("Please use %q instead of %q as the version pattern.", ver+".*", ver+"*")
-                       Explain2(
+                       line.Warnf("Please use %q instead of %q as the version pattern.", ver+".*", ver+"*")
+                       Explain(
                                "For example, the version \"1*\" also matches \"10.0.0\", which is",
                                "probably not intended.")
                }
 
        } else if wildcard == "*" {
-               line.Warn1("Please use \"%[1]s-[0-9]*\" instead of \"%[1]s-*\".", deppat.pkgbase)
-               Explain3(
+               line.Warnf("Please use \"%[1]s-[0-9]*\" instead of \"%[1]s-*\".", deppat.pkgbase)
+               Explain(
                        "If you use a * alone, the package specification may match other",
                        "packages that have the same prefix, but a longer name.  For example,",
                        "foo-* matches foo-1.2, but also foo-client-1.2 and foo-server-1.2.")
        }
 
        if nocclasses := regcomp(`\[[\d-]+\]`).ReplaceAllString(wildcard, ""); contains(nocclasses, "-") {
-               line.Warn1("The version pattern %q should not contain a hyphen.", wildcard)
+               line.Warnf("The version pattern %q should not contain a hyphen.", wildcard)
                Explain(
                        "Pkgsrc interprets package names with version numbers like this:",
                        "",
@@ -267,11 +267,11 @@ func (cv *VartypeCheck) DependencyWithPa
 
                switch pkg {
                case "msgfmt", "gettext":
-                       line.Warn0("Please use USE_TOOLS+=msgfmt instead of this dependency.")
+                       line.Warnf("Please use USE_TOOLS+=msgfmt instead of this dependency.")
                case "perl5":
-                       line.Warn0("Please use USE_TOOLS+=perl:run instead of this dependency.")
+                       line.Warnf("Please use USE_TOOLS+=perl:run instead of this dependency.")
                case "gmake":
-                       line.Warn0("Please use USE_TOOLS+=gmake instead of this dependency.")
+                       line.Warnf("Please use USE_TOOLS+=gmake instead of this dependency.")
                }
 
                cv.MkLine.CheckVartypePrimitive(cv.Varname, BtDependency, cv.Op, pattern, cv.MkComment, cv.Guessed)
@@ -279,13 +279,13 @@ func (cv *VartypeCheck) DependencyWithPa
        }
 
        if matches(value, `:\.\./[^/]+$`) {
-               line.Warn0("Dependencies should have the form \"../../category/package\".")
+               line.Warnf("Dependencies should have the form \"../../category/package\".")
                cv.MkLine.explainRelativeDirs()
                return
        }
 
-       line.Warn1("Unknown dependency pattern with path %q.", value)
-       Explain4(
+       line.Warnf("Unknown dependency pattern with path %q.", value)
+       Explain(
                "Examples for valid dependency patterns with path are:",
                "  package-[0-9]*:../../category/package",
                "  package>=3.41:../../category/package",
@@ -294,7 +294,7 @@ func (cv *VartypeCheck) DependencyWithPa
 
 func (cv *VartypeCheck) DistSuffix() {
        if cv.Value == ".tar.gz" {
-               cv.Line.Note1("%s is \".tar.gz\" by default, so this definition may be redundant.", cv.Varname)
+               cv.Line.Notef("%s is \".tar.gz\" by default, so this definition may be redundant.", cv.Varname)
        }
 }
 
@@ -326,7 +326,7 @@ func (cv *VartypeCheck) EmulPlatform() {
                        cv.Guessed}
                enumEmulArch.checker(archCv)
        } else {
-               cv.Line.Warn1("%q is not a valid emulation platform.", cv.Value)
+               cv.Line.Warnf("%q is not a valid emulation platform.", cv.Value)
                Explain(
                        "An emulation platform has the form <OPSYS>-<MACHINE_ARCH>.",
                        "OPSYS is the lower-case name of the operating system, and",
@@ -357,10 +357,10 @@ func (cv *VartypeCheck) FetchURL() {
 
        if m, name, subdir := match2(cv.Value, `\$\{(MASTER_SITE_[^:]*).*:=(.*)\}$`); m {
                if G.globalData.MasterSiteVarToURL[name] == "" {
-                       cv.Line.Error1("The site %s does not exist.", name)
+                       cv.Line.Errorf("The site %s does not exist.", name)
                }
                if !hasSuffix(subdir, "/") {
-                       cv.Line.Error1("The subdirectory in %s must end with a slash.", name)
+                       cv.Line.Errorf("The subdirectory in %s must end with a slash.", name)
                }
        }
 }
@@ -372,9 +372,9 @@ func (cv *VartypeCheck) Filename() {
        case cv.Op == opUseMatch:
                break
        case contains(cv.ValueNoVar, "/"):
-               cv.Line.Warn0("A filename should not contain a slash.")
+               cv.Line.Warnf("A filename should not contain a slash.")
        case !matches(cv.ValueNoVar, `^[-0-9@A-Za-z.,_~+%]*$`):
-               cv.Line.Warn1("%q is not a valid filename.", cv.Value)
+               cv.Line.Warnf("%q is not a valid filename.", cv.Value)
        }
 }
 
@@ -383,7 +383,7 @@ func (cv *VartypeCheck) Filemask() {
                return
        }
        if !matches(cv.ValueNoVar, `^[-0-9A-Za-z._~+%*?]*$`) {
-               cv.Line.Warn1("%q is not a valid filename mask.", cv.Value)
+               cv.Line.Warnf("%q is not a valid filename mask.", cv.Value)
        }
 }
 
@@ -394,7 +394,7 @@ func (cv *VartypeCheck) FileMode() {
        case matches(cv.Value, `^[0-7]{3,4}`):
                // Fine.
        default:
-               cv.Line.Warn1("Invalid file mode %q.", cv.Value)
+               cv.Line.Warnf("Invalid file mode %q.", cv.Value)
        }
 }
 
@@ -413,11 +413,11 @@ func (cv *VartypeCheck) Homepage() {
                explain := false
                if baseURL != "" {
                        if !cv.Line.AutofixReplace(wrong, fixedURL) {
-                               cv.Line.Warn1("HOMEPAGE should not be defined in terms of MASTER_SITEs. Use %s directly.", fixedURL)
+                               cv.Line.Warnf("HOMEPAGE should not be defined in terms of MASTER_SITEs. Use %s directly.", fixedURL)
                                explain = true
                        }
                } else {
-                       cv.Line.Warn0("HOMEPAGE should not be defined in terms of MASTER_SITEs.")
+                       cv.Line.Warnf("HOMEPAGE should not be defined in terms of MASTER_SITEs.")
                        explain = true
                }
                if explain {
@@ -435,7 +435,7 @@ func (cv *VartypeCheck) Homepage() {
 func (cv *VartypeCheck) Identifier() {
        if cv.Op == opUseMatch {
                if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[\w*?]`) {
-                       cv.Line.Warn2("Invalid identifier pattern %q for %s.", cv.Value, cv.Varname)
+                       cv.Line.Warnf("Invalid identifier pattern %q for %s.", cv.Value, cv.Varname)
                }
                return
        }
@@ -448,13 +448,13 @@ func (cv *VartypeCheck) Identifier() {
        case cv.Value != "" && cv.ValueNoVar == "":
                // Don't warn here.
        default:
-               cv.Line.Warn1("Invalid identifier %q.", cv.Value)
+               cv.Line.Warnf("Invalid identifier %q.", cv.Value)
        }
 }
 
 func (cv *VartypeCheck) Integer() {
        if !matches(cv.Value, `^\d+$`) {
-               cv.Line.Warn1("Invalid integer %q.", cv.Value)
+               cv.Line.Warnf("Invalid integer %q.", cv.Value)
        }
 }
 
@@ -464,7 +464,7 @@ func (cv *VartypeCheck) LdFlag() {
        }
        ldflag := cv.Value
        if m, rpathFlag := match1(ldflag, `^(-Wl,(?:-R|-rpath|--rpath))`); m {
-               cv.Line.Warn1("Please use \"${COMPILER_RPATH_FLAG}\" instead of %q.", rpathFlag)
+               cv.Line.Warnf("Please use \"${COMPILER_RPATH_FLAG}\" instead of %q.", rpathFlag)
                return
        }
 
@@ -479,9 +479,9 @@ func (cv *VartypeCheck) LdFlag() {
                ldflag != cv.ValueNoVar:
                return
        case hasPrefix(ldflag, "-"):
-               cv.Line.Warn1("Unknown linker flag %q.", cv.Value)
+               cv.Line.Warnf("Unknown linker flag %q.", cv.Value)
        default:
-               cv.Line.Warn1("Linker flag %q should start with a hypen.", cv.Value)
+               cv.Line.Warnf("Linker flag %q should start with a hypen.", cv.Value)
        }
 }
 
@@ -530,7 +530,7 @@ func (cv *VartypeCheck) MachineGnuPlatfo
                enumMachineGnuPlatformOpsys.checker(opsysCv)
 
        } else {
-               cv.Line.Warn1("%q is not a valid platform pattern.", cv.Value)
+               cv.Line.Warnf("%q is not a valid platform pattern.", cv.Value)
                Explain(
                        "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.",
                        "Each of these components may be a shell globbing expression.",
@@ -547,14 +547,14 @@ func (cv *VartypeCheck) MailAddress() {
 
        if m, _, domain := match2(value, `^([+\-.0-9A-Z_a-z]+)@([-\w\d.]+)$`); m {
                if strings.EqualFold(domain, "NetBSD.org") && domain != "NetBSD.org" {
-                       line.Warn1("Please write \"NetBSD.org\" instead of %q.", domain)
+                       line.Warnf("Please write \"NetBSD.org\" instead of %q.", domain)
                }
                if matches(value, `(?i)^(tech-pkg|packages)@NetBSD\.org$`) {
-                       line.Error0("This mailing list address is obsolete. Use pkgsrc-users%NetBSD.org@localhost instead.")
+                       line.Errorf("This mailing list address is obsolete. Use pkgsrc-users%NetBSD.org@localhost instead.")
                }
 
        } else {
-               line.Warn1("\"%s\" is not a valid mail address.", value)
+               line.Warnf("\"%s\" is not a valid mail address.", value)
        }
 }
 
@@ -563,7 +563,7 @@ func (cv *VartypeCheck) Message() {
        line, varname, value := cv.Line, cv.Varname, cv.Value
 
        if matches(value, `^[\"'].*[\"']$`) {
-               line.Warn1("%s should not be quoted.", varname)
+               line.Warnf("%s should not be quoted.", varname)
                Explain(
                        "The quoting is only needed for variables which are interpreted as",
                        "multiple words (or, generally speaking, a list of something).  A",
@@ -588,8 +588,8 @@ func (cv *VartypeCheck) Option() {
 
        if m, optname := match1(value, `^-?([a-z][-0-9a-z+]*)$`); m {
                if _, found := G.globalData.PkgOptions[optname]; !found { // There’s a difference between empty and absent here.
-                       line.Warn1("Unknown option \"%s\".", optname)
-                       Explain4(
+                       line.Warnf("Unknown option \"%s\".", optname)
+                       Explain(
                                "This option is not documented in the mk/defaults/options.description",
                                "file.  Please think of a brief but precise description and either",
                                "update that file yourself or suggest a description for this option",
@@ -599,11 +599,11 @@ func (cv *VartypeCheck) Option() {
        }
 
        if matches(value, `^-?([a-z][-0-9a-z_\+]*)$`) {
-               line.Warn0("Use of the underscore character in option names is deprecated.")
+               line.Warnf("Use of the underscore character in option names is deprecated.")
                return
        }
 
-       line.Error1("Invalid option name %q. Option names must start with a lowercase letter and be all-lowercase.", value)
+       line.Errorf("Invalid option name %q. Option names must start with a lowercase letter and be all-lowercase.", value)
 }
 
 // The PATH environment variable
@@ -619,11 +619,11 @@ func (cv *VartypeCheck) Pathlist() {
                }
 
                if !matches(path, `^[-0-9A-Za-z._~+%/]*$`) {
-                       cv.Line.Warn1("%q is not a valid pathname.", path)
+                       cv.Line.Warnf("%q is not a valid pathname.", path)
                }
 
                if !hasPrefix(path, "/") {
-                       cv.Line.Warn2("All components of %s (in this case %q) should be absolute paths.", cv.Varname, path)
+                       cv.Line.Warnf("All components of %s (in this case %q) should be absolute paths.", cv.Varname, path)
                }
        }
 }
@@ -635,7 +635,7 @@ func (cv *VartypeCheck) Pathmask() {
                return
        }
        if !matches(cv.ValueNoVar, `^[#\-0-9A-Za-z._~+%*?/\[\]]*`) {
-               cv.Line.Warn1("%q is not a valid pathname mask.", cv.Value)
+               cv.Line.Warnf("%q is not a valid pathname mask.", cv.Value)
        }
        cv.Line.CheckAbsolutePathname(cv.Value)
 }
@@ -647,35 +647,35 @@ func (cv *VartypeCheck) Pathname() {
                return
        }
        if !matches(cv.ValueNoVar, `^[#\-0-9A-Za-z._~+%/]*$`) {
-               cv.Line.Warn1("%q is not a valid pathname.", cv.Value)
+               cv.Line.Warnf("%q is not a valid pathname.", cv.Value)
        }
        cv.Line.CheckAbsolutePathname(cv.Value)
 }
 
 func (cv *VartypeCheck) Perl5Packlist() {
        if cv.Value != cv.ValueNoVar {
-               cv.Line.Warn1("%s should not depend on other variables.", cv.Varname)
+               cv.Line.Warnf("%s should not depend on other variables.", cv.Varname)
        }
 }
 
 func (cv *VartypeCheck) Perms() {
        if cv.Value == "${ROOT_USER}" || cv.Value == "${ROOT_GROUP}" {
                valuename := cv.Value[2 : len(cv.Value)-1]
-               cv.Line.Error1("%s must not be used in permission definitions. Use REAL_%[1]s instead.", valuename)
+               cv.Line.Errorf("%s must not be used in permission definitions. Use REAL_%[1]s instead.", valuename)
        }
 }
 
 func (cv *VartypeCheck) PkgName() {
        if cv.Op != opUseMatch && cv.Value == cv.ValueNoVar && !matches(cv.Value, rePkgname) {
-               cv.Line.Warn1("%q is not a valid package name. A valid package name has the form packagename-version, where version consists only of digits, letters and dots.", cv.Value)
+               cv.Line.Warnf("%q is not a valid package name. A valid package name has the form packagename-version, where version consists only of digits, letters and dots.", cv.Value)
        }
 }
 
 func (cv *VartypeCheck) PkgOptionsVar() {
        cv.MkLine.CheckVartypePrimitive(cv.Varname, BtVariableName, cv.Op, cv.Value, cv.MkComment, cv.Guessed)
        if matches(cv.Value, `\$\{PKGBASE[:\}]`) {
-               cv.Line.Error0("PKGBASE must not be used in PKG_OPTIONS_VAR.")
-               Explain3(
+               cv.Line.Errorf("PKGBASE must not be used in PKG_OPTIONS_VAR.")
+               Explain(
                        "PKGBASE is defined in bsd.pkg.mk, which is included as the",
                        "very last file, but PKG_OPTIONS_VAR is evaluated earlier.",
                        "Use ${PKGNAME:C/-[0-9].*//} instead.")
@@ -683,7 +683,7 @@ func (cv *VartypeCheck) PkgOptionsVar() 
 
        // PR 46570, item "6. It should complain in PKG_OPTIONS_VAR is wrong"
        if !hasPrefix(cv.Value, "PKG_OPTIONS.") {
-               cv.Line.Error2("PKG_OPTIONS_VAR must be of the form %q, not %q.", "PKG_OPTIONS.*", cv.Value)
+               cv.Line.Errorf("PKG_OPTIONS_VAR must be of the form %q, not %q.", "PKG_OPTIONS.*", cv.Value)
        }
 }
 
@@ -695,10 +695,10 @@ func (cv *VartypeCheck) PkgPath() {
 
 func (cv *VartypeCheck) PkgRevision() {
        if !matches(cv.Value, `^[1-9]\d*$`) {
-               cv.Line.Warn1("%s must be a positive integer number.", cv.Varname)
+               cv.Line.Warnf("%s must be a positive integer number.", cv.Varname)
        }
        if path.Base(cv.Line.Fname) != "Makefile" {
-               cv.Line.Error1("%s only makes sense directly in the package Makefile.", cv.Varname)
+               cv.Line.Errorf("%s only makes sense directly in the package Makefile.", cv.Varname)
                Explain(
                        "Usually, different packages using the same Makefile.common have",
                        "different dependencies and will be bumped at different times (e.g.",
@@ -752,7 +752,7 @@ func (cv *VartypeCheck) MachinePlatformP
                enumMachineArch.checker(archCv)
 
        } else {
-               cv.Line.Warn1("%q is not a valid platform pattern.", cv.Value)
+               cv.Line.Warnf("%q is not a valid platform pattern.", cv.Value)
                Explain(
                        "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.",
                        "Each of these components may be a shell globbing expression.",
@@ -767,16 +767,16 @@ func (cv *VartypeCheck) MachinePlatformP
 // A pathname relative to ${PREFIX}.
 func (cv *VartypeCheck) PrefixPathname() {
        if m, mansubdir := match1(cv.Value, `^man/(.+)`); m {
-               cv.Line.Warn2("Please use \"${PKGMANDIR}/%s\" instead of %q.", mansubdir, cv.Value)
+               cv.Line.Warnf("Please use \"${PKGMANDIR}/%s\" instead of %q.", mansubdir, cv.Value)
        }
 }
 
 func (cv *VartypeCheck) PythonDependency() {
        if cv.Value != cv.ValueNoVar {
-               cv.Line.Warn0("Python dependencies should not contain variables.")
+               cv.Line.Warnf("Python dependencies should not contain variables.")
        } else if !matches(cv.ValueNoVar, `^[+\-.0-9A-Z_a-z]+(?:|:link|:build)$`) {
-               cv.Line.Warn1("Invalid Python dependency %q.", cv.Value)
-               Explain4(
+               cv.Line.Warnf("Invalid Python dependency %q.", cv.Value)
+               Explain(
                        "Python dependencies must be an identifier for a package, as",
                        "specified in lang/python/versioned_dependencies.mk.  This",
                        "identifier may be followed by :build for a build-time only",
@@ -796,8 +796,8 @@ func (cv *VartypeCheck) RelativePkgPath(
 
 func (cv *VartypeCheck) Restricted() {
        if cv.Value != "${RESTRICTED}" {
-               cv.Line.Warn1("The only valid value for %s is ${RESTRICTED}.", cv.Varname)
-               Explain3(
+               cv.Line.Warnf("The only valid value for %s is ${RESTRICTED}.", cv.Varname)
+               Explain(
                        "These variables are used to control which files may be mirrored on",
                        "FTP servers or CD-ROM collections.  They are not intended to mark",
                        "packages whose only MASTER_SITES are on ftp.NetBSD.org.")
@@ -814,8 +814,8 @@ func (cv *VartypeCheck) SedCommands() {
        tokens, rest := splitIntoShellTokens(line, cv.Value)
        if rest != "" {
                if strings.Contains(line.Text, "#") {
-                       line.Error1("Invalid shell words %q in sed commands.", rest)
-                       Explain4(
+                       line.Errorf("Invalid shell words %q in sed commands.", rest)
+                       Explain(
                                "When sed commands have embedded \"#\" characters, they need to be",
                                "escaped with a backslash, otherwise make(1) will interpret them as a",
                                "comment, no matter if they occur in single or double quotes or",
@@ -837,7 +837,7 @@ func (cv *VartypeCheck) SedCommands() {
                                i++
                                ncommands++
                                if ncommands > 1 {
-                                       line.Note0("Each sed command should appear in an assignment of its own.")
+                                       line.Notef("Each sed command should appear in an assignment of its own.")
                                        Explain(
                                                "For example, instead of",
                                                "    SUBST_SED.foo+=        -e s,command1,, -e s,command2,,",
@@ -849,7 +849,7 @@ func (cv *VartypeCheck) SedCommands() {
                                }
                                mkline.CheckVartypePrimitive(cv.Varname, BtSedCommand, cv.Op, tokens[i], cv.MkComment, cv.Guessed)
                        } else {
-                               line.Error0("The -e option to sed requires an argument.")
+                               line.Errorf("The -e option to sed requires an argument.")
                        }
                case token == "-E":
                        // Switch to extended regular expressions mode.
@@ -858,16 +858,16 @@ func (cv *VartypeCheck) SedCommands() {
                        // Don't print lines per default.
 
                case i == 0 && matches(token, `^(["']?)(?:\d*|/.*/)s.+["']?$`):
-                       line.Note0("Please always use \"-e\" in sed commands, even if there is only one substitution.")
+                       line.Notef("Please always use \"-e\" in sed commands, even if there is only one substitution.")
 
                default:
-                       line.Warn1("Unknown sed command %q.", token)
+                       line.Warnf("Unknown sed command %q.", token)
                }
        }
 }
 
 func (cv *VartypeCheck) ShellCommand() {
-       if cv.Op == opUseMatch || cv.Op == opUse {
+       if cv.Op == opUseMatch || cv.Op == opUseCompare {
                return
        }
        setE := true
@@ -885,7 +885,7 @@ func (cv *VartypeCheck) ShellWord() {
 
 func (cv *VartypeCheck) Stage() {
        if !matches(cv.Value, `^(?:pre|do|post)-(?:extract|patch|configure|build|test|install)`) {
-               cv.Line.Warn1("Invalid stage name %q. Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.", cv.Value)
+               cv.Line.Warnf("Invalid stage name %q. Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.", cv.Value)
        }
 }
 
@@ -895,15 +895,15 @@ func (cv *VartypeCheck) Tool() {
 
        } else if m, toolname, tooldep := match2(cv.Value, `^([-\w]+|\[)(?::(\w+))?$`); m {
                if G.globalData.Tools.byName[toolname] == nil && (G.Mk == nil || G.Mk.toolRegistry.byName[toolname] == nil) {
-                       cv.Line.Error1("Unknown tool %q.", toolname)
+                       cv.Line.Errorf("Unknown tool %q.", toolname)
                }
                switch tooldep {
                case "", "bootstrap", "build", "pkgsrc", "run":
                default:
-                       cv.Line.Error1("Unknown tool dependency %q. Use one of \"build\", \"pkgsrc\" or \"run\".", tooldep)
+                       cv.Line.Errorf("Unknown tool dependency %q. Use one of \"build\", \"pkgsrc\" or \"run\".", tooldep)
                }
        } else if cv.Op != opUseMatch {
-               cv.Line.Error1("Invalid tool syntax: %q.", cv.Value)
+               cv.Line.Errorf("Invalid tool syntax: %q.", cv.Value)
        }
 }
 
@@ -922,35 +922,35 @@ func (cv *VartypeCheck) URL() {
 
        } else if m, _, host, _, _ := match4(value, `^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:;=?@A-Z_a-z~]|#)*$`); m {
                if matches(host, `(?i)\.NetBSD\.org$`) && !matches(host, `\.NetBSD\.org$`) {
-                       line.Warn1("Please write NetBSD.org instead of %s.", host)
+                       line.Warnf("Please write NetBSD.org instead of %s.", host)
                }
 
        } else if m, scheme, _, absPath := match3(value, `^([0-9A-Za-z]+)://([^/]+)(.*)$`); m {
                switch {
                case scheme != "ftp" && scheme != "http" && scheme != "https" && scheme != "gopher":
-                       line.Warn1("%q is not a valid URL. Only ftp, gopher, http, and https URLs are allowed here.", value)
+                       line.Warnf("%q is not a valid URL. Only ftp, gopher, http, and https URLs are allowed here.", value)
 
                case absPath == "":
-                       line.Note1("For consistency, please add a trailing slash to %q.", value)
+                       line.Notef("For consistency, please add a trailing slash to %q.", value)
 
                default:
-                       line.Warn1("%q is not a valid URL.", value)
+                       line.Warnf("%q is not a valid URL.", value)
                }
 
        } else {
-               line.Warn1("%q is not a valid URL.", value)
+               line.Warnf("%q is not a valid URL.", value)
        }
 }
 
 func (cv *VartypeCheck) UserGroupName() {
        if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[0-9_a-z]+$`) {
-               cv.Line.Warn1("Invalid user or group name %q.", cv.Value)
+               cv.Line.Warnf("Invalid user or group name %q.", cv.Value)
        }
 }
 
 func (cv *VartypeCheck) VariableName() {
        if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[A-Z_][0-9A-Z_]*(?:[.].*)?$`) {
-               cv.Line.Warn1("%q is not a valid variable name.", cv.Value)
+               cv.Line.Warnf("%q is not a valid variable name.", cv.Value)
                Explain(
                        "Variable names are restricted to only uppercase letters and the",
                        "underscore in the basename, and arbitrary characters in the",
@@ -965,16 +965,16 @@ func (cv *VartypeCheck) VariableName() {
 func (cv *VartypeCheck) Version() {
        if cv.Op == opUseMatch {
                if !matches(cv.Value, `^[\d?\[][\w\-.*?\[\]]+$`) {
-                       cv.Line.Warn1("Invalid version number pattern %q.", cv.Value)
+                       cv.Line.Warnf("Invalid version number pattern %q.", cv.Value)
                }
        } else if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^\d[\w.]*$`) {
-               cv.Line.Warn1("Invalid version number %q.", cv.Value)
+               cv.Line.Warnf("Invalid version number %q.", cv.Value)
        }
 }
 
 func (cv *VartypeCheck) WrapperReorder() {
        if !matches(cv.Value, `^reorder:l:([\w\-]+):([\w\-]+)$`) {
-               cv.Line.Warn1("Unknown wrapper reorder command %q.", cv.Value)
+               cv.Line.Warnf("Unknown wrapper reorder command %q.", cv.Value)
        }
 }
 
@@ -987,7 +987,7 @@ func (cv *VartypeCheck) WrapperTransform
                matches(cmd, `^["']?s[|:,]`) {
                return
        }
-       cv.Line.Warn1("Unknown wrapper transform command %q.", cmd)
+       cv.Line.Warnf("Unknown wrapper transform command %q.", cmd)
 }
 
 func (cv *VartypeCheck) WrkdirSubdirectory() {
@@ -1000,22 +1000,22 @@ func (cv *VartypeCheck) WrksrcSubdirecto
                if rest == "" {
                        rest = "."
                }
-               cv.Line.Note2("You can use %q instead of %q.", rest, cv.Value)
-               Explain1(
+               cv.Line.Notef("You can use %q instead of %q.", rest, cv.Value)
+               Explain(
                        "These directories are interpreted relative to ${WRKSRC}.")
 
        } else if cv.Value != "" && cv.ValueNoVar == "" {
                // The value of another variable
 
        } else if !matches(cv.ValueNoVar, `^(?:\.|[0-9A-Za-z_@][-0-9A-Za-z_@./+]*)$`) {
-               cv.Line.Warn1("%q is not a valid subdirectory of ${WRKSRC}.", cv.Value)
+               cv.Line.Warnf("%q is not a valid subdirectory of ${WRKSRC}.", cv.Value)
        }
 }
 
 func (cv *VartypeCheck) Yes() {
        switch cv.Op {
        case opUseMatch:
-               cv.Line.Warn1("%s should only be used in a \".if defined(...)\" conditional.", cv.Varname)
+               cv.Line.Warnf("%s should only be used in a \".if defined(...)\" conditional.", cv.Varname)
                Explain(
                        "This variable can have only two values: defined or undefined.",
                        "When it is defined, it means \"yes\", even when its value is",
@@ -1026,8 +1026,8 @@ func (cv *VartypeCheck) Yes() {
 
        default:
                if !matches(cv.Value, `^(?:YES|yes)(?:\s+#.*)?$`) {
-                       cv.Line.Warn1("%s should be set to YES or yes.", cv.Varname)
-                       Explain4(
+                       cv.Line.Warnf("%s should be set to YES or yes.", cv.Varname)
+                       Explain(
                                "This variable means \"yes\" if it is defined, and \"no\" if it is",
                                "undefined.  Even when it has the value \"no\", this means \"yes\".",
                                "Therefore when it is defined, its value should correspond to its",
@@ -1049,14 +1049,14 @@ func (cv *VartypeCheck) YesNo() {
                default:
                        cv.Line.Warnf("%s should be matched against %q or %q, not %q.", cv.Varname, yes1, no1, cv.Value)
                }
-       } else if cv.Op == opUse {
+       } else if cv.Op == opUseCompare {
                cv.Line.Warnf("%s should be matched against %q or %q, not compared with %q.", cv.Varname, yes1, no1, cv.Value)
                Explain(
                        "The yes/no value can be written in either upper or lower case, and",
                        "both forms are actually used.  As long as this is the case, when",
                        "checking the variable value, both must be accepted.")
        } else if !matches(cv.Value, `^(?:YES|yes|NO|no)(?:\s+#.*)?$`) {
-               cv.Line.Warn1("%s should be set to YES, yes, NO, or no.", cv.Varname)
+               cv.Line.Warnf("%s should be set to YES, yes, NO, or no.", cv.Varname)
        }
 }
 

Added files:

Index: pkgsrc/pkgtools/pkglint/files/regex.go
diff -u /dev/null pkgsrc/pkgtools/pkglint/files/regex.go:1.1
--- /dev/null   Sun Dec  4 15:28:37 2016
+++ pkgsrc/pkgtools/pkglint/files/regex.go      Sun Dec  4 15:28:36 2016
@@ -0,0 +1,112 @@
+package main
+
+import (
+       "fmt"
+       "regexp"
+       "time"
+)
+
+type RegexPattern string
+
+func regcomp(re RegexPattern) *regexp.Regexp {
+       if G.res == nil {
+               G.res = make(map[RegexPattern]*regexp.Regexp)
+       }
+       cre := G.res[re]
+       if cre == nil {
+               cre = regexp.MustCompile(string(re))
+               G.res[re] = cre
+       }
+       return cre
+}
+
+func match(s string, re RegexPattern) []string {
+       if !G.opts.Profiling {
+               return regcomp(re).FindStringSubmatch(s)
+       }
+
+       before := time.Now()
+       immediatelyBefore := time.Now()
+       m := regcomp(re).FindStringSubmatch(s)
+       after := time.Now()
+
+       delay := immediatelyBefore.UnixNano() - before.UnixNano()
+       timeTaken := after.UnixNano() - immediatelyBefore.UnixNano() - delay
+
+       G.retime.Add(string(re), int(timeTaken))
+       if m != nil {
+               G.rematch.Add(string(re), 1)
+       } else {
+               G.renomatch.Add(string(re), 1)
+       }
+       return m
+}
+
+func matches(s string, re RegexPattern) bool {
+       matches := regcomp(re).MatchString(s)
+       if G.opts.Profiling {
+               if matches {
+                       G.rematch.Add(string(re), 1)
+               } else {
+                       G.renomatch.Add(string(re), 1)
+               }
+       }
+       return matches
+}
+
+func matchn(s string, re RegexPattern, n int) []string {
+       if m := match(s, re); m != nil {
+               if len(m) != 1+n {
+                       panic(fmt.Sprintf("expected match%d, got match%d for %q", len(m)-1, n, re))
+               }
+               return m
+       }
+       return nil
+}
+
+func match1(s string, re RegexPattern) (matched bool, m1 string) {
+       if m := matchn(s, re, 1); m != nil {
+               return true, m[1]
+       }
+       return
+}
+func match2(s string, re RegexPattern) (matched bool, m1, m2 string) {
+       if m := matchn(s, re, 2); m != nil {
+               return true, m[1], m[2]
+       }
+       return
+}
+func match3(s string, re RegexPattern) (matched bool, m1, m2, m3 string) {
+       if m := matchn(s, re, 3); m != nil {
+               return true, m[1], m[2], m[3]
+       }
+       return
+}
+func match4(s string, re RegexPattern) (matched bool, m1, m2, m3, m4 string) {
+       if m := matchn(s, re, 4); m != nil {
+               return true, m[1], m[2], m[3], m[4]
+       }
+       return
+}
+func match5(s string, re RegexPattern) (matched bool, m1, m2, m3, m4, m5 string) {
+       if m := matchn(s, re, 5); m != nil {
+               return true, m[1], m[2], m[3], m[4], m[5]
+       }
+       return
+}
+
+func replaceFirst(s string, re RegexPattern, replacement string) ([]string, string) {
+       if G.opts.Debug {
+               defer tracecall(s, re, replacement)()
+       }
+
+       if m := regcomp(re).FindStringSubmatchIndex(s); m != nil {
+               replaced := s[:m[0]] + replacement + s[m[1]:]
+               mm := make([]string, len(m)/2)
+               for i := 0; i < len(m); i += 2 {
+                       mm[i/2] = s[negToZero(m[i]):negToZero(m[i+1])]
+               }
+               return mm, replaced
+       }
+       return nil, s
+}



Home | Main Index | Thread Index | Old Index