// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package runtime import "unsafe" // The compiler knows that a print of a value of this type // should use printhex instead of printuint (decimal). type hex uint64 func bytes(s string) (ret []byte) { rp := (*slice)(unsafe.Pointer(&ret)) sp := (*_string)(noescape(unsafe.Pointer(&s))) rp.array = unsafe.Pointer(sp.str) rp.len = sp.len rp.cap = sp.len return } var debuglock mutex // The compiler emits calls to printlock and printunlock around // the multiple calls that implement a single Go print or println // statement. Some of the print helpers (printsp, for example) // call print recursively. There is also the problem of a crash // happening during the print routines and needing to acquire // the print lock to print information about the crash. // For both these reasons, let a thread acquire the printlock 'recursively'. func printlock() { mp := getg().m mp.locks++ // do not reschedule between printlock++ and lock(&debuglock). mp.printlock++ if mp.printlock == 1 { lock(&debuglock) } mp.locks-- // now we know debuglock is held and holding up mp.locks for us. } func printunlock() { mp := getg().m mp.printlock-- if mp.printlock == 0 { unlock(&debuglock) } } // write to goroutine-local buffer if diverting output, // or else standard error. func gwrite(b []byte) { if len(b) == 0 { return } gp := getg() if gp == nil || gp.writebuf == nil { writeErr(b) return } n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b) gp.writebuf = gp.writebuf[:len(gp.writebuf)+n] } func printsp() { print(" ") } func printnl() { print("\n") } func printpc(p unsafe.Pointer) { print("PC=", hex(uintptr(p))) } func printbool(v bool) { if v { print("true") } else { print("false") } } func printbyte(c byte) { gwrite((*[1]byte)(unsafe.Pointer(&c))[:]) } func printfloat(v float64) { switch { case v != v: print("NaN") return case v+v == v && v > 0: print("+Inf") return case v+v == v && v < 0: print("-Inf") return } const n = 7 // digits printed var buf [n + 7]byte buf[0] = '+' e := 0 // exp if v == 0 { if 1/v < 0 { buf[0] = '-' } } else { if v < 0 { v = -v buf[0] = '-' } // normalize for v >= 10 { e++ v /= 10 } for v < 1 { e-- v *= 10 } // round h := 5.0 for i := 0; i < n; i++ { h /= 10 } v += h if v >= 10 { e++ v /= 10 } } // format +d.dddd+edd for i := 0; i < n; i++ { s := int(v) buf[i+2] = byte(s + '0') v -= float64(s) v *= 10 } buf[1] = buf[2] buf[2] = '.' buf[n+2] = 'e' buf[n+3] = '+' if e < 0 { e = -e buf[n+3] = '-' } buf[n+4] = byte(e/100) + '0' buf[n+5] = byte(e/10)%10 + '0' buf[n+6] = byte(e%10) + '0' gwrite(buf[:]) } func printcomplex(c complex128) { print("(", real(c), imag(c), "i)") } func printuint(v uint64) { var buf [100]byte i := len(buf) for i--; i > 0; i-- { buf[i] = byte(v%10 + '0') if v < 10 { break } v /= 10 } gwrite(buf[i:]) } func printint(v int64) { if v < 0 { print("-") v = -v } printuint(uint64(v)) } func printhex(v uint64) { const dig = "0123456789abcdef" var buf [100]byte i := len(buf) for i--; i > 0; i-- { buf[i] = dig[v%16] if v < 16 { break } v /= 16 } i-- buf[i] = 'x' i-- buf[i] = '0' gwrite(buf[i:]) } func printpointer(p unsafe.Pointer) { printhex(uint64(uintptr(p))) } func printstring(s string) { if uintptr(len(s)) > maxstring { gwrite(bytes("[string too long]")) return } gwrite(bytes(s)) } func printslice(s []byte) { sp := (*slice)(unsafe.Pointer(&s)) print("[", len(s), "/", cap(s), "]") printpointer(unsafe.Pointer(sp.array)) } func printeface(e interface{}) { ep := (*eface)(unsafe.Pointer(&e)) print("(", ep._type, ",", ep.data, ")") } func printiface(i fInterface) { ip := (*iface)(unsafe.Pointer(&i)) print("(", ip.tab, ",", ip.data, ")") }