Source-Changes-HG archive

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

[pkgsrc/trunk]: pkgsrc/pkgtools/pkglint pkgtools/pkglint: update to 20.1.18



details:   https://anonhg.NetBSD.org/pkgsrc/rev/44fe8dfb8c6a
branches:  trunk
changeset: 434641:44fe8dfb8c6a
user:      rillig <rillig%pkgsrc.org@localhost>
date:      Sat Jun 20 07:00:44 2020 +0000

description:
pkgtools/pkglint: update to 20.1.18

Changes since 20.1.17:

Fixed the algorithm for checking whether two patterns overlap, such as
MACHINE_PLATFORM:MNetBSD-[0-9].*-*.

Fixed wrong warning about foreign variable in SUBST block, as seen in
geography/qgis.

diffstat:

 pkgtools/pkglint/Makefile                   |    5 +-
 pkgtools/pkglint/files/check_test.go        |    1 -
 pkgtools/pkglint/files/makepat/pat.go       |  230 ++++++++++++++++++---------
 pkgtools/pkglint/files/makepat/pat_test.go  |  183 +++++++++++++++++++--
 pkgtools/pkglint/files/scope.go             |    6 +-
 pkgtools/pkglint/files/scope_test.go        |  206 ++++++++++++++++++++++++-
 pkgtools/pkglint/files/substcontext.go      |    8 +
 pkgtools/pkglint/files/substcontext_test.go |   16 +
 pkgtools/pkglint/files/vardefs.go           |    2 +-
 9 files changed, 545 insertions(+), 112 deletions(-)

diffs (truncated from 928 to 300 lines):

diff -r 3705fc460ba6 -r 44fe8dfb8c6a pkgtools/pkglint/Makefile
--- a/pkgtools/pkglint/Makefile Sat Jun 20 06:59:42 2020 +0000
+++ b/pkgtools/pkglint/Makefile Sat Jun 20 07:00:44 2020 +0000
@@ -1,7 +1,6 @@
-# $NetBSD: Makefile,v 1.657 2020/06/17 09:54:12 bsiegert Exp $
+# $NetBSD: Makefile,v 1.658 2020/06/20 07:00:44 rillig Exp $
 
-PKGNAME=       pkglint-20.1.17
-PKGREVISION=   1
+PKGNAME=       pkglint-20.1.18
 CATEGORIES=    pkgtools
 DISTNAME=      tools
 MASTER_SITES=  ${MASTER_SITE_GITHUB:=golang/}
diff -r 3705fc460ba6 -r 44fe8dfb8c6a pkgtools/pkglint/files/check_test.go
--- a/pkgtools/pkglint/files/check_test.go      Sat Jun 20 06:59:42 2020 +0000
+++ b/pkgtools/pkglint/files/check_test.go      Sat Jun 20 07:00:44 2020 +0000
@@ -128,7 +128,6 @@
        ck.Configure("pkglint.go", "*", "*", -intqa.EMissingTest)        // TODO
        ck.Configure("pkgsrc.go", "*", "*", -intqa.EMissingTest)         // TODO
        ck.Configure("redundantscope.go", "*", "*", -intqa.EMissingTest) // TODO
-       ck.Configure("scope.go", "*", "*", -intqa.EMissingTest)          // TODO
        ck.Configure("shell.go", "*", "*", -intqa.EMissingTest)          // TODO
        ck.Configure("shtokenizer.go", "*", "*", -intqa.EMissingTest)    // TODO
        ck.Configure("shtypes.go", "*", "*", -intqa.EMissingTest)        // TODO
