...
Run Format

Source file src/runtime/print.go

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

View as plain text