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