github.com/euank/go@v0.0.0-20160829210321-495514729181/src/runtime/print.go (about)

     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 := stringStructOf(&s)
    16  	rp.array = 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 printbool(v bool) {
    75  	if v {
    76  		print("true")
    77  	} else {
    78  		print("false")
    79  	}
    80  }
    81  
    82  func printfloat(v float64) {
    83  	switch {
    84  	case v != v:
    85  		print("NaN")
    86  		return
    87  	case v+v == v && v > 0:
    88  		print("+Inf")
    89  		return
    90  	case v+v == v && v < 0:
    91  		print("-Inf")
    92  		return
    93  	}
    94  
    95  	const n = 7 // digits printed
    96  	var buf [n + 7]byte
    97  	buf[0] = '+'
    98  	e := 0 // exp
    99  	if v == 0 {
   100  		if 1/v < 0 {
   101  			buf[0] = '-'
   102  		}
   103  	} else {
   104  		if v < 0 {
   105  			v = -v
   106  			buf[0] = '-'
   107  		}
   108  
   109  		// normalize
   110  		for v >= 10 {
   111  			e++
   112  			v /= 10
   113  		}
   114  		for v < 1 {
   115  			e--
   116  			v *= 10
   117  		}
   118  
   119  		// round
   120  		h := 5.0
   121  		for i := 0; i < n; i++ {
   122  			h /= 10
   123  		}
   124  		v += h
   125  		if v >= 10 {
   126  			e++
   127  			v /= 10
   128  		}
   129  	}
   130  
   131  	// format +d.dddd+edd
   132  	for i := 0; i < n; i++ {
   133  		s := int(v)
   134  		buf[i+2] = byte(s + '0')
   135  		v -= float64(s)
   136  		v *= 10
   137  	}
   138  	buf[1] = buf[2]
   139  	buf[2] = '.'
   140  
   141  	buf[n+2] = 'e'
   142  	buf[n+3] = '+'
   143  	if e < 0 {
   144  		e = -e
   145  		buf[n+3] = '-'
   146  	}
   147  
   148  	buf[n+4] = byte(e/100) + '0'
   149  	buf[n+5] = byte(e/10)%10 + '0'
   150  	buf[n+6] = byte(e%10) + '0'
   151  	gwrite(buf[:])
   152  }
   153  
   154  func printcomplex(c complex128) {
   155  	print("(", real(c), imag(c), "i)")
   156  }
   157  
   158  func printuint(v uint64) {
   159  	var buf [100]byte
   160  	i := len(buf)
   161  	for i--; i > 0; i-- {
   162  		buf[i] = byte(v%10 + '0')
   163  		if v < 10 {
   164  			break
   165  		}
   166  		v /= 10
   167  	}
   168  	gwrite(buf[i:])
   169  }
   170  
   171  func printint(v int64) {
   172  	if v < 0 {
   173  		print("-")
   174  		v = -v
   175  	}
   176  	printuint(uint64(v))
   177  }
   178  
   179  func printhex(v uint64) {
   180  	const dig = "0123456789abcdef"
   181  	var buf [100]byte
   182  	i := len(buf)
   183  	for i--; i > 0; i-- {
   184  		buf[i] = dig[v%16]
   185  		if v < 16 {
   186  			break
   187  		}
   188  		v /= 16
   189  	}
   190  	i--
   191  	buf[i] = 'x'
   192  	i--
   193  	buf[i] = '0'
   194  	gwrite(buf[i:])
   195  }
   196  
   197  func printpointer(p unsafe.Pointer) {
   198  	printhex(uint64(uintptr(p)))
   199  }
   200  
   201  func printstring(s string) {
   202  	if uintptr(len(s)) > maxstring {
   203  		gwrite(bytes("[string too long]"))
   204  		return
   205  	}
   206  	gwrite(bytes(s))
   207  }
   208  
   209  func printslice(s []byte) {
   210  	sp := (*slice)(unsafe.Pointer(&s))
   211  	print("[", len(s), "/", cap(s), "]")
   212  	printpointer(sp.array)
   213  }
   214  
   215  func printeface(e eface) {
   216  	print("(", e._type, ",", e.data, ")")
   217  }
   218  
   219  func printiface(i iface) {
   220  	print("(", i.tab, ",", i.data, ")")
   221  }