diff -r 3705fc460ba6 -r 44fe8dfb8c6a pkgtools/pkglint/files/makepat/pat.go
--- a/pkgtools/pkglint/files/makepat/pat.go     Sat Jun 20 06:59:42 2020 +0000
+++ b/pkgtools/pkglint/files/makepat/pat.go     Sat Jun 20 07:00:44 2020 +0000
@@ -27,22 +27,20 @@
 // Compile parses a pattern, including the error checking that is missing
 // from bmake.
 func Compile(pattern string) (*Pattern, error) {
-       var a Pattern
-       s := a.AddState(false)
-
-       var deadEnd StateID
+       var p Pattern
+       s := p.AddState(false)
 
        lex := textproc.NewLexer(pattern)
        for !lex.EOF() {
 
                if lex.SkipByte('*') {
-                       a.AddTransition(s, 0, 255, s)
+                       p.AddTransition(s, 0, 255, s)
                        continue
                }
 
                if lex.SkipByte('?') {
-                       next := a.AddState(false)
-                       a.AddTransition(s, 0, 255, next)
+                       next := p.AddState(false)
+                       p.AddTransition(s, 0, 255, next)
                        s = next
                        continue
                }
@@ -52,112 +50,194 @@
                                return nil, errors.New("unfinished escape sequence")
                        }
                        ch := lex.NextByte()
-                       next := a.AddState(false)
-                       a.AddTransition(s, ch, ch, next)
+                       next := p.AddState(false)
+                       p.AddTransition(s, ch, ch, next)
                        s = next
                        continue
                }
 
                ch := lex.NextByte()
                if ch != '[' {
-                       next := a.AddState(false)
-                       a.AddTransition(s, ch, ch, next)
+                       next := p.AddState(false)
+                       p.AddTransition(s, ch, ch, next)
                        s = next
                        continue
                }
 
-               negate := lex.SkipByte('^')
-               if negate && deadEnd == 0 {
-                       deadEnd = a.AddState(false)
+               next, err := compileCharClass(&p, lex, ch, s)
+               if err != nil {
+                       return nil, err
                }
-               next := a.AddState(false)
-               for {
-                       if lex.EOF() {
-                               return nil, errors.New("unfinished character class")
-                       }
-                       ch = lex.NextByte()
-                       if ch == ']' {
-                               break
-                       }
-                       max := ch
-                       if lex.SkipByte('-') {
-                               if lex.EOF() {
-                                       return nil, errors.New("unfinished character range")
-                               }
-                               max = lex.NextByte()
-                       }
 
-                       to := next
-                       if negate {
-                               to = deadEnd
-                       }
-                       a.AddTransition(s, bmin(ch, max), bmax(ch, max), to)
-               }
-               if negate {
-                       a.AddTransition(s, 0, 255, next)
-               }
                s = next
        }
 
-       a.states[s].end = true
-       return &a, nil
+       p.states[s].end = true
+       return &p, nil
 }
 
