blob: 3b4bb103d07dd12f83653511f28ee7303e2a034c [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "type.h"
//static Lock debuglock;
static void vprintf(int8*, byte*);
void
runtime·dump(byte *p, int32 n)
{
int32 i;
for(i=0; i<n; i++) {
runtime·printpointer((byte*)(p[i]>>4));
runtime·printpointer((byte*)(p[i]&0xf));
if((i&15) == 15)
runtime·prints("\n");
else
runtime·prints(" ");
}
if(n & 15)
runtime·prints("\n");
}
void
runtime·prints(int8 *s)
{
runtime·write(2, s, runtime·findnull((byte*)s));
}
#pragma textflag 7
void
runtime·printf(int8 *s, ...)
{
byte *arg;
arg = (byte*)(&s+1);
vprintf(s, arg);
}
static byte*
vrnd(byte *p, int32 x)
{
if((uint32)(uintptr)p&(x-1))
p += x - ((uint32)(uintptr)p&(x-1));
return p;
}
// Very simple printf. Only for debugging prints.
// Do not add to this without checking with Rob.
static void
vprintf(int8 *s, byte *arg)
{
int8 *p, *lp;
byte *narg;
// lock(&debuglock);
lp = p = s;
for(; *p; p++) {
if(*p != '%')
continue;
if(p > lp)
runtime·write(2, lp, p-lp);
p++;
narg = nil;
switch(*p) {
case 't':
narg = arg + 1;
break;
case 'd': // 32-bit
case 'x':
arg = vrnd(arg, 4);
narg = arg + 4;
break;
case 'D': // 64-bit
case 'U':
case 'X':
case 'f':
arg = vrnd(arg, sizeof(uintptr));
narg = arg + 8;
break;
case 'C':
arg = vrnd(arg, sizeof(uintptr));
narg = arg + 16;
break;
case 'p': // pointer-sized
case 's':
arg = vrnd(arg, sizeof(uintptr));
narg = arg + sizeof(uintptr);
break;
case 'S': // pointer-aligned but bigger
arg = vrnd(arg, sizeof(uintptr));
narg = arg + sizeof(String);
break;
case 'a': // pointer-aligned but bigger
arg = vrnd(arg, sizeof(uintptr));
narg = arg + sizeof(Slice);
break;
case 'i': // pointer-aligned but bigger
case 'e':
arg = vrnd(arg, sizeof(uintptr));
narg = arg + sizeof(Eface);
break;
}
switch(*p) {
case 'a':
runtime·printslice(*(Slice*)arg);
break;
case 'd':
runtime·printint(*(int32*)arg);
break;
case 'D':
runtime·printint(*(int64*)arg);
break;
case 'e':
runtime·printeface(*(Eface*)arg);
break;
case 'f':
runtime·printfloat(*(float64*)arg);
break;
case 'C':
runtime·printcomplex(*(Complex128*)arg);
break;
case 'i':
runtime·printiface(*(Iface*)arg);
break;
case 'p':
runtime·printpointer(*(void**)arg);
break;
case 's':
runtime·prints(*(int8**)arg);
break;
case 'S':
runtime·printstring(*(String*)arg);
break;
case 't':
runtime·printbool(*(bool*)arg);
break;
case 'U':
runtime·printuint(*(uint64*)arg);
break;
case 'x':
runtime·printhex(*(uint32*)arg);
break;
case 'X':
runtime·printhex(*(uint64*)arg);
break;
}
arg = narg;
lp = p+1;
}
if(p > lp)
runtime·write(2, lp, p-lp);
// unlock(&debuglock);
}
#pragma textflag 7
void
runtime·goprintf(String s, ...)
{
// Can assume s has terminating NUL because only
// the Go compiler generates calls to runtime·goprintf, using
// string constants, and all the string constants have NULs.
vprintf((int8*)s.str, (byte*)(&s+1));
}
void
runtime·printpc(void *p)
{
runtime·prints("PC=");
runtime·printhex((uint64)runtime·getcallerpc(p));
}
void
runtime·printbool(bool v)
{
if(v) {
runtime·write(2, (byte*)"true", 4);
return;
}
runtime·write(2, (byte*)"false", 5);
}
void
runtime·printfloat(float64 v)
{
byte buf[20];
int32 e, s, i, n;
float64 h;
if(runtime·isNaN(v)) {
runtime·write(2, "NaN", 3);
return;
}
if(runtime·isInf(v, 1)) {
runtime·write(2, "+Inf", 4);
return;
}
if(runtime·isInf(v, -1)) {
runtime·write(2, "-Inf", 4);
return;
}
n = 7; // digits printed
e = 0; // exp
s = 0; // sign
if(v != 0) {
// sign
if(v < 0) {
v = -v;
s = 1;
}
// normalize
while(v >= 10) {
e++;
v /= 10;
}
while(v < 1) {
e--;
v *= 10;
}
// round
h = 5;
for(i=0; i<n; i++)
h /= 10;
v += h;
if(v >= 10) {
e++;
v /= 10;
}
}
// format +d.dddd+edd
buf[0] = '+';
if(s)
buf[0] = '-';
for(i=0; i<n; i++) {
s = v;
buf[i+2] = s+'0';
v -= s;
v *= 10.;
}
buf[1] = buf[2];
buf[2] = '.';
buf[n+2] = 'e';
buf[n+3] = '+';
if(e < 0) {
e = -e;
buf[n+3] = '-';
}
buf[n+4] = (e/100) + '0';
buf[n+5] = (e/10)%10 + '0';
buf[n+6] = (e%10) + '0';
runtime·write(2, buf, n+7);
}
void
runtime·printcomplex(Complex128 v)
{
runtime·write(2, "(", 1);
runtime·printfloat(v.real);
runtime·printfloat(v.imag);
runtime·write(2, "i)", 2);
}
void
runtime·printuint(uint64 v)
{
byte buf[100];
int32 i;
for(i=nelem(buf)-1; i>0; i--) {
buf[i] = v%10 + '0';
if(v < 10)
break;
v = v/10;
}
runtime·write(2, buf+i, nelem(buf)-i);
}
void
runtime·printint(int64 v)
{
if(v < 0) {
runtime·write(2, "-", 1);
v = -v;
}
runtime·printuint(v);
}
void
runtime·printhex(uint64 v)
{
static int8 *dig = "0123456789abcdef";
byte buf[100];
int32 i;
i=nelem(buf);
for(; v>0; v/=16)
buf[--i] = dig[v%16];
if(i == nelem(buf))
buf[--i] = '0';
buf[--i] = 'x';
buf[--i] = '0';
runtime·write(2, buf+i, nelem(buf)-i);
}
void
runtime·printpointer(void *p)
{
runtime·printhex((uint64)p);
}
void
runtime·printstring(String v)
{
extern int32 runtime·maxstring;
if(v.len > runtime·maxstring) {
runtime·write(2, "[invalid string]", 16);
return;
}
if(v.len > 0)
runtime·write(2, v.str, v.len);
}
void
runtime·printsp(void)
{
runtime·write(2, " ", 1);
}
void
runtime·printnl(void)
{
runtime·write(2, "\n", 1);
}
void
runtime·typestring(Eface e, String s)
{
s = *e.type->string;
FLUSH(&s);
}