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 #include <stdarg.h>
6 #include "runtime.h"
7 #include "array.h"
8 
9 //static Lock debuglock;
10 
11 static void go_vprintf(const char*, va_list);
12 
13 // write to goroutine-local buffer if diverting output,
14 // or else standard error.
15 static void
gwrite(const void * v,int32 n)16 gwrite(const void *v, int32 n)
17 {
18 	G* g = runtime_g();
19 
20 	if(g == nil || g->writebuf == nil) {
21 		// Avoid -D_FORTIFY_SOURCE problems.
22 		int rv __attribute__((unused));
23 
24 		rv = runtime_write(2, v, n);
25 		return;
26 	}
27 
28 	if(g->writenbuf == 0)
29 		return;
30 
31 	if(n > g->writenbuf)
32 		n = g->writenbuf;
33 	runtime_memmove(g->writebuf, v, n);
34 	g->writebuf += n;
35 	g->writenbuf -= n;
36 }
37 
38 void
runtime_dump(byte * p,int32 n)39 runtime_dump(byte *p, int32 n)
40 {
41 	int32 i;
42 
43 	for(i=0; i<n; i++) {
44 		runtime_printpointer((byte*)(uintptr)(p[i]>>4));
45 		runtime_printpointer((byte*)(uintptr)(p[i]&0xf));
46 		if((i&15) == 15)
47 			runtime_prints("\n");
48 		else
49 			runtime_prints(" ");
50 	}
51 	if(n & 15)
52 		runtime_prints("\n");
53 }
54 
55 void
runtime_prints(const char * s)56 runtime_prints(const char *s)
57 {
58 	gwrite(s, runtime_findnull((const byte*)s));
59 }
60 
61 void
runtime_printf(const char * s,...)62 runtime_printf(const char *s, ...)
63 {
64 	va_list va;
65 
66 	va_start(va, s);
67 	go_vprintf(s, va);
68 	va_end(va);
69 }
70 
71 // Very simple printf.  Only for debugging prints.
72 // Do not add to this without checking with Rob.
73 static void
go_vprintf(const char * s,va_list va)74 go_vprintf(const char *s, va_list va)
75 {
76 	const char *p, *lp;
77 
78 	//runtime_lock(&debuglock);
79 
80 	lp = p = s;
81 	for(; *p; p++) {
82 		if(*p != '%')
83 			continue;
84 		if(p > lp)
85 			gwrite(lp, p-lp);
86 		p++;
87 		switch(*p) {
88 		case 'a':
89 			runtime_printslice(va_arg(va, Slice));
90 			break;
91 		case 'c':
92 			runtime_printbyte(va_arg(va, int32));
93 			break;
94 		case 'd':
95 			runtime_printint(va_arg(va, int32));
96 			break;
97 		case 'D':
98 			runtime_printint(va_arg(va, int64));
99 			break;
100 		case 'e':
101 			runtime_printeface(va_arg(va, Eface));
102 			break;
103 		case 'f':
104 			runtime_printfloat(va_arg(va, float64));
105 			break;
106 		case 'C':
107 			runtime_printcomplex(va_arg(va, __complex double));
108 			break;
109 		case 'i':
110 			runtime_printiface(va_arg(va, Iface));
111 			break;
112 		case 'p':
113 			runtime_printpointer(va_arg(va, void*));
114 			break;
115 		case 's':
116 			runtime_prints(va_arg(va, char*));
117 			break;
118 		case 'S':
119 			runtime_printstring(va_arg(va, String));
120 			break;
121 		case 't':
122 			runtime_printbool(va_arg(va, int));
123 			break;
124 		case 'U':
125 			runtime_printuint(va_arg(va, uint64));
126 			break;
127 		case 'x':
128 			runtime_printhex(va_arg(va, uint32));
129 			break;
130 		case 'X':
131 			runtime_printhex(va_arg(va, uint64));
132 			break;
133 		}
134 		lp = p+1;
135 	}
136 	if(p > lp)
137 		gwrite(lp, p-lp);
138 
139 	//runtime_unlock(&debuglock);
140 }
141 
142 void
runtime_printpc(void * p)143 runtime_printpc(void *p __attribute__ ((unused)))
144 {
145 	runtime_prints("PC=");
146 	runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p));
147 }
148 
149 void
runtime_printbool(_Bool v)150 runtime_printbool(_Bool v)
151 {
152 	if(v) {
153 		gwrite("true", 4);
154 		return;
155 	}
156 	gwrite("false", 5);
157 }
158 
159 void
runtime_printbyte(int8 c)160 runtime_printbyte(int8 c)
161 {
162 	gwrite(&c, 1);
163 }
164 
165 void
runtime_printfloat(double v)166 runtime_printfloat(double v)
167 {
168 	byte buf[20];
169 	int32 e, s, i, n;
170 	float64 h;
171 
172 	if(ISNAN(v)) {
173 		gwrite("NaN", 3);
174 		return;
175 	}
176 	i = __builtin_isinf_sign(v);
177 	if(i > 0) {
178 		gwrite("+Inf", 4);
179 		return;
180 	}
181 	if(i < 0) {
182 		gwrite("-Inf", 4);
183 		return;
184 	}
185 
186 	n = 7;	// digits printed
187 	e = 0;	// exp
188 	s = 0;	// sign
189 	if(v != 0) {
190 		// sign
191 		if(v < 0) {
192 			v = -v;
193 			s = 1;
194 		}
195 
196 		// normalize
197 		while(v >= 10) {
198 			e++;
199 			v /= 10;
200 		}
201 		while(v < 1) {
202 			e--;
203 			v *= 10;
204 		}
205 
206 		// round
207 		h = 5;
208 		for(i=0; i<n; i++)
209 			h /= 10;
210 
211 		v += h;
212 		if(v >= 10) {
213 			e++;
214 			v /= 10;
215 		}
216 	}
217 
218 	// format +d.dddd+edd
219 	buf[0] = '+';
220 	if(s)
221 		buf[0] = '-';
222 	for(i=0; i<n; i++) {
223 		s = v;
224 		buf[i+2] = s+'0';
225 		v -= s;
226 		v *= 10.;
227 	}
228 	buf[1] = buf[2];
229 	buf[2] = '.';
230 
231 	buf[n+2] = 'e';
232 	buf[n+3] = '+';
233 	if(e < 0) {
234 		e = -e;
235 		buf[n+3] = '-';
236 	}
237 
238 	buf[n+4] = (e/100) + '0';
239 	buf[n+5] = (e/10)%10 + '0';
240 	buf[n+6] = (e%10) + '0';
241 	gwrite(buf, n+7);
242 }
243 
244 void
runtime_printcomplex(__complex double v)245 runtime_printcomplex(__complex double v)
246 {
247 	gwrite("(", 1);
248 	runtime_printfloat(__builtin_creal(v));
249 	runtime_printfloat(__builtin_cimag(v));
250 	gwrite("i)", 2);
251 }
252 
253 void
runtime_printuint(uint64 v)254 runtime_printuint(uint64 v)
255 {
256 	byte buf[100];
257 	int32 i;
258 
259 	for(i=nelem(buf)-1; i>0; i--) {
260 		buf[i] = v%10 + '0';
261 		if(v < 10)
262 			break;
263 		v = v/10;
264 	}
265 	gwrite(buf+i, nelem(buf)-i);
266 }
267 
268 void
runtime_printint(int64 v)269 runtime_printint(int64 v)
270 {
271 	if(v < 0) {
272 		gwrite("-", 1);
273 		v = -v;
274 	}
275 	runtime_printuint(v);
276 }
277 
278 void
runtime_printhex(uint64 v)279 runtime_printhex(uint64 v)
280 {
281 	static const char *dig = "0123456789abcdef";
282 	byte buf[100];
283 	int32 i;
284 
285 	i=nelem(buf);
286 	for(; v>0; v/=16)
287 		buf[--i] = dig[v%16];
288 	if(i == nelem(buf))
289 		buf[--i] = '0';
290 	buf[--i] = 'x';
291 	buf[--i] = '0';
292 	gwrite(buf+i, nelem(buf)-i);
293 }
294 
295 void
runtime_printpointer(void * p)296 runtime_printpointer(void *p)
297 {
298 	runtime_printhex((uint64)(uintptr)p);
299 }
300 
301 void
runtime_printstring(String v)302 runtime_printstring(String v)
303 {
304 	// extern uint32 runtime_maxstring;
305 
306 	// if(v.len > runtime_maxstring) {
307 	//	gwrite("[string too long]", 17);
308 	//	return;
309 	// }
310 	if(v.len > 0)
311 		gwrite(v.str, v.len);
312 }
313 
314 void
__go_print_space(void)315 __go_print_space(void)
316 {
317 	gwrite(" ", 1);
318 }
319 
320 void
__go_print_nl(void)321 __go_print_nl(void)
322 {
323 	gwrite("\n", 1);
324 }
325