-func (a *Pattern) AddState(end bool) StateID {
-       a.states = append(a.states, state{nil, end})
-       return StateID(len(a.states) - 1)
+func compileCharClass(p *Pattern, lex *textproc.Lexer, ch byte, s StateID) (StateID, error) {
+       negate := lex.SkipByte('^')
+       chars := make([]bool, 256)
+       next := p.AddState(false)
+       for {
+               if lex.EOF() {
+                       return 0, errors.New("unfinished character class")
+               }
+               ch = lex.NextByte()
+               if ch == ']' {
+                       break
+               }
+               if lex.SkipByte('-') {
+                       if lex.EOF() {
+                               return 0, errors.New("unfinished character range")
+                       }
+                       max := lex.NextByte()
+                       if ch > max {
+                               ch, max = max, ch
+                       }
+                       for i := int(ch); i <= int(max); i++ {
+                               chars[i] = true
+                       }
+               } else {
+                       chars[ch] = true
+               }
+       }
+       if negate {
+               for i, b := range chars {
+                       chars[i] = !b
+               }
+       }
+
+       start := 0
+       for start < len(chars) && !chars[start] {
+               start++
+       }
+
+       for start < len(chars) {
+               end := start
+               for end < len(chars) && chars[end] {
+                       end++
+               }
+
+               if start < end {
+                       p.AddTransition(s, byte(start), byte(end-1), next)
+               }
+
+               start = end
+               for start < len(chars) && !chars[start] {
+                       start++
+               }
+       }
+       return next, nil
 }
 
-func (a *Pattern) AddTransition(from StateID, min, max byte, to StateID) {
-       state := &a.states[from]
+func (p *Pattern) AddState(end bool) StateID {
+       p.states = append(p.states, state{nil, end})
+       return StateID(len(p.states) - 1)
+}
+
+func (p *Pattern) AddTransition(from StateID, min, max byte, to StateID) {
+       state := &p.states[from]
        state.transitions = append(state.transitions, transition{min, max, to})
 }
 
 // Match tests whether a pattern matches the given string.
-func (a *Pattern) Match(s string) bool {
-       state := StateID(0)
+func (p *Pattern) Match(s string) bool {
+       curr := make([]bool, len(p.states))
+       next := make([]bool, len(p.states))
+
+       curr[0] = true
        for _, ch := range []byte(s) {
-               for _, tr := range a.states[state].transitions {
-                       if tr.min <= ch && ch <= tr.max {
-                               state = tr.to
-                               goto nextByte
+               ok := false
+               for i, _ := range next {
+                       next[i] = false
+               }
+
+               for si := range curr {
+                       if !curr[si] {
+                               continue
+                       }
+                       for _, tr := range p.states[si].transitions {
+                               if tr.min <= ch && ch <= tr.max {
+                                       next[tr.to] = true
+                                       ok = true
+                               }
                        }
                }
-               return false
-       nextByte:
+               if !ok {
+                       return false
+               }
+               curr, next = next, curr
        }
-       return a.states[state].end
+
+       for i, curr := range curr {
+               if curr && p.states[i].end {
+                       return true
+               }
+       }
+       return false
 }
 
 // Intersect computes a pattern that only matches if both given patterns
 // match at the same time.
-func Intersect(a, b *Pattern) *Pattern {
-       var is Pattern
-       for i := 0; i < len(a.states); i++ {
-               for j := 0; j < len(b.states); j++ {
-                       is.AddState(a.states[i].end && b.states[j].end)
+func Intersect(p1, p2 *Pattern) *Pattern {
+       var res Pattern
+       for i1 := 0; i1 < len(p1.states); i1++ {
+               for i2 := 0; i2 < len(p2.states); i2++ {
+                       res.AddState(p1.states[i1].end && p2.states[i2].end)
                }
        }
 
-       for i := 0; i < len(a.states); i++ {
-               for j := 0; j < len(b.states); j++ {
-                       for _, at := range a.states[i].transitions {
-                               for _, bt := range b.states[j].transitions {
-                                       min := bmax(at.min, bt.min)
-                                       max := bmin(at.max, bt.max)
+       for i1 := 0; i1 < len(p1.states); i1++ {
+               for i2 := 0; i2 < len(p2.states); i2++ {
+                       for _, t1 := range p1.states[i1].transitions {
+                               for _, t2 := range p2.states[i2].transitions {
+                                       min := bmax(t1.min, t2.min)
+                                       max := bmin(t1.max, t2.max)
                                        if min <= max {
-                                               from := StateID(i*len(b.states) + j)
-                                               to := at.to*StateID(len(b.states)) + bt.to
-                                               is.AddTransition(from, min, max, to)
+                                               from := StateID(i1*len(p2.states) + i2)
+                                               to := t1.to*StateID(len(p2.states)) + t2.to
+                                               res.AddTransition(from, min, max, to)
                                        }
                                }
                        }
                }
        }
 
-       // TODO: optimize: remove transitions that point to a dead end
+       return res.optimized()
+}
+
+func (p *Pattern) optimized() *Pattern {
+       var opt Pattern
+
+       var todo []StateID
+       hasNewID := make([]bool, len(p.states))
+       newIDs := make([]StateID, len(p.states))
+
+       todo = append(todo, 0)
+       newIDs[0] = opt.AddState(p.states[0].end)
+       hasNewID[0] = true
 
-       return &is
+       for len(todo) > 0 {
+               oldStateID := todo[len(todo)-1]
+               todo = todo[:len(todo)-1]
+
+               oldState := p.states[oldStateID]
+
+               for _, t := range oldState.transitions {
+                       if !hasNewID[t.to] {



Home | Main Index | Thread Index | Old Index