Source file
src/cmd/covdata/subtractintersect.go
1
2
3
4
5 package main
6
7
8
9
10 import (
11 "flag"
12 "fmt"
13 "internal/coverage"
14 "internal/coverage/decodecounter"
15 "internal/coverage/decodemeta"
16 "internal/coverage/pods"
17 "os"
18 "strings"
19 )
20
21
22
23 func makeSubtractIntersectOp(mode string) covOperation {
24 outdirflag = flag.String("o", "", "Output directory to write")
25 s := &sstate{
26 mode: mode,
27 mm: newMetaMerge(),
28 inidx: -1,
29 }
30 return s
31 }
32
33
34
35
36
37
38 type sstate struct {
39 mm *metaMerge
40 inidx int
41 mode string
42
43
44
45 imm map[pkfunc]struct{}
46 }
47
48 func (s *sstate) Usage(msg string) {
49 if len(msg) > 0 {
50 fmt.Fprintf(os.Stderr, "error: %s\n", msg)
51 }
52 fmt.Fprintf(os.Stderr, "usage: go tool covdata %s -i=dir1,dir2 -o=<dir>\n\n", s.mode)
53 flag.PrintDefaults()
54 fmt.Fprintf(os.Stderr, "\nExamples:\n\n")
55 op := "from"
56 if s.mode == intersectMode {
57 op = "with"
58 }
59 fmt.Fprintf(os.Stderr, " go tool covdata %s -i=dir1,dir2 -o=outdir\n\n", s.mode)
60 fmt.Fprintf(os.Stderr, " \t%ss dir2 %s dir1, writing result\n", s.mode, op)
61 fmt.Fprintf(os.Stderr, " \tinto output dir outdir.\n")
62 os.Exit(2)
63 }
64
65 func (s *sstate) Setup() {
66 if *indirsflag == "" {
67 usage("select input directories with '-i' option")
68 }
69 indirs := strings.Split(*indirsflag, ",")
70 if s.mode == subtractMode && len(indirs) != 2 {
71 usage("supply exactly two input dirs for subtract operation")
72 }
73 if *outdirflag == "" {
74 usage("select output directory with '-o' option")
75 }
76 }
77
78 func (s *sstate) BeginPod(p pods.Pod) {
79 s.mm.beginPod()
80 }
81
82 func (s *sstate) EndPod(p pods.Pod) {
83 const pcombine = false
84 s.mm.endPod(pcombine)
85 }
86
87 func (s *sstate) EndCounters() {
88 if s.imm != nil {
89 s.pruneCounters()
90 }
91 }
92
93
94
95
96 func (s *sstate) pruneCounters() {
97 pkeys := make([]pkfunc, 0, len(s.mm.pod.pmm))
98 for k := range s.mm.pod.pmm {
99 pkeys = append(pkeys, k)
100 }
101
102
103
104 for _, k := range pkeys {
105 if _, found := s.imm[k]; !found {
106 delete(s.mm.pod.pmm, k)
107 }
108 }
109 s.imm = nil
110 }
111
112 func (s *sstate) BeginCounterDataFile(cdf string, cdr *decodecounter.CounterDataReader, dirIdx int) {
113 dbgtrace(2, "visiting counter data file %s diridx %d", cdf, dirIdx)
114 if s.inidx != dirIdx {
115 if s.inidx > dirIdx {
116
117
118
119 panic("decreasing dir index, internal error")
120 }
121 if dirIdx == 0 {
122
123
124
125 s.imm = nil
126 } else {
127
128 if s.mode == intersectMode {
129 if s.imm != nil {
130 s.pruneCounters()
131 }
132 s.imm = make(map[pkfunc]struct{})
133 }
134 }
135 s.inidx = dirIdx
136 }
137 }
138
139 func (s *sstate) EndCounterDataFile(cdf string, cdr *decodecounter.CounterDataReader, dirIdx int) {
140 }
141
142 func (s *sstate) VisitFuncCounterData(data decodecounter.FuncPayload) {
143 key := pkfunc{pk: data.PkgIdx, fcn: data.FuncIdx}
144
145 if *verbflag >= 5 {
146 fmt.Printf("ctr visit fid=%d pk=%d inidx=%d data.Counters=%+v\n", data.FuncIdx, data.PkgIdx, s.inidx, data.Counters)
147 }
148
149
150
151
152 if s.inidx == 0 {
153 s.mm.visitFuncCounterData(data)
154 return
155 }
156
157
158
159 if val, ok := s.mm.pod.pmm[key]; ok {
160 if s.mode == subtractMode {
161 for i := 0; i < len(data.Counters); i++ {
162 if data.Counters[i] != 0 {
163 val.Counters[i] = 0
164 }
165 }
166 } else if s.mode == intersectMode {
167 s.imm[key] = struct{}{}
168 for i := 0; i < len(data.Counters); i++ {
169 if data.Counters[i] == 0 {
170 val.Counters[i] = 0
171 }
172 }
173 }
174 }
175 }
176
177 func (s *sstate) VisitMetaDataFile(mdf string, mfr *decodemeta.CoverageMetaFileReader) {
178 if s.mode == intersectMode {
179 s.imm = make(map[pkfunc]struct{})
180 }
181 s.mm.visitMetaDataFile(mdf, mfr)
182 }
183
184 func (s *sstate) BeginPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32) {
185 s.mm.visitPackage(pd, pkgIdx, false)
186 }
187
188 func (s *sstate) EndPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32) {
189 }
190
191 func (s *sstate) VisitFunc(pkgIdx uint32, fnIdx uint32, fd *coverage.FuncDesc) {
192 s.mm.visitFunc(pkgIdx, fnIdx, fd, s.mode, false)
193 }
194
195 func (s *sstate) Finish() {
196 }
197
View as plain text