blob: 79aee7788bfe50f6da7885d87ba6e3f9f15d3f0b [file] [log] [blame]
Rob Pikee7601e22009-12-29 14:03:33 +11001package gob
2
3// This file is not normally included in the gob package. Used only for debugging the package itself.
Rob Pikec490bb62010-10-29 15:52:25 -07004// Add debug.go to the files listed in the Makefile to add Debug to the gob package.
Rob Pike5b5a6742011-01-21 11:28:53 -08005// Except for reading uints, it is an implementation of a reader that is independent of
6// the one implemented by Decoder.
Rob Pikee7601e22009-12-29 14:03:33 +11007
8import (
9 "bytes"
10 "fmt"
11 "io"
Rob Pikee7601e22009-12-29 14:03:33 +110012 "os"
Rob Pike5b5a6742011-01-21 11:28:53 -080013 "strings"
14 "sync"
Rob Pikee7601e22009-12-29 14:03:33 +110015)
16
Rob Pike5b5a6742011-01-21 11:28:53 -080017var dumpBytes = false // If true, print the remaining bytes in the input buffer at each item.
Rob Pike96b9efe2010-10-29 15:07:56 -070018
19// Init installs the debugging facility. If this file is not compiled in the
Rob Pike5b5a6742011-01-21 11:28:53 -080020// package, the tests in codec_test.go are no-ops.
Rob Pike96b9efe2010-10-29 15:07:56 -070021func init() {
22 debugFunc = Debug
23}
24
Rob Pike5b5a6742011-01-21 11:28:53 -080025var (
26 blanks = bytes.Repeat([]byte{' '}, 3*10)
27 empty = []byte(": <empty>\n")
28 tabs = strings.Repeat("\t", 100)
29)
30
31// tab indents itself when printed.
32type tab int
33
34func (t tab) String() string {
35 n := int(t)
36 if n > len(tabs) {
37 n = len(tabs)
38 }
39 return tabs[0:n]
40}
41
42func (t tab) print() {
43 fmt.Fprint(os.Stderr, t)
44}
45
46// A peekReader wraps an io.Reader, allowing one to peek ahead to see
47// what's coming without stealing the data from the client of the Reader.
48type peekReader struct {
49 r io.Reader
50 data []byte // read-ahead data
51}
52
53// newPeekReader returns a peekReader that wraps r.
54func newPeekReader(r io.Reader) *peekReader {
55 return &peekReader{r: r}
56}
57
58// Read is the usual method. It will first take data that has been read ahead.
59func (p *peekReader) Read(b []byte) (n int, err os.Error) {
60 if len(p.data) == 0 {
61 return p.r.Read(b)
62 }
63 // Satisfy what's possible from the read-ahead data.
64 n = copy(b, p.data)
65 // Move data down to beginning of slice, to avoid endless growth
66 copy(p.data, p.data[n:])
67 p.data = p.data[:len(p.data)-n]
68 return
69}
70
71// peek returns as many bytes as possible from the unread
72// portion of the stream, up to the length of b.
73func (p *peekReader) peek(b []byte) (n int, err os.Error) {
74 if len(p.data) > 0 {
75 n = copy(b, p.data)
76 if n == len(b) {
77 return
78 }
79 b = b[n:]
80 }
81 if len(b) == 0 {
82 return
83 }
84 m, e := io.ReadFull(p.r, b)
85 if m > 0 {
86 p.data = append(p.data, b[:m]...)
87 }
88 n += m
89 if e == io.ErrUnexpectedEOF {
90 // That means m > 0 but we reached EOF. If we got data
91 // we won't complain about not being able to peek enough.
92 if n > 0 {
93 e = nil
94 } else {
95 e = os.EOF
96 }
97 }
98 return n, e
99}
100
Rob Pike04a89052011-01-28 10:53:06 -0800101type debugger struct {
102 mutex sync.Mutex
103 remain int // the number of bytes known to remain in the input
104 remainingKnown bool // the value of 'remain' is valid
105 r *peekReader
106 wireType map[typeId]*wireType
107 tmp []byte // scratch space for decoding uints.
108}
109
Rob Pike5b5a6742011-01-21 11:28:53 -0800110// dump prints the next nBytes of the input.
111// It arranges to print the output aligned from call to
112// call, to make it easy to see what has been consumed.
Rob Pike04a89052011-01-28 10:53:06 -0800113func (deb *debugger) dump(format string, args ...interface{}) {
Rob Pike5b5a6742011-01-21 11:28:53 -0800114 if !dumpBytes {
115 return
116 }
117 fmt.Fprintf(os.Stderr, format+" ", args...)
Rob Pike04a89052011-01-28 10:53:06 -0800118 if !deb.remainingKnown {
Rob Pike5b5a6742011-01-21 11:28:53 -0800119 return
120 }
Rob Pike04a89052011-01-28 10:53:06 -0800121 if deb.remain < 0 {
122 fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain)
123 return
124 }
125 data := make([]byte, deb.remain)
Rob Pike5b5a6742011-01-21 11:28:53 -0800126 n, _ := deb.r.peek(data)
127 if n == 0 {
128 os.Stderr.Write(empty)
129 return
130 }
131 b := new(bytes.Buffer)
Rob Pike04a89052011-01-28 10:53:06 -0800132 fmt.Fprintf(b, "[%d]{\n", deb.remain)
Rob Pike5b5a6742011-01-21 11:28:53 -0800133 // Blanks until first byte
134 lineLength := 0
135 if n := len(data); n%10 != 0 {
136 lineLength = 10 - n%10
137 fmt.Fprintf(b, "\t%s", blanks[:lineLength*3])
138 }
139 // 10 bytes per line
140 for len(data) > 0 {
141 if lineLength == 0 {
142 fmt.Fprint(b, "\t")
143 }
144 m := 10 - lineLength
145 lineLength = 0
146 if m > len(data) {
147 m = len(data)
148 }
149 fmt.Fprintf(b, "% x\n", data[:m])
150 data = data[m:]
151 }
152 fmt.Fprint(b, "}\n")
153 os.Stderr.Write(b.Bytes())
154}
155
Rob Pikee7601e22009-12-29 14:03:33 +1100156// Debug prints a human-readable representation of the gob data read from r.
Rob Pike96b9efe2010-10-29 15:07:56 -0700157func Debug(r io.Reader) {
Rob Pikec91daef2011-03-04 12:25:18 -0800158 err := debug(r)
159 if err != nil {
160 fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
161 }
162}
163
164// debug implements Debug, but catches panics and returns
165// them as errors to be printed by Debug.
166func debug(r io.Reader) (err os.Error) {
167 defer catchError(&err)
Rob Pike5b5a6742011-01-21 11:28:53 -0800168 fmt.Fprintln(os.Stderr, "Start of debugging")
169 deb := &debugger{
170 r: newPeekReader(r),
171 wireType: make(map[typeId]*wireType),
172 tmp: make([]byte, 16),
173 }
Rob Pike04a89052011-01-28 10:53:06 -0800174 if b, ok := r.(*bytes.Buffer); ok {
175 deb.remain = b.Len()
176 deb.remainingKnown = true
177 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800178 deb.gobStream()
Rob Pikec91daef2011-03-04 12:25:18 -0800179 return
Rob Pike96b9efe2010-10-29 15:07:56 -0700180}
181
Rob Pike04a89052011-01-28 10:53:06 -0800182// note that we've consumed some bytes
183func (deb *debugger) consumed(n int) {
184 if deb.remainingKnown {
185 deb.remain -= n
Rob Pike96b9efe2010-10-29 15:07:56 -0700186 }
Rob Pike96b9efe2010-10-29 15:07:56 -0700187}
188
Rob Pike04a89052011-01-28 10:53:06 -0800189// int64 decodes and returns the next integer, which must be present.
Rob Pike5b5a6742011-01-21 11:28:53 -0800190// Don't call this if you could be at EOF.
Rob Pike04a89052011-01-28 10:53:06 -0800191func (deb *debugger) int64() int64 {
192 return toInt(deb.uint64())
Rob Pike5b5a6742011-01-21 11:28:53 -0800193}
Rob Pikee7601e22009-12-29 14:03:33 +1100194
Rob Pike04a89052011-01-28 10:53:06 -0800195// uint64 returns and decodes the next unsigned integer, which must be present.
Rob Pike5b5a6742011-01-21 11:28:53 -0800196// Don't call this if you could be at EOF.
197// TODO: handle errors better.
Rob Pike04a89052011-01-28 10:53:06 -0800198func (deb *debugger) uint64() uint64 {
Rob Pike5b5a6742011-01-21 11:28:53 -0800199 n, w, err := decodeUintReader(deb.r, deb.tmp)
200 if err != nil {
201 errorf("debug: read error: %s", err)
202 }
Rob Pike04a89052011-01-28 10:53:06 -0800203 deb.consumed(w)
204 return n
Rob Pike5b5a6742011-01-21 11:28:53 -0800205}
206
207// GobStream:
208// DelimitedMessage* (until EOF)
209func (deb *debugger) gobStream() {
Rob Pike96b9efe2010-10-29 15:07:56 -0700210 // Make sure we're single-threaded through here.
Rob Pike5b5a6742011-01-21 11:28:53 -0800211 deb.mutex.Lock()
212 defer deb.mutex.Unlock()
Rob Pikee7601e22009-12-29 14:03:33 +1100213
Rob Pike5b5a6742011-01-21 11:28:53 -0800214 for deb.delimitedMessage(0) {
Rob Pike96b9efe2010-10-29 15:07:56 -0700215 }
Rob Pike96b9efe2010-10-29 15:07:56 -0700216}
Rob Pikee7601e22009-12-29 14:03:33 +1100217
Rob Pike5b5a6742011-01-21 11:28:53 -0800218// DelimitedMessage:
219// uint(lengthOfMessage) Message
220func (deb *debugger) delimitedMessage(indent tab) bool {
221 for {
222 n := deb.loadBlock(true)
223 if n < 0 {
224 return false
Rob Pikee7601e22009-12-29 14:03:33 +1100225 }
Rob Pike04a89052011-01-28 10:53:06 -0800226 deb.dump("Delimited message of length %d", n)
227 deb.message(indent)
Rob Pike5b5a6742011-01-21 11:28:53 -0800228 }
229 return true
230}
Rob Pikee7601e22009-12-29 14:03:33 +1100231
Rob Pike5b5a6742011-01-21 11:28:53 -0800232// loadBlock preps us to read a message
233// of the length specified next in the input. It returns
234// the length of the block. The argument tells whether
235// an EOF is acceptable now. If it is and one is found,
236// the return value is negative.
237func (deb *debugger) loadBlock(eofOK bool) int {
Rob Pike04a89052011-01-28 10:53:06 -0800238 n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF
Rob Pike5b5a6742011-01-21 11:28:53 -0800239 if err != nil {
240 if eofOK && err == os.EOF {
241 return -1
242 }
243 errorf("debug: unexpected error: %s", err)
244 }
Rob Pike04a89052011-01-28 10:53:06 -0800245 deb.consumed(w)
Rob Pike5b5a6742011-01-21 11:28:53 -0800246 n := int(n64)
247 if n < 0 {
248 errorf("huge value for message length: %d", n64)
249 }
Rob Pike04a89052011-01-28 10:53:06 -0800250 return int(n)
Rob Pike5b5a6742011-01-21 11:28:53 -0800251}
252
253// Message:
254// TypeSequence TypedValue
255// TypeSequence
256// (TypeDefinition DelimitedTypeDefinition*)?
257// DelimitedTypeDefinition:
258// uint(lengthOfTypeDefinition) TypeDefinition
259// TypedValue:
260// int(typeId) Value
Rob Pike04a89052011-01-28 10:53:06 -0800261func (deb *debugger) message(indent tab) bool {
Rob Pike5b5a6742011-01-21 11:28:53 -0800262 for {
263 // Convert the uint64 to a signed integer typeId
Rob Pike04a89052011-01-28 10:53:06 -0800264 uid := deb.int64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800265 id := typeId(uid)
Rob Pike04a89052011-01-28 10:53:06 -0800266 deb.dump("type id=%d", id)
Rob Pike5b5a6742011-01-21 11:28:53 -0800267 if id < 0 {
Rob Pike04a89052011-01-28 10:53:06 -0800268 deb.typeDefinition(indent, -id)
269 n := deb.loadBlock(false)
270 deb.dump("Message of length %d", n)
Rob Pike5b5a6742011-01-21 11:28:53 -0800271 continue
272 } else {
Rob Pike04a89052011-01-28 10:53:06 -0800273 deb.value(indent, id)
Rob Pikee7601e22009-12-29 14:03:33 +1100274 break
275 }
Rob Pikee7601e22009-12-29 14:03:33 +1100276 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800277 return true
Rob Pikee7601e22009-12-29 14:03:33 +1100278}
279
Rob Pike04a89052011-01-28 10:53:06 -0800280// Helper methods to make it easy to scan a type descriptor.
281
282// common returns the CommonType at the input point.
283func (deb *debugger) common() CommonType {
284 fieldNum := -1
285 name := ""
286 id := typeId(0)
287 for {
288 delta := deb.delta(-1)
289 if delta == 0 {
290 break
291 }
292 fieldNum += delta
293 switch fieldNum {
294 case 0:
295 name = deb.string()
296 case 1:
297 // Id typeId
298 id = deb.typeId()
299 default:
300 errorf("corrupted CommonType")
301 }
302 }
303 return CommonType{name, id}
304}
305
306// uint returns the unsigned int at the input point, as a uint (not uint64).
307func (deb *debugger) uint() uint {
308 return uint(deb.uint64())
309}
310
311// int returns the signed int at the input point, as an int (not int64).
312func (deb *debugger) int() int {
313 return int(deb.int64())
314}
315
316// typeId returns the type id at the input point.
317func (deb *debugger) typeId() typeId {
318 return typeId(deb.int64())
319}
320
321// string returns the string at the input point.
322func (deb *debugger) string() string {
323 x := int(deb.uint64())
324 b := make([]byte, x)
325 nb, _ := deb.r.Read(b)
326 if nb != x {
327 errorf("corrupted type")
328 }
329 deb.consumed(nb)
330 return string(b)
331}
332
333// delta returns the field delta at the input point. The expect argument,
334// if non-negative, identifies what the value should be.
335func (deb *debugger) delta(expect int) int {
336 delta := int(deb.uint64())
337 if delta < 0 || (expect >= 0 && delta != expect) {
Rob Pikec4cc9c22011-04-20 14:22:52 -0700338 errorf("decode: corrupted type: delta %d expected %d", delta, expect)
Rob Pike04a89052011-01-28 10:53:06 -0800339 }
340 return delta
341}
342
Rob Pike5b5a6742011-01-21 11:28:53 -0800343// TypeDefinition:
344// [int(-typeId) (already read)] encodingOfWireType
Rob Pike04a89052011-01-28 10:53:06 -0800345func (deb *debugger) typeDefinition(indent tab, id typeId) {
346 deb.dump("type definition for id %d", id)
Rob Pike5b5a6742011-01-21 11:28:53 -0800347 // Encoding is of a wireType. Decode the structure as usual
348 fieldNum := -1
Rob Pikee7601e22009-12-29 14:03:33 +1100349 wire := new(wireType)
Rob Pike5b5a6742011-01-21 11:28:53 -0800350 // A wireType defines a single field.
Rob Pike04a89052011-01-28 10:53:06 -0800351 delta := deb.delta(-1)
Rob Pike5b5a6742011-01-21 11:28:53 -0800352 fieldNum += delta
353 switch fieldNum {
354 case 0: // array type, one field of {{Common}, elem, length}
355 // Field number 0 is CommonType
Rob Pike04a89052011-01-28 10:53:06 -0800356 deb.delta(1)
357 com := deb.common()
Rob Pike5b5a6742011-01-21 11:28:53 -0800358 // Field number 1 is type Id of elem
Rob Pike04a89052011-01-28 10:53:06 -0800359 deb.delta(1)
360 id := deb.typeId()
Rob Pike5b5a6742011-01-21 11:28:53 -0800361 // Field number 3 is length
Rob Pike04a89052011-01-28 10:53:06 -0800362 deb.delta(1)
363 length := deb.int()
Rob Pike5b5a6742011-01-21 11:28:53 -0800364 wire.ArrayT = &arrayType{com, id, length}
Rob Pike96b9efe2010-10-29 15:07:56 -0700365
Rob Pike5b5a6742011-01-21 11:28:53 -0800366 case 1: // slice type, one field of {{Common}, elem}
367 // Field number 0 is CommonType
Rob Pike04a89052011-01-28 10:53:06 -0800368 deb.delta(1)
369 com := deb.common()
Rob Pike5b5a6742011-01-21 11:28:53 -0800370 // Field number 1 is type Id of elem
Rob Pike04a89052011-01-28 10:53:06 -0800371 deb.delta(1)
372 id := deb.typeId()
Rob Pike5b5a6742011-01-21 11:28:53 -0800373 wire.SliceT = &sliceType{com, id}
Rob Pikee7601e22009-12-29 14:03:33 +1100374
Rob Pike5b5a6742011-01-21 11:28:53 -0800375 case 2: // struct type, one field of {{Common}, []fieldType}
376 // Field number 0 is CommonType
Rob Pike04a89052011-01-28 10:53:06 -0800377 deb.delta(1)
378 com := deb.common()
Rob Pike5b5a6742011-01-21 11:28:53 -0800379 // Field number 1 is slice of FieldType
Rob Pike04a89052011-01-28 10:53:06 -0800380 deb.delta(1)
381 numField := int(deb.uint())
Rob Pike5b5a6742011-01-21 11:28:53 -0800382 field := make([]*fieldType, numField)
383 for i := 0; i < numField; i++ {
384 field[i] = new(fieldType)
Rob Pike04a89052011-01-28 10:53:06 -0800385 deb.delta(1) // field 0 of fieldType: name
386 field[i].Name = deb.string()
387 deb.delta(1) // field 1 of fieldType: id
388 field[i].Id = deb.typeId()
389 deb.delta(0) // end of fieldType
Rob Pikee7601e22009-12-29 14:03:33 +1100390 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800391 wire.StructT = &structType{com, field}
392
393 case 3: // map type, one field of {{Common}, key, elem}
394 // Field number 0 is CommonType
Rob Pike04a89052011-01-28 10:53:06 -0800395 deb.delta(1)
396 com := deb.common()
Rob Pike5b5a6742011-01-21 11:28:53 -0800397 // Field number 1 is type Id of key
Rob Pike04a89052011-01-28 10:53:06 -0800398 deb.delta(1)
399 keyId := deb.typeId()
Rob Pike5b5a6742011-01-21 11:28:53 -0800400 // Field number 2 is type Id of elem
Rob Pike04a89052011-01-28 10:53:06 -0800401 deb.delta(1)
402 elemId := deb.typeId()
Rob Pike5b5a6742011-01-21 11:28:53 -0800403 wire.MapT = &mapType{com, keyId, elemId}
Rob Pikec91daef2011-03-04 12:25:18 -0800404 case 4: // GobEncoder type, one field of {{Common}}
405 // Field number 0 is CommonType
406 deb.delta(1)
407 com := deb.common()
408 wire.GobEncoderT = &gobEncoderType{com}
Rob Pike5b5a6742011-01-21 11:28:53 -0800409 default:
410 errorf("bad field in type %d", fieldNum)
Rob Pikee7601e22009-12-29 14:03:33 +1100411 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800412 deb.printWireType(indent, wire)
Rob Pike04a89052011-01-28 10:53:06 -0800413 deb.delta(0) // end inner type (arrayType, etc.)
414 deb.delta(0) // end wireType
Rob Pike5b5a6742011-01-21 11:28:53 -0800415 // Remember we've seen this type.
416 deb.wireType[id] = wire
Rob Pikee7601e22009-12-29 14:03:33 +1100417}
418
Rob Pike5b5a6742011-01-21 11:28:53 -0800419
420// Value:
Rob Pike5b5a6742011-01-21 11:28:53 -0800421// SingletonValue | StructValue
Rob Pike04a89052011-01-28 10:53:06 -0800422func (deb *debugger) value(indent tab, id typeId) {
Rob Pike5b5a6742011-01-21 11:28:53 -0800423 wire, ok := deb.wireType[id]
Rob Pike30366042011-01-11 13:44:00 -0800424 if ok && wire.StructT != nil {
Rob Pike04a89052011-01-28 10:53:06 -0800425 deb.structValue(indent, id)
426 } else {
427 deb.singletonValue(indent, id)
Rob Pikee7601e22009-12-29 14:03:33 +1100428 }
Rob Pike96b9efe2010-10-29 15:07:56 -0700429}
430
Rob Pike5b5a6742011-01-21 11:28:53 -0800431// SingletonValue:
Rob Pike7f6ffad2011-01-21 16:10:39 -0800432// uint(0) FieldValue
Rob Pike04a89052011-01-28 10:53:06 -0800433func (deb *debugger) singletonValue(indent tab, id typeId) {
434 deb.dump("Singleton value")
Rob Pikee7601e22009-12-29 14:03:33 +1100435 // is it a builtin type?
Rob Pike5b5a6742011-01-21 11:28:53 -0800436 wire := deb.wireType[id]
Rob Pikee7601e22009-12-29 14:03:33 +1100437 _, ok := builtinIdToType[id]
Rob Pike96b9efe2010-10-29 15:07:56 -0700438 if !ok && wire == nil {
Rob Pike5b5a6742011-01-21 11:28:53 -0800439 errorf("type id %d not defined", id)
Rob Pike96b9efe2010-10-29 15:07:56 -0700440 }
Rob Pike04a89052011-01-28 10:53:06 -0800441 m := deb.uint64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800442 if m != 0 {
Rob Pike04a89052011-01-28 10:53:06 -0800443 errorf("expected zero; got %d", m)
Rob Pike5b5a6742011-01-21 11:28:53 -0800444 }
Rob Pike04a89052011-01-28 10:53:06 -0800445 deb.fieldValue(indent, id)
Rob Pike96b9efe2010-10-29 15:07:56 -0700446}
447
Rob Pike5b5a6742011-01-21 11:28:53 -0800448// InterfaceValue:
449// NilInterfaceValue | NonNilInterfaceValue
Rob Pike04a89052011-01-28 10:53:06 -0800450func (deb *debugger) interfaceValue(indent tab) {
451 deb.dump("Start of interface value")
452 if nameLen := deb.uint64(); nameLen == 0 {
453 deb.nilInterfaceValue(indent)
454 } else {
455 deb.nonNilInterfaceValue(indent, int(nameLen))
Rob Pike96b9efe2010-10-29 15:07:56 -0700456 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800457}
458
459// NilInterfaceValue:
460// uint(0) [already read]
461func (deb *debugger) nilInterfaceValue(indent tab) int {
462 fmt.Fprintf(os.Stderr, "%snil interface\n", indent)
463 return 0
464}
465
466
467// NonNilInterfaceValue:
468// ConcreteTypeName TypeSequence InterfaceContents
469// ConcreteTypeName:
470// uint(lengthOfName) [already read=n] name
471// InterfaceContents:
472// int(concreteTypeId) DelimitedValue
473// DelimitedValue:
474// uint(length) Value
Rob Pike04a89052011-01-28 10:53:06 -0800475func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) {
Rob Pike5b5a6742011-01-21 11:28:53 -0800476 // ConcreteTypeName
477 b := make([]byte, nameLen)
478 deb.r.Read(b) // TODO: CHECK THESE READS!!
Rob Pike04a89052011-01-28 10:53:06 -0800479 deb.consumed(nameLen)
Rob Pike5b5a6742011-01-21 11:28:53 -0800480 name := string(b)
Rob Pike5b5a6742011-01-21 11:28:53 -0800481
482 for {
Rob Pike04a89052011-01-28 10:53:06 -0800483 id := deb.typeId()
Rob Pike5b5a6742011-01-21 11:28:53 -0800484 if id < 0 {
Rob Pike04a89052011-01-28 10:53:06 -0800485 deb.typeDefinition(indent, -id)
486 n := deb.loadBlock(false)
487 deb.dump("Nested message of length %d", n)
Rob Pike5b5a6742011-01-21 11:28:53 -0800488 } else {
489 // DelimitedValue
Rob Pike04a89052011-01-28 10:53:06 -0800490 x := deb.uint64() // in case we want to ignore the value; we don't.
491 fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x)
492 deb.value(indent, id)
493 break
Rob Pike5b5a6742011-01-21 11:28:53 -0800494 }
495 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800496}
497
498// printCommonType prints a common type; used by printWireType.
499func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) {
500 indent.print()
501 fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id)
502}
503
504// printWireType prints the contents of a wireType.
505func (deb *debugger) printWireType(indent tab, wire *wireType) {
506 fmt.Fprintf(os.Stderr, "%stype definition {\n", indent)
507 indent++
508 switch {
509 case wire.ArrayT != nil:
510 deb.printCommonType(indent, "array", &wire.ArrayT.CommonType)
511 fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len)
512 fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem)
513 case wire.MapT != nil:
514 deb.printCommonType(indent, "map", &wire.MapT.CommonType)
515 fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key)
516 fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem)
517 case wire.SliceT != nil:
518 deb.printCommonType(indent, "slice", &wire.SliceT.CommonType)
519 fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem)
520 case wire.StructT != nil:
521 deb.printCommonType(indent, "struct", &wire.StructT.CommonType)
522 for i, field := range wire.StructT.Field {
523 fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
524 }
Rob Pikec91daef2011-03-04 12:25:18 -0800525 case wire.GobEncoderT != nil:
526 deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
Rob Pike5b5a6742011-01-21 11:28:53 -0800527 }
528 indent--
529 fmt.Fprintf(os.Stderr, "%s}\n", indent)
530}
531
532// fieldValue prints a value of any type, such as a struct field.
Rob Pike7f6ffad2011-01-21 16:10:39 -0800533// FieldValue:
534// builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue
Rob Pike04a89052011-01-28 10:53:06 -0800535func (deb *debugger) fieldValue(indent tab, id typeId) {
Rob Pike96b9efe2010-10-29 15:07:56 -0700536 _, ok := builtinIdToType[id]
Rob Pikee7601e22009-12-29 14:03:33 +1100537 if ok {
Rob Pike7f6ffad2011-01-21 16:10:39 -0800538 if id == tInterface {
Rob Pike04a89052011-01-28 10:53:06 -0800539 deb.interfaceValue(indent)
540 } else {
541 deb.printBuiltin(indent, id)
Rob Pike7f6ffad2011-01-21 16:10:39 -0800542 }
Rob Pike04a89052011-01-28 10:53:06 -0800543 return
Rob Pikee7601e22009-12-29 14:03:33 +1100544 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800545 wire, ok := deb.wireType[id]
Rob Pikee7601e22009-12-29 14:03:33 +1100546 if !ok {
Rob Pike5b5a6742011-01-21 11:28:53 -0800547 errorf("type id %d not defined", id)
Rob Pikee7601e22009-12-29 14:03:33 +1100548 }
549 switch {
Rob Pike30366042011-01-11 13:44:00 -0800550 case wire.ArrayT != nil:
Rob Pike04a89052011-01-28 10:53:06 -0800551 deb.arrayValue(indent, wire)
Rob Pike30366042011-01-11 13:44:00 -0800552 case wire.MapT != nil:
Rob Pike04a89052011-01-28 10:53:06 -0800553 deb.mapValue(indent, wire)
Rob Pike30366042011-01-11 13:44:00 -0800554 case wire.SliceT != nil:
Rob Pike04a89052011-01-28 10:53:06 -0800555 deb.sliceValue(indent, wire)
Rob Pike30366042011-01-11 13:44:00 -0800556 case wire.StructT != nil:
Rob Pike04a89052011-01-28 10:53:06 -0800557 deb.structValue(indent, id)
Rob Pikec91daef2011-03-04 12:25:18 -0800558 case wire.GobEncoderT != nil:
559 deb.gobEncoderValue(indent, id)
Rob Pike04a89052011-01-28 10:53:06 -0800560 default:
561 panic("bad wire type for field")
Rob Pikee7601e22009-12-29 14:03:33 +1100562 }
563}
564
Rob Pike5b5a6742011-01-21 11:28:53 -0800565// printBuiltin prints a value not of a fundamental type, that is,
566// one whose type is known to gobs at bootstrap time.
Rob Pike04a89052011-01-28 10:53:06 -0800567func (deb *debugger) printBuiltin(indent tab, id typeId) {
Rob Pikee7601e22009-12-29 14:03:33 +1100568 switch id {
569 case tBool:
Rob Pike04a89052011-01-28 10:53:06 -0800570 x := deb.int64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800571 if x == 0 {
572 fmt.Fprintf(os.Stderr, "%sfalse\n", indent)
Rob Pikee7601e22009-12-29 14:03:33 +1100573 } else {
Rob Pike5b5a6742011-01-21 11:28:53 -0800574 fmt.Fprintf(os.Stderr, "%strue\n", indent)
Rob Pikee7601e22009-12-29 14:03:33 +1100575 }
576 case tInt:
Rob Pike04a89052011-01-28 10:53:06 -0800577 x := deb.int64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800578 fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
Rob Pikee7601e22009-12-29 14:03:33 +1100579 case tUint:
Rob Pike04a89052011-01-28 10:53:06 -0800580 x := deb.int64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800581 fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
Rob Pikee7601e22009-12-29 14:03:33 +1100582 case tFloat:
Rob Pike04a89052011-01-28 10:53:06 -0800583 x := deb.uint64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800584 fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x))
Rob Pike04a89052011-01-28 10:53:06 -0800585 case tComplex:
586 r := deb.uint64()
587 i := deb.uint64()
588 fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i))
Rob Pikee7601e22009-12-29 14:03:33 +1100589 case tBytes:
Rob Pike04a89052011-01-28 10:53:06 -0800590 x := int(deb.uint64())
Rob Pike5b5a6742011-01-21 11:28:53 -0800591 b := make([]byte, x)
592 deb.r.Read(b)
Rob Pike04a89052011-01-28 10:53:06 -0800593 deb.consumed(x)
Rob Pike5b5a6742011-01-21 11:28:53 -0800594 fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b)
Rob Pikee7601e22009-12-29 14:03:33 +1100595 case tString:
Rob Pike04a89052011-01-28 10:53:06 -0800596 x := int(deb.uint64())
Rob Pike5b5a6742011-01-21 11:28:53 -0800597 b := make([]byte, x)
598 deb.r.Read(b)
Rob Pike04a89052011-01-28 10:53:06 -0800599 deb.consumed(x)
Rob Pike5b5a6742011-01-21 11:28:53 -0800600 fmt.Fprintf(os.Stderr, "%s%q\n", indent, b)
Rob Pikee7601e22009-12-29 14:03:33 +1100601 default:
Rob Pike04a89052011-01-28 10:53:06 -0800602 panic("unknown builtin")
Rob Pikee7601e22009-12-29 14:03:33 +1100603 }
Rob Pikee7601e22009-12-29 14:03:33 +1100604}
605
Rob Pike5b5a6742011-01-21 11:28:53 -0800606
607// ArrayValue:
Rob Pike7f6ffad2011-01-21 16:10:39 -0800608// uint(n) FieldValue*n
Rob Pike04a89052011-01-28 10:53:06 -0800609func (deb *debugger) arrayValue(indent tab, wire *wireType) {
Rob Pike5b5a6742011-01-21 11:28:53 -0800610 elemId := wire.ArrayT.Elem
Rob Pike04a89052011-01-28 10:53:06 -0800611 u := deb.uint64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800612 length := int(u)
613 for i := 0; i < length; i++ {
Rob Pike04a89052011-01-28 10:53:06 -0800614 deb.fieldValue(indent, elemId)
Rob Pike5b5a6742011-01-21 11:28:53 -0800615 }
616 if length != wire.ArrayT.Len {
617 fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len)
618 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800619}
620
621// MapValue:
Rob Pike7f6ffad2011-01-21 16:10:39 -0800622// uint(n) (FieldValue FieldValue)*n [n (key, value) pairs]
Rob Pike04a89052011-01-28 10:53:06 -0800623func (deb *debugger) mapValue(indent tab, wire *wireType) {
Rob Pike5b5a6742011-01-21 11:28:53 -0800624 keyId := wire.MapT.Key
625 elemId := wire.MapT.Elem
Rob Pike04a89052011-01-28 10:53:06 -0800626 u := deb.uint64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800627 length := int(u)
628 for i := 0; i < length; i++ {
Rob Pike04a89052011-01-28 10:53:06 -0800629 deb.fieldValue(indent+1, keyId)
630 deb.fieldValue(indent+1, elemId)
Rob Pike5b5a6742011-01-21 11:28:53 -0800631 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800632}
633
634// SliceValue:
Rob Pike7f6ffad2011-01-21 16:10:39 -0800635// uint(n) (n FieldValue)
Rob Pike04a89052011-01-28 10:53:06 -0800636func (deb *debugger) sliceValue(indent tab, wire *wireType) {
Rob Pike5b5a6742011-01-21 11:28:53 -0800637 elemId := wire.SliceT.Elem
Rob Pike04a89052011-01-28 10:53:06 -0800638 u := deb.uint64()
Rob Pike5b5a6742011-01-21 11:28:53 -0800639 length := int(u)
Rob Pike04a89052011-01-28 10:53:06 -0800640 deb.dump("Start of slice of length %d", length)
641
Rob Pike5b5a6742011-01-21 11:28:53 -0800642 for i := 0; i < length; i++ {
Rob Pike04a89052011-01-28 10:53:06 -0800643 deb.fieldValue(indent, elemId)
Rob Pike5b5a6742011-01-21 11:28:53 -0800644 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800645}
646
647// StructValue:
Rob Pike7f6ffad2011-01-21 16:10:39 -0800648// (uint(fieldDelta) FieldValue)*
Rob Pike04a89052011-01-28 10:53:06 -0800649func (deb *debugger) structValue(indent tab, id typeId) {
650 deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id)
Rob Pike5b5a6742011-01-21 11:28:53 -0800651 fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name())
652 wire, ok := deb.wireType[id]
653 if !ok {
654 errorf("type id %d not defined", id)
655 }
Rob Pike30366042011-01-11 13:44:00 -0800656 strct := wire.StructT
Rob Pike5b5a6742011-01-21 11:28:53 -0800657 fieldNum := -1
658 indent++
Rob Pike5b5a6742011-01-21 11:28:53 -0800659 for {
Rob Pike04a89052011-01-28 10:53:06 -0800660 delta := deb.uint64()
Rob Pike96b9efe2010-10-29 15:07:56 -0700661 if delta == 0 { // struct terminator is zero delta fieldnum
662 break
Rob Pikee7601e22009-12-29 14:03:33 +1100663 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800664 fieldNum += int(delta)
Rob Pike30366042011-01-11 13:44:00 -0800665 if fieldNum < 0 || fieldNum >= len(strct.Field) {
Rob Pike04a89052011-01-28 10:53:06 -0800666 deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta)
Rob Pike96b9efe2010-10-29 15:07:56 -0700667 break
Rob Pikee7601e22009-12-29 14:03:33 +1100668 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800669 fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name)
Rob Pike04a89052011-01-28 10:53:06 -0800670 deb.fieldValue(indent+1, strct.Field[fieldNum].Id)
Rob Pikee7601e22009-12-29 14:03:33 +1100671 }
Rob Pike5b5a6742011-01-21 11:28:53 -0800672 indent--
673 fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name())
Rob Pike04a89052011-01-28 10:53:06 -0800674 deb.dump(">> End of struct value of type %d %q", id, id.name())
Rob Pikee7601e22009-12-29 14:03:33 +1100675}
Rob Pikec91daef2011-03-04 12:25:18 -0800676
677// GobEncoderValue:
678// uint(n) byte*n
679func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
680 len := deb.uint64()
681 deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
682 fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
683 data := make([]byte, len)
684 _, err := deb.r.Read(data)
685 if err != nil {
686 errorf("gobEncoder data read: %s", err)
687 }
688 fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
689}