2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / print.c
blob69b1f81fb421966b3cfdcc02bf8aaff733c2575e
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.
5 #include <complex.h>
6 #include <math.h>
7 #include <stdarg.h>
8 #include "runtime.h"
9 #include "array.h"
10 #include "go-type.h"
12 //static Lock debuglock;
14 // Clang requires this function to not be inlined (see below).
15 static void go_vprintf(const char*, va_list)
16 __attribute__((noinline));
18 // write to goroutine-local buffer if diverting output,
19 // or else standard error.
20 static void
21 gwrite(const void *v, intgo n)
23 G* g = runtime_g();
25 if(g == nil || g->writebuf == nil) {
26 // Avoid -D_FORTIFY_SOURCE problems.
27 int rv __attribute__((unused));
29 rv = runtime_write(2, v, n);
30 return;
33 if(g->writenbuf == 0)
34 return;
36 if(n > g->writenbuf)
37 n = g->writenbuf;
38 runtime_memmove(g->writebuf, v, n);
39 g->writebuf += n;
40 g->writenbuf -= n;
43 void
44 runtime_dump(byte *p, int32 n)
46 int32 i;
48 for(i=0; i<n; i++) {
49 runtime_printpointer((byte*)(uintptr)(p[i]>>4));
50 runtime_printpointer((byte*)(uintptr)(p[i]&0xf));
51 if((i&15) == 15)
52 runtime_prints("\n");
53 else
54 runtime_prints(" ");
56 if(n & 15)
57 runtime_prints("\n");
60 void
61 runtime_prints(const char *s)
63 gwrite(s, runtime_findnull((const byte*)s));
66 #if defined (__clang__) && (defined (__i386__) || defined (__x86_64__))
67 // LLVM's code generator does not currently support split stacks for vararg
68 // functions, so we disable the feature for this function under Clang. This
69 // appears to be OK as long as:
70 // - this function only calls non-inlined, internal-linkage (hence no dynamic
71 // loader) functions compiled with split stacks (i.e. go_vprintf), which can
72 // allocate more stack space as required;
73 // - this function itself does not occupy more than BACKOFF bytes of stack space
74 // (see libgcc/config/i386/morestack.S).
75 // These conditions are currently known to be satisfied by Clang on x86-32 and
76 // x86-64. Note that signal handlers receive slightly less stack space than they
77 // would normally do if they happen to be called while this function is being
78 // run. If this turns out to be a problem we could consider increasing BACKOFF.
80 void
81 runtime_printf(const char *s, ...)
82 __attribute__((no_split_stack));
84 int32
85 runtime_snprintf(byte *buf, int32 n, const char *s, ...)
86 __attribute__((no_split_stack));
88 #endif
90 void
91 runtime_printf(const char *s, ...)
93 va_list va;
95 va_start(va, s);
96 go_vprintf(s, va);
97 va_end(va);
100 int32
101 runtime_snprintf(byte *buf, int32 n, const char *s, ...)
103 G *g = runtime_g();
104 va_list va;
105 int32 m;
107 g->writebuf = buf;
108 g->writenbuf = n-1;
109 va_start(va, s);
110 go_vprintf(s, va);
111 va_end(va);
112 *g->writebuf = '\0';
113 m = g->writebuf - buf;
114 g->writenbuf = 0;
115 g->writebuf = nil;
116 return m;
119 // Very simple printf. Only for debugging prints.
120 // Do not add to this without checking with Rob.
121 static void
122 go_vprintf(const char *s, va_list va)
124 const char *p, *lp;
126 //runtime_lock(&debuglock);
128 lp = p = s;
129 for(; *p; p++) {
130 if(*p != '%')
131 continue;
132 if(p > lp)
133 gwrite(lp, p-lp);
134 p++;
135 switch(*p) {
136 case 'a':
137 runtime_printslice(va_arg(va, Slice));
138 break;
139 case 'c':
140 runtime_printbyte(va_arg(va, int32));
141 break;
142 case 'd':
143 runtime_printint(va_arg(va, int32));
144 break;
145 case 'D':
146 runtime_printint(va_arg(va, int64));
147 break;
148 case 'e':
149 runtime_printeface(va_arg(va, Eface));
150 break;
151 case 'f':
152 runtime_printfloat(va_arg(va, float64));
153 break;
154 case 'C':
155 runtime_printcomplex(va_arg(va, complex double));
156 break;
157 case 'i':
158 runtime_printiface(va_arg(va, Iface));
159 break;
160 case 'p':
161 runtime_printpointer(va_arg(va, void*));
162 break;
163 case 's':
164 runtime_prints(va_arg(va, char*));
165 break;
166 case 'S':
167 runtime_printstring(va_arg(va, String));
168 break;
169 case 't':
170 runtime_printbool(va_arg(va, int));
171 break;
172 case 'U':
173 runtime_printuint(va_arg(va, uint64));
174 break;
175 case 'x':
176 runtime_printhex(va_arg(va, uint32));
177 break;
178 case 'X':
179 runtime_printhex(va_arg(va, uint64));
180 break;
182 lp = p+1;
184 if(p > lp)
185 gwrite(lp, p-lp);
187 //runtime_unlock(&debuglock);
190 void
191 runtime_printpc(void *p __attribute__ ((unused)))
193 runtime_prints("PC=");
194 runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p));
197 void
198 runtime_printbool(_Bool v)
200 if(v) {
201 gwrite("true", 4);
202 return;
204 gwrite("false", 5);
207 void
208 runtime_printbyte(int8 c)
210 gwrite(&c, 1);
213 void
214 runtime_printfloat(double v)
216 byte buf[20];
217 int32 e, s, i, n;
218 float64 h;
220 if(ISNAN(v)) {
221 gwrite("NaN", 3);
222 return;
224 if(isinf(v)) {
225 if(signbit(v)) {
226 gwrite("-Inf", 4);
227 } else {
228 gwrite("+Inf", 4);
230 return;
233 n = 7; // digits printed
234 e = 0; // exp
235 s = 0; // sign
236 if(v == 0) {
237 if(isinf(1/v) && 1/v < 0)
238 s = 1;
239 } else {
240 // sign
241 if(v < 0) {
242 v = -v;
243 s = 1;
246 // normalize
247 while(v >= 10) {
248 e++;
249 v /= 10;
251 while(v < 1) {
252 e--;
253 v *= 10;
256 // round
257 h = 5;
258 for(i=0; i<n; i++)
259 h /= 10;
261 v += h;
262 if(v >= 10) {
263 e++;
264 v /= 10;
268 // format +d.dddd+edd
269 buf[0] = '+';
270 if(s)
271 buf[0] = '-';
272 for(i=0; i<n; i++) {
273 s = v;
274 buf[i+2] = s+'0';
275 v -= s;
276 v *= 10.;
278 buf[1] = buf[2];
279 buf[2] = '.';
281 buf[n+2] = 'e';
282 buf[n+3] = '+';
283 if(e < 0) {
284 e = -e;
285 buf[n+3] = '-';
288 buf[n+4] = (e/100) + '0';
289 buf[n+5] = (e/10)%10 + '0';
290 buf[n+6] = (e%10) + '0';
291 gwrite(buf, n+7);
294 void
295 runtime_printcomplex(complex double v)
297 gwrite("(", 1);
298 runtime_printfloat(creal(v));
299 runtime_printfloat(cimag(v));
300 gwrite("i)", 2);
303 void
304 runtime_printuint(uint64 v)
306 byte buf[100];
307 int32 i;
309 for(i=nelem(buf)-1; i>0; i--) {
310 buf[i] = v%10 + '0';
311 if(v < 10)
312 break;
313 v = v/10;
315 gwrite(buf+i, nelem(buf)-i);
318 void
319 runtime_printint(int64 v)
321 if(v < 0) {
322 gwrite("-", 1);
323 v = -v;
325 runtime_printuint(v);
328 void
329 runtime_printhex(uint64 v)
331 static const char *dig = "0123456789abcdef";
332 byte buf[100];
333 int32 i;
335 i=nelem(buf);
336 for(; v>0; v/=16)
337 buf[--i] = dig[v%16];
338 if(i == nelem(buf))
339 buf[--i] = '0';
340 buf[--i] = 'x';
341 buf[--i] = '0';
342 gwrite(buf+i, nelem(buf)-i);
345 void
346 runtime_printpointer(void *p)
348 runtime_printhex((uintptr)p);
351 void
352 runtime_printstring(String v)
354 // if(v.len > runtime_maxstring) {
355 // gwrite("[string too long]", 17);
356 // return;
357 // }
358 if(v.len > 0)
359 gwrite(v.str, v.len);
362 void
363 __go_print_space(void)
365 gwrite(" ", 1);
368 void
369 __go_print_nl(void)
371 gwrite("\n", 1);