Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package runtime
      6 
      7 import "unsafe"
      8 
      9 // The compiler knows that a print of a value of this type
     10 // should use printhex instead of printuint (decimal).
     11 type hex uint64
     12 
     13 func bytes(s string) (ret []byte) {
     14 	rp := (*slice)(unsafe.Pointer(&ret))
     15 	sp := (*_string)(noescape(unsafe.Pointer(&s)))
     16 	rp.array = unsafe.Pointer(sp.str)
     17 	rp.len = sp.len
     18 	rp.cap = sp.len
     19 	return
     20 }
     21 
     22 var debuglock mutex
     23 
     24 // The compiler emits calls to printlock and printunlock around
     25 // the multiple calls that implement a single Go print or println
     26 // statement. Some of the print helpers (printsp, for example)
     27 // call print recursively. There is also the problem of a crash
     28 // happening during the print routines and needing to acquire
     29 // the print lock to print information about the crash.
     30 // For both these reasons, let a thread acquire the printlock 'recursively'.
     31 
     32 func printlock() {
     33 	mp := getg().m
     34 	mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
     35 	mp.printlock++
     36 	if mp.printlock == 1 {
     37 		lock(&debuglock)
     38 	}
     39 	mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
     40 }
     41 
     42 func printunlock() {
     43 	mp := getg().m
     44 	mp.printlock--
     45 	if mp.printlock == 0 {
     46 		unlock(&debuglock)
     47 	}
     48 }
     49 
     50 // write to goroutine-local buffer if diverting output,
     51 // or else standard error.
     52 func gwrite(b []byte) {
     53 	if len(b) == 0 {
     54 		return
     55 	}
     56 	gp := getg()
     57 	if gp == nil || gp.writebuf == nil {
     58 		writeErr(b)
     59 		return
     60 	}
     61 
     62 	n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
     63 	gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
     64 }
     65 
     66 func printsp() {
     67 	print(" ")
     68 }
     69 
     70 func printnl() {
     71 	print("\n")
     72 }
     73 
     74 func printpc(p unsafe.Pointer) {
     75 	print("PC=", hex(uintptr(p)))
     76 }
     77 
     78 func printbool(v bool) {
     79 	if v {
     80 		print("true")
     81 	} else {
     82 		print("false")
     83 	}
     84 }
     85 
     86 func printbyte(c byte) {
     87 	gwrite((*[1]byte)(unsafe.Pointer(&c))[:])
     88 }
     89 
     90 func printfloat(v float64) {
     91 	switch {
     92 	case v != v:
     93 		print("NaN")
     94 		return
     95 	case v+v == v && v > 0:
     96 		print("+Inf")
     97 		return
     98 	case v+v == v && v < 0:
     99 		print("-Inf")
    100 		return
    101 	}
    102 
    103 	const n = 7 // digits printed
    104 	var buf [n + 7]byte
    105 	buf[0] = '+'
    106 	e := 0 // exp
    107 	if v == 0 {
    108 		if 1/v < 0 {
    109 			buf[0] = '-'
    110 		}
    111 	} else {
    112 		if v < 0 {
    113 			v = -v
    114 			buf[0] = '-'
    115 		}
    116 
    117 		// normalize
    118 		for v >= 10 {
    119 			e++
    120 			v /= 10
    121 		}
    122 		for v < 1 {
    123 			e--
    124 			v *= 10
    125 		}
    126 
    127 		// round
    128 		h := 5.0
    129 		for i := 0; i < n; i++ {
    130 			h /= 10
    131 		}
    132 		v += h
    133 		if v >= 10 {
    134 			e++
    135 			v /= 10
    136 		}
    137 	}
    138 
    139 	// format +d.dddd+edd
    140 	for i := 0; i < n; i++ {
    141 		s := int(v)
    142 		buf[i+2] = byte(s + '0')
    143 		v -= float64(s)
    144 		v *= 10
    145 	}
    146 	buf[1] = buf[2]
    147 	buf[2] = '.'
    148 
    149 	buf[n+2] = 'e'
    150 	buf[n+3] = '+'
    151 	if e < 0 {
    152 		e = -e
    153 		buf[n+3] = '-'
    154 	}
    155 
    156 	buf[n+4] = byte(e/100) + '0'
    157 	buf[n+5] = byte(e/10)%10 + '0'
    158 	buf[n+6] = byte(e%10) + '0'
    159 	gwrite(buf[:])
    160 }
    161 
    162 func printcomplex(c complex128) {
    163 	print("(", real(c), imag(c), "i)")
    164 }
    165 
    166 func printuint(v uint64) {
    167 	var buf [100]byte
    168 	i := len(buf)
    169 	for i--; i > 0; i-- {
    170 		buf[i] = byte(v%10 + '0')
    171 		if v < 10 {
    172 			break
    173 		}
    174 		v /= 10
    175 	}
    176 	gwrite(buf[i:])
    177 }
    178 
    179 func printint(v int64) {
    180 	if v < 0 {
    181 		print("-")
    182 		v = -v
    183 	}
    184 	printuint(uint64(v))
    185 }
    186 
    187 func printhex(v uint64) {
    188 	const dig = "0123456789abcdef"
    189 	var buf [100]byte
    190 	i := len(buf)
    191 	for i--; i > 0; i-- {
    192 		buf[i] = dig[v%16]
    193 		if v < 16 {
    194 			break
    195 		}
    196 		v /= 16
    197 	}
    198 	i--
    199 	buf[i] = 'x'
    200 	i--
    201 	buf[i] = '0'
    202 	gwrite(buf[i:])
    203 }
    204 
    205 func printpointer(p unsafe.Pointer) {
    206 	printhex(uint64(uintptr(p)))
    207 }
    208 
    209 func printstring(s string) {
    210 	if uintptr(len(s)) > maxstring {
    211 		gwrite(bytes("[string too long]"))
    212 		return
    213 	}
    214 	gwrite(bytes(s))
    215 }
    216 
    217 func printslice(s []byte) {
    218 	sp := (*slice)(unsafe.Pointer(&s))
    219 	print("[", len(s), "/", cap(s), "]")
    220 	printpointer(unsafe.Pointer(sp.array))
    221 }
    222 
    223 func printeface(e interface{}) {
    224 	ep := (*eface)(unsafe.Pointer(&e))
    225 	print("(", ep._type, ",", ep.data, ")")
    226 }
    227 
    228 func printiface(i fInterface) {
    229 	ip := (*iface)(unsafe.Pointer(&i))
    230 	print("(", ip.tab, ",", ip.data, ")")
    231 }
    232