// 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" int32 panicking = 0; int32 maxround = sizeof(uintptr); int32 fd = 1; int32 gotraceback(void) { byte *p; p = getenv("GOTRACEBACK"); if(p == nil || p[0] == '\0') return 1; // default is on return atoi(p); } void panic(int32 unused) { fd = 2; if(panicking) { printf("double panic\n"); exit(3); } panicking++; printf("\npanic PC=%X\n", (uint64)(uintptr)&unused); if(gotraceback()){ traceback(·getcallerpc(&unused), getcallersp(&unused), 0, g); tracebackothers(g); } breakpoint(); // so we can grab it in a debugger exit(2); } void ·panicindex(void) { panicstring("index out of range"); } void ·panicslice(void) { panicstring("slice bounds out of range"); } void ·throwreturn(void) { // can only happen if compiler is broken throw("no return at end of a typed function - compiler is broken"); } void ·throwinit(void) { // can only happen with linker skew throw("recursive call during initialization - linker skew"); } void throw(int8 *s) { fd = 2; printf("throw: %s\n", s); panic(-1); *(int32*)0 = 0; // not reached exit(1); // even more not reached } void panicstring(int8 *s) { Eface err; ·newErrorString(gostringnocopy((byte*)s), &err); ·panic(err); } void mcpy(byte *t, byte *f, uint32 n) { while(n > 0) { *t = *f; t++; f++; n--; } } int32 mcmp(byte *s1, byte *s2, uint32 n) { uint32 i; byte c1, c2; for(i=0; i c2) return +1; } return 0; } byte* mchr(byte *p, byte c, byte *ep) { for(; p < ep; p++) if(*p == c) return p; return nil; } uint32 rnd(uint32 n, uint32 m) { uint32 r; if(m > maxround) m = maxround; r = n % m; if(r) n += m-r; return n; } static int32 argc; static uint8** argv; Slice os·Args; Slice os·Envs; void args(int32 c, uint8 **v) { argc = c; argv = v; } int32 isplan9; void goargs(void) { String *gargv; String *genvv; int32 i, envc; if(isplan9) envc=0; else for(envc=0; argv[argc+1+envc] != 0; envc++) ; gargv = malloc(argc*sizeof gargv[0]); genvv = malloc(envc*sizeof genvv[0]); for(i=0; i 0) { if(sizeof(hash) == 4) hash = (hash ^ *b) * 3267000013UL; else hash = (hash ^ *b) * 23344194077549503ULL; b++; s--; } return hash; } static uint32 memequal(uint32 s, void *a, void *b) { byte *ba, *bb, *aend; uint32 i; ba = a; bb = b; aend = ba+s; while(ba != aend) { if(*ba != *bb) return 0; ba++; bb++; } return 1; } static void memprint(uint32 s, void *a) { uint64 v; v = 0xbadb00b; switch(s) { case 1: v = *(uint8*)a; break; case 2: v = *(uint16*)a; break; case 4: v = *(uint32*)a; break; case 8: v = *(uint64*)a; break; } ·printint(v); } static void memcopy(uint32 s, void *a, void *b) { byte *ba, *bb; uint32 i; ba = a; bb = b; if(bb == nil) { for(i=0; ilen; if(alen != b->len) return false; return memequal(alen, a->str, b->str); } static void strprint(uint32 s, String *a) { USED(s); ·printstring(*a); } static uintptr interhash(uint32 s, Iface *a) { USED(s); return ifacehash(*a); } static void interprint(uint32 s, Iface *a) { USED(s); ·printiface(*a); } static uint32 interequal(uint32 s, Iface *a, Iface *b) { USED(s); return ifaceeq(*a, *b); } static uintptr nilinterhash(uint32 s, Eface *a) { USED(s); return efacehash(*a); } static void nilinterprint(uint32 s, Eface *a) { USED(s); ·printeface(*a); } static uint32 nilinterequal(uint32 s, Eface *a, Eface *b) { USED(s); return efaceeq(*a, *b); } uintptr nohash(uint32 s, void *a) { USED(s); USED(a); panicstring("hash of unhashable type"); return 0; } uint32 noequal(uint32 s, void *a, void *b) { USED(s); USED(a); USED(b); panicstring("comparing uncomparable types"); return 0; } Alg algarray[] = { [AMEM] { memhash, memequal, memprint, memcopy }, [ANOEQ] { nohash, noequal, memprint, memcopy }, [ASTRING] { strhash, strequal, strprint, memcopy }, [AINTER] { interhash, interequal, interprint, memcopy }, [ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy }, [AMEMWORD] { memhash, memwordequal, memprint, memwordcopy }, }; #pragma textflag 7 void FLUSH(void *v) { USED(v); } int64 nanotime(void) { int64 sec; int32 usec; sec = 0; usec = 0; gettime(&sec, &usec); return sec*1000000000 + (int64)usec*1000; } void ·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool) { Func *f; if(callers(1+skip, &retpc, 1) == 0 || (f = findfunc(retpc-1)) == nil) { retfile = emptystring; retline = 0; retbool = false; } else { retfile = f->src; retline = funcline(f, retpc-1); retbool = true; } FLUSH(&retfile); FLUSH(&retline); FLUSH(&retbool); } void ·Callers(int32 skip, Slice pc, int32 retn) { retn = callers(skip, (uintptr*)pc.array, pc.len); FLUSH(&retn); } void ·FuncForPC(uintptr pc, void *retf) { retf = findfunc(pc); FLUSH(&retf); }