modernc.org/crt/v2@v2.0.1-alpha.3/crt.go (about) 1 // Copyright 2019 The CRT 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 //go:generate gofmt -l -s -w . 6 //go:generate go run generate.go 7 //go:generate gofmt -l -s -w . 8 9 package crt // import "modernc.org/crt/v2" 10 11 import ( 12 "fmt" 13 "math" 14 "os" 15 "sort" 16 "sync" 17 "sync/atomic" 18 "syscall" 19 "time" 20 "unsafe" 21 22 "github.com/mattn/go-isatty" 23 "modernc.org/crt/v2/libc/stdio" 24 "modernc.org/memory" 25 ) 26 27 const ( 28 stackHeaderSize = unsafe.Sizeof(stackHeader{}) 29 stackSegmentSize = 1 << 10 30 uintptrSize = unsafe.Sizeof(uintptr(0)) 31 ) 32 33 var ( 34 _ = ""[:stackHeaderSize%16] 35 _ = ""[:stackSegmentSize%16] 36 37 allocMu sync.Mutex 38 allocator memory.Allocator 39 40 stderr = int32(2) 41 stdin = int32(1) 42 stdout = int32(0) 43 ) 44 45 // Keep these outside of the var block otherwise go generate will miss them. 46 var Xstderr = &stderr 47 var Xstdin = &stdin 48 var Xstdout = &stdout 49 50 func Start(main func(*TLS, int32, Intptr) int32) { 51 argv := mustCalloc((len(os.Args) + 1) * int(uintptrSize)) 52 p := argv 53 for _, v := range os.Args { 54 s := mustCalloc(len(v) + 1) 55 copy((*(*[1 << 20]byte)(unsafe.Pointer(s)))[:], v) 56 *(*uintptr)(unsafe.Pointer(p)) = s 57 p += uintptrSize 58 } 59 t := NewTLS() 60 Xexit(t, main(t, int32(len(os.Args)), Intptr(argv))) 61 } 62 63 func Bool32(b bool) int32 { 64 if b { 65 return 1 66 } 67 return 0 68 } 69 70 func Bool64(b bool) int64 { 71 if b { 72 return 1 73 } 74 return 0 75 } 76 77 func malloc(n int) uintptr { 78 allocMu.Lock() 79 p, err := allocator.UintptrMalloc(n) 80 allocMu.Unlock() 81 // if dmesgs { 82 // dmesg("malloc(%d): (%#x, %v)", n, p, err) 83 // } 84 if err != nil { 85 if dmesgs { 86 dmesg("malloc(): ", err) 87 } 88 return 0 89 } 90 91 return p 92 } 93 94 func mustMalloc(n int) uintptr { 95 if p := malloc(n); p != 0 { 96 return p 97 } 98 99 panic("OOM") 100 } 101 102 func realloc(p uintptr, n int) uintptr { 103 allocMu.Lock() 104 q, err := allocator.UintptrRealloc(p, n) 105 allocMu.Unlock() 106 // if dmesgs { 107 // dmesg("realloc(%#x, %d): (%#x, %v)", p, n, q, err) 108 // } 109 if err != nil { 110 if dmesgs { 111 dmesg("realloc(): ", err) 112 } 113 return 0 114 } 115 116 return q 117 } 118 119 func calloc(n int) uintptr { 120 allocMu.Lock() 121 p, err := allocator.UintptrCalloc(n) 122 allocMu.Unlock() 123 // if dmesgs { 124 // dmesg("calloc(%d): (%#x, %v)", n, p, err) 125 // } 126 if err != nil { 127 if dmesgs { 128 dmesg("calloc(): ", err) 129 } 130 return 0 131 } 132 133 return p 134 } 135 136 func mustCalloc(n int) uintptr { 137 if p := calloc(n); p != 0 { 138 return p 139 } 140 141 panic("OOM") 142 } 143 144 func free(p uintptr) { 145 // if dmesgs { 146 // dmesg("free(%#x)", p) 147 // } 148 allocMu.Lock() 149 err := allocator.UintptrFree(p) 150 allocMu.Unlock() 151 if err != nil { 152 if dmesgs { 153 dmesg("free(): ", err) 154 } 155 panic(err.Error()) 156 } 157 } 158 159 func roundup(n, to uintptr) uintptr { 160 if r := n % to; r != 0 { 161 return n + to - r 162 } 163 164 return n 165 } 166 167 type stackHeader struct { 168 free int // bytes left in page 169 page uintptr // stack page 170 prev uintptr // prev stack page = prev stack header 171 sp uintptr // next allocation address 172 } 173 174 type TLS struct { 175 ID int32 176 errnop uintptr 177 stack stackHeader 178 } 179 180 var tid int32 181 182 func NewTLS() *TLS { 183 id := atomic.AddInt32(&tid, 1) 184 return &TLS{errnop: mustCalloc(4), ID: id} 185 } 186 187 func (t *TLS) Close() { 188 Xfree(t, Intptr(t.errnop)) 189 } 190 191 func CloseTLS(t *TLS) { 192 t.Close() 193 *t = TLS{} 194 } 195 196 //TODO- var ( 197 //TODO- balance int 198 //TODO- rqBalanace int 199 //TODO- pageBalance int 200 //TODO- prefix string 201 //TODO- ) 202 //TODO- 203 //TODO- func (t *TLS) dump(op string, n int, r uintptr) { 204 //TODO- fmt.Printf( 205 //TODO- "%spost %s(%4d): r %#016x, free %6d, page %#016x, prev %#016x, sp %#016x, bal %3d, rqBalanace %5d, pageBal %3d\n", 206 //TODO- prefix, op, n, r, t.stack.free, t.stack.page, t.stack.prev, t.stack.sp, balance, rqBalanace, pageBalance, 207 //TODO- ) 208 //TODO- } 209 210 func (t *TLS) Alloc(n int) (r uintptr) { 211 //TODO- defer func() { 212 //TODO- t.dump("alloc", n, r) 213 //TODO- }() 214 //TODO- balance++ 215 //TODO- rqBalanace += n 216 if t.stack.free >= n { 217 r = t.stack.sp 218 t.stack.free -= n 219 t.stack.sp += uintptr(n) 220 return r 221 } 222 223 if t.stack.page != 0 { 224 *(*stackHeader)(unsafe.Pointer(t.stack.page)) = t.stack 225 } 226 rq := n + int(stackHeaderSize) 227 if rq < stackSegmentSize { 228 rq = stackSegmentSize 229 } 230 t.stack.free = rq - int(stackHeaderSize) 231 t.stack.prev = t.stack.page 232 t.stack.page = mustMalloc(rq) 233 //TODO- fmt.Printf("---- malloc(%d): %#016x\n", rq, t.stack.page) 234 //TODO- prefix += "· " 235 //TODO- pageBalance++ 236 t.stack.sp = t.stack.page + stackHeaderSize 237 238 r = t.stack.sp 239 t.stack.free -= n 240 t.stack.sp += uintptr(n) 241 return r 242 } 243 244 func (t *TLS) Free(n int) { 245 //TODO hysteresis 246 //TODO- defer t.dump(" free", n, 0) 247 //TODO- balance-- 248 //TODO- rqBalanace -= n 249 t.stack.free += n 250 t.stack.sp -= uintptr(n) 251 if t.stack.sp != t.stack.page+stackHeaderSize { 252 return 253 } 254 255 //TODO- prefix = prefix[:len(prefix)-len("· ")] 256 //TODO- fmt.Printf("---- free(%#x)\n", t.stack.page) 257 //TODO- pageBalance-- 258 free(t.stack.page) 259 if t.stack.prev != 0 { 260 t.stack = *(*stackHeader)(unsafe.Pointer(t.stack.prev)) 261 return 262 } 263 264 t.stack = stackHeader{} 265 } 266 267 func (t *TLS) setErrno(err interface{}) { 268 // if dmesgs { 269 // dmesg("errno <- %v", err) 270 // } 271 switch x := err.(type) { 272 case int: 273 // if dmesgs { 274 // dmesg("errno <- %v", x) 275 // } 276 *(*int32)(unsafe.Pointer(t.errnop)) = int32(x) 277 case *os.PathError: 278 t.setErrno(x.Err) 279 case syscall.Errno: 280 // if dmesgs { 281 // dmesg("errno <- %v", int32(x)) 282 // } 283 *(*int32)(unsafe.Pointer(t.errnop)) = int32(x) 284 default: 285 panic("TODO") 286 } 287 } 288 289 func (t *TLS) DynAlloc(a *[]uintptr, n uintptr) uintptr { 290 // if dmesgs { 291 // dmesg("DynAlloc(%#x, %#x)", a, n) 292 // } 293 n += 15 294 n &^= 15 295 p := malloc(int(n)) 296 *a = append(*a, p) 297 // if dmesgs { 298 // dmesg("DynAlloc(%#x, %#x): %#x", a, n, p) 299 // } 300 return p 301 } 302 303 func (t *TLS) FreeList(a []uintptr) { 304 // if dmesgs { 305 // dmesg("FreeList(%#x)", a) 306 // } 307 for _, p := range a { 308 free(p) 309 } 310 } 311 312 func GoString(s Intptr) string { 313 if s == 0 { 314 return "" 315 } 316 317 var buf []byte 318 for { 319 b := *(*byte)(unsafe.Pointer(uintptr(s))) 320 if b == 0 { 321 return string(buf) 322 } 323 324 buf = append(buf, b) 325 s++ 326 } 327 } 328 329 // int printf(const char *format, ...); 330 func Xprintf(t *TLS, s Intptr, args uintptr) int32 { 331 // if dmesgs { 332 // dmesg("Xprintf(%q, %#x)", GoString(s), args) 333 // } 334 b := printf(s, args) 335 os.Stdout.Write(b) 336 return int32(len(b)) 337 } 338 339 // int printf(const char *format, ...); 340 func printf(s Intptr, args uintptr) (r []byte) { 341 // if dmesgs { 342 // dmesg("printf(%q)", GoString(s0)) 343 // } 344 var b []byte 345 for { 346 c := *(*byte)(unsafe.Pointer(uintptr(s))) 347 s++ 348 if c == 0 { 349 // if dmesgs { 350 // dmesg("printf(): %d, %q", len(b), b) 351 // } 352 return b 353 } 354 355 var spec []byte 356 switch c { 357 case '%': 358 more: 359 c := *(*byte)(unsafe.Pointer(uintptr(s))) 360 s++ 361 switch { 362 case c >= '0' && c <= '9' || c == '.': 363 spec = append(spec, c) 364 goto more 365 case c == '*': 366 var w int32 367 args, w = int32Arg(args) 368 spec = append(spec, []byte(fmt.Sprint(w))...) 369 goto more 370 } 371 spec := string(spec) 372 switch c { 373 case 'c': 374 var c int32 375 args, c = int32Arg(args) 376 b = append(b, fmt.Sprintf("%"+spec+"c", c)...) 377 case 'i', 'd': 378 var n int32 379 args, n = int32Arg(args) 380 b = append(b, fmt.Sprintf("%"+spec+"d", n)...) 381 case 'u': 382 var n uint32 383 args, n = uint32Arg(args) 384 b = append(b, fmt.Sprintf("%"+spec+"d", n)...) 385 case 'x': 386 var n uint32 387 args, n = uint32Arg(args) 388 b = append(b, fmt.Sprintf("%"+spec+"x", n)...) 389 case 'X': 390 var n uint32 391 args, n = uint32Arg(args) 392 b = append(b, fmt.Sprintf("%"+spec+"X", n)...) 393 case 'l': 394 switch c := *(*byte)(unsafe.Pointer(uintptr(s))); c { 395 case 'd', 'i': 396 s++ 397 var n long 398 args, n = longArg(args) 399 b = append(b, fmt.Sprintf("%"+spec+"d", n)...) 400 case 'l': 401 s++ 402 switch *(*byte)(unsafe.Pointer(uintptr(s))) { 403 case 'd': 404 var n int64 405 s++ 406 args, n = int64Arg(args) 407 b = append(b, fmt.Sprintf("%"+spec+"d", n)...) 408 default: 409 panic("internal error") 410 } 411 case 'u': 412 s++ 413 var n long 414 args, n = longArg(args) 415 b = append(b, fmt.Sprintf("%"+spec+"d", uint64(n))...) 416 case 'x': 417 s++ 418 var n long 419 args, n = longArg(args) 420 b = append(b, fmt.Sprintf("%"+spec+"x", n)...) 421 default: 422 panic(fmt.Errorf("internal error %q", string(c))) 423 } 424 case 'f': 425 var f float64 426 args, f = float64Arg(args) 427 switch { 428 case spec == "": 429 spec = ".6" 430 } 431 b = append(b, fmt.Sprintf("%"+spec+"f", f)...) 432 case 'e': 433 var f float64 434 args, f = float64Arg(args) 435 switch { 436 case spec == "": 437 spec = ".6" 438 } 439 b = append(b, fmt.Sprintf("%"+spec+"e", f)...) 440 case 'E': 441 var f float64 442 args, f = float64Arg(args) 443 switch { 444 case spec == "": 445 spec = ".6" 446 } 447 b = append(b, fmt.Sprintf("%"+spec+"E", f)...) 448 case 'g': 449 var f float64 450 args, f = float64Arg(args) 451 switch { 452 case spec == "": 453 spec = ".6" 454 case spec == "0": 455 spec = ".1" 456 } 457 b = append(b, fmt.Sprintf("%"+spec+"g", f)...) 458 case 's': 459 var ps Intptr 460 args, ps = ptrArg(args) 461 var b2 []byte 462 for { 463 c := *(*byte)(unsafe.Pointer(uintptr(ps))) 464 if c == 0 { 465 break 466 } 467 468 b2 = append(b2, c) 469 ps++ 470 } 471 b = append(b, fmt.Sprintf("%"+spec+"s", b2)...) 472 default: 473 panic(fmt.Sprintf("%q", string(c))) 474 } 475 default: 476 b = append(b, c) 477 } 478 } 479 } 480 481 func float64Arg(ap uintptr) (uintptr, float64) { 482 ap = roundup(ap, 8) 483 v := *(*float64)(unsafe.Pointer(ap)) 484 ap += 8 485 return ap, v 486 } 487 488 func longArg(ap uintptr) (uintptr, long) { 489 ap = roundup(ap, 8) 490 v := *(*long)(unsafe.Pointer(ap)) 491 ap += 8 492 return ap, v 493 } 494 495 func int64Arg(ap uintptr) (uintptr, int64) { 496 ap = roundup(ap, 8) 497 v := *(*int64)(unsafe.Pointer(ap)) 498 ap += 8 499 return ap, v 500 } 501 502 func ptrArg(ap uintptr) (uintptr, Intptr) { 503 ap = roundup(ap, 8) 504 v := *(*Intptr)(unsafe.Pointer(ap)) 505 ap += 8 506 return ap, v 507 } 508 509 func uint32Arg(ap uintptr) (uintptr, uint32) { 510 ap = roundup(ap, 8) 511 v := *(*uint32)(unsafe.Pointer(ap)) 512 ap += 8 513 return ap, v 514 } 515 516 func int32Arg(ap uintptr) (uintptr, int32) { 517 ap = roundup(ap, 8) 518 v := *(*int32)(unsafe.Pointer(ap)) 519 ap += 8 520 return ap, v 521 } 522 523 // void *memset(void *s, int c, size_t n) 524 func Xmemset(t *TLS, s Intptr, c int32, n Intptr) Intptr { 525 // if dmesgs { 526 // dmesg("memset(%#x, %#x, %#x)", s, c, n) 527 // } 528 if n != 0 { 529 b := (*RawMem)(unsafe.Pointer(uintptr(s)))[:n] 530 for i := range b { 531 b[i] = byte(c) 532 } 533 } 534 return s 535 } 536 537 // int putchar(int c); 538 func Xputchar(t *TLS, c int32) int32 { 539 // if dmesgs { 540 // dmesg("putchar(%#x)", c) 541 // } 542 _, err := os.Stdout.Write([]byte{byte(c)}) 543 if err != nil { 544 if dmesgs { 545 dmesg("putchar(%#x): %v", c, err) 546 } 547 return eof 548 } 549 550 return int32(byte(c)) 551 } 552 553 // void *memcpy(void *dest, const void *src, size_t n); 554 func Xmemcpy(t *TLS, dest, src, n Intptr) (r Intptr) { 555 // if dmesgs { 556 // dmesg("memcpy(%#x, %#x, %#x)", dest, src, n) 557 // } 558 r = dest 559 for ; n != 0; n-- { 560 *(*byte)(unsafe.Pointer(uintptr(dest))) = *(*byte)(unsafe.Pointer(uintptr(src))) 561 src++ 562 dest++ 563 } 564 return r 565 } 566 567 // int puts(const char *s); 568 func Xputs(t *TLS, s Intptr) int32 { 569 // if dmesgs { 570 // dmesg("puts(%q)", GoString(s)) 571 // } 572 var err error 573 for { 574 c := *(*byte)(unsafe.Pointer(uintptr(s))) 575 s++ 576 if c == 0 { 577 _, err = os.Stdout.Write([]byte{'\n'}) 578 break 579 } 580 581 if _, err = os.Stdout.Write([]byte{c}); err != nil { 582 break 583 } 584 } 585 if err != nil { 586 if dmesgs { 587 dmesg("puts(): %v", err) 588 } 589 return 1 590 } 591 592 return eof 593 } 594 595 // void *calloc(size_t nmemb, size_t size); 596 func Xcalloc(t *TLS, n, size Intptr) Intptr { 597 r := calloc(int(uint(n) * uint(size))) 598 // if dmesgs { 599 // dmesg("calloc(%#x, %#x): %#x", n, size, r) 600 // } 601 return Intptr(r) 602 } 603 604 func VaInt32(app Intptr) int32 { 605 ap := *(*uintptr)(unsafe.Pointer(uintptr(app))) 606 ap = roundup(ap, 8) 607 v := *(*int32)(unsafe.Pointer(ap)) 608 ap += 8 609 *(*uintptr)(unsafe.Pointer(uintptr(app))) = ap 610 return v 611 } 612 613 func VaInt64(app Intptr) int64 { 614 ap := *(*uintptr)(unsafe.Pointer(uintptr(app))) 615 ap = roundup(ap, 8) 616 v := *(*int64)(unsafe.Pointer(ap)) 617 ap += 8 618 *(*uintptr)(unsafe.Pointer(uintptr(app))) = ap 619 return v 620 } 621 622 func VaFloat64(app Intptr) float64 { 623 ap := *(*uintptr)(unsafe.Pointer(uintptr(app))) 624 ap = roundup(ap, 8) 625 v := *(*float64)(unsafe.Pointer(ap)) 626 ap += 8 627 *(*uintptr)(unsafe.Pointer(uintptr(app))) = ap 628 return v 629 } 630 631 // int vprintf(const char *format, va_list ap); 632 func Xvprintf(t *TLS, s, ap Intptr) int32 { 633 // if dmesgs { 634 // dmesg("vprintf(%q, %#x)", GoString(s), ap) 635 // } 636 return Xprintf(t, s, *(*uintptr)(unsafe.Pointer(uintptr(ap)))) 637 } 638 639 // int vfprintf(FILE *stream, const char *format, va_list ap); 640 func Xvfprintf(t *TLS, stream, format, ap Intptr) int32 { 641 // if dmesgs { 642 // dmesg("vfprintf(%#x(%d)%q, %q, %#x)", stream, *(*int32)(unsafe.Pointer(uintptr(stream))), GoString(format), ap) 643 // } 644 return Xfprintf(t, stream, format, *(*uintptr)(unsafe.Pointer(uintptr(ap)))) 645 } 646 647 // int memcmp(const void *s1, const void *s2, size_t n); 648 func Xmemcmp(t *TLS, s1, s2, n Intptr) int32 { 649 // if dmesgs { 650 // dmesg("memcmpy(%#x, %#x, %#x)", s1, s2, n) 651 // } 652 for ; n != 0; n-- { 653 c1 := *(*byte)(unsafe.Pointer(uintptr(s1))) 654 s1++ 655 c2 := *(*byte)(unsafe.Pointer(uintptr(s2))) 656 s2++ 657 if c1 < c2 { 658 return -1 659 } 660 if c1 > c2 { 661 return 1 662 } 663 } 664 return 0 665 } 666 667 // void abort(void); 668 func Xabort(t *TLS) { 669 if dmesgs { 670 dmesg("abort()") 671 } 672 Xexit(t, 1) 673 } 674 675 // double sin(double x); 676 func Xsin(t *TLS, x float64) float64 { return math.Sin(x) } 677 678 // float sinf(float x); 679 func Xsinf(t *TLS, x float32) float32 { return float32(math.Sin(float64(x))) } 680 681 // double cos(double x); 682 func Xcos(t *TLS, x float64) float64 { return math.Cos(x) } 683 684 // float cosf(float x); 685 func Xcosf(t *TLS, x float32) float32 { return float32(math.Cos(float64(x))) } 686 687 // double tan(double x); 688 func Xtan(t *TLS, x float64) float64 { return math.Tan(x) } 689 690 // double asin(double x); 691 func Xasin(t *TLS, x float64) float64 { return math.Asin(x) } 692 693 // double acos(double x); 694 func Xacos(t *TLS, x float64) float64 { return math.Acos(x) } 695 696 // double atan(double x); 697 func Xatan(t *TLS, x float64) float64 { return math.Atan(x) } 698 699 // double sinh(double x); 700 func Xsinh(t *TLS, x float64) float64 { return math.Sinh(x) } 701 702 // double cosh(double x); 703 func Xcosh(t *TLS, x float64) float64 { return math.Cosh(x) } 704 705 // double tanh(double x); 706 func Xtanh(t *TLS, x float64) float64 { return math.Tanh(x) } 707 708 // double exp(double x); 709 func Xexp(t *TLS, x float64) float64 { return math.Exp(x) } 710 711 // double fabs(double x); 712 func Xfabs(t *TLS, x float64) float64 { return math.Abs(x) } 713 714 // float fabs(float x); 715 func Xfabsf(t *TLS, x float32) float32 { return float32(math.Abs(float64(x))) } 716 717 // double log(double x); 718 func Xlog(t *TLS, x float64) float64 { return math.Log(x) } 719 720 // double log10(double x); 721 func Xlog10(t *TLS, x float64) float64 { return math.Log10(x) } 722 723 // double pow(double x, double y); 724 func Xpow(t *TLS, x, y float64) float64 { return math.Pow(x, y) } 725 726 // double sqrt(double x); 727 func Xsqrt(t *TLS, x float64) float64 { return math.Sqrt(x) } 728 729 // double round(double x); 730 func Xround(t *TLS, x float64) float64 { return math.Round(x) } 731 732 // double ceil(double x); 733 func Xceil(t *TLS, x float64) float64 { return math.Ceil(x) } 734 735 // double floor(double x); 736 func Xfloor(t *TLS, x float64) float64 { return math.Floor(x) } 737 738 // char *strcpy(char *dest, const char *src) 739 func Xstrcpy(t *TLS, dest, src Intptr) Intptr { 740 // if dmesgs { 741 // dmesg("strcpy(%#x, %q)", dest, GoString(src)) 742 // } 743 r := dest 744 for ; ; dest++ { 745 c := *(*int8)(unsafe.Pointer(uintptr(src))) 746 src++ 747 *(*int8)(unsafe.Pointer(uintptr(dest))) = c 748 if c == 0 { 749 return r 750 } 751 } 752 } 753 754 // char *strncpy(char *dest, const char *src, size_t n) 755 func Xstrncpy(t *TLS, dest, src, n Intptr) Intptr { 756 // if dmesgs { 757 // dmesg("strncpy(%#x, %q, %#x)", dest, GoString(src), n) 758 // } 759 ret := dest 760 for c := *(*int8)(unsafe.Pointer(uintptr(src))); c != 0 && n > 0; n-- { 761 *(*int8)(unsafe.Pointer(uintptr(dest))) = c 762 dest++ 763 src++ 764 c = *(*int8)(unsafe.Pointer(uintptr(src))) 765 } 766 for ; uintptr(n) > 0; n-- { 767 *(*int8)(unsafe.Pointer(uintptr(dest))) = 0 768 dest++ 769 } 770 return ret 771 } 772 773 // int strcmp(const char *s1, const char *s2) 774 func Xstrcmp(t *TLS, s1, s2 Intptr) int32 { 775 // if dmesgs { 776 // dmesg("strcmp(%q, %q)", GoString(s1), GoString(s2)) 777 // } 778 for { 779 ch1 := *(*byte)(unsafe.Pointer(uintptr(s1))) 780 s1++ 781 ch2 := *(*byte)(unsafe.Pointer(uintptr(s2))) 782 s2++ 783 if ch1 != ch2 || ch1 == 0 || ch2 == 0 { 784 return int32(ch1) - int32(ch2) 785 } 786 } 787 } 788 789 // size_t strlen(const char *s) 790 func Xstrlen(t *TLS, s Intptr) Intptr { 791 // if dmesgs { 792 // dmesg("strlen(%q)", GoString(s)) 793 // } 794 var n Intptr 795 for ; *(*int8)(unsafe.Pointer(uintptr(s))) != 0; s++ { 796 n++ 797 } 798 return n 799 } 800 801 // char *strcat(char *dest, const char *src) 802 func Xstrcat(t *TLS, dest, src Intptr) Intptr { 803 // if dmesgs { 804 // dmesg("strcat(%q, %q)", GoString(dest), GoString(src)) 805 // } 806 ret := dest 807 for *(*int8)(unsafe.Pointer(uintptr(dest))) != 0 { 808 dest++ 809 } 810 for { 811 c := *(*int8)(unsafe.Pointer(uintptr(src))) 812 src++ 813 *(*int8)(unsafe.Pointer(uintptr(dest))) = c 814 dest++ 815 if c == 0 { 816 return ret 817 } 818 } 819 } 820 821 // int strncmp(const char *s1, const char *s2, size_t n) 822 func Xstrncmp(t *TLS, s1, s2, n Intptr) int32 { 823 // if dmesgs { 824 // dmesg("strncmp(%q, %q, %d)", GoString(s1), GoString(s2), n) 825 // } 826 var ch1, ch2 byte 827 for n != 0 { 828 ch1 = *(*byte)(unsafe.Pointer(uintptr(s1))) 829 s1++ 830 ch2 = *(*byte)(unsafe.Pointer(uintptr(s2))) 831 s2++ 832 n-- 833 if ch1 != ch2 || ch1 == 0 || ch2 == 0 { 834 break 835 } 836 } 837 if n != 0 { 838 return int32(ch1) - int32(ch2) 839 } 840 841 return 0 842 } 843 844 // char *strchr(const char *s, int c) 845 func Xstrchr(t *TLS, s Intptr, c int32) Intptr { 846 // if dmesgs { 847 // dmesg("strchr(%q, %#x)", GoString(s), c) 848 // } 849 for { 850 ch2 := *(*byte)(unsafe.Pointer(uintptr(s))) 851 if ch2 == byte(c) { 852 return s 853 } 854 855 if ch2 == 0 { 856 return 0 857 } 858 859 s++ 860 } 861 } 862 863 // char *strrchr(const char *s, int c) 864 func Xstrrchr(t *TLS, s Intptr, c int32) Intptr { 865 // if dmesgs { 866 // dmesg("strrchr(%q, %#x)", GoString(s), c) 867 // } 868 var ret Intptr 869 for { 870 ch2 := *(*byte)(unsafe.Pointer(uintptr(s))) 871 if ch2 == 0 { 872 return ret 873 } 874 875 if ch2 == byte(c) { 876 ret = s 877 } 878 s++ 879 } 880 } 881 882 // int sprintf(char *str, const char *format, ...); 883 func Xsprintf(t *TLS, str, format Intptr, args uintptr) (r int32) { 884 // if dmesgs { 885 // dmesg("sprintf(%#x, %q, %#x)", str, GoString(format), args) 886 // } 887 b := printf(format, args) 888 b = append(b, 0) 889 copy((*RawMem)(unsafe.Pointer(uintptr(str)))[:len(b)], b) 890 return int32(len(b) - 1) 891 } 892 893 // void *malloc(size_t size); 894 func Xmalloc(t *TLS, size Intptr) Intptr { return Intptr(malloc(int(size))) } 895 896 // void *realloc(void *ptr, size_t size); 897 func Xrealloc(t *TLS, ptr, size Intptr) Intptr { return Intptr(realloc(uintptr(ptr), int(size))) } 898 899 // void free(void *ptr); 900 func Xfree(t *TLS, ptr Intptr) { free(uintptr(ptr)) } 901 902 // void exit(int status); 903 func Xexit(t *TLS, status int32) { 904 if dmesgs { 905 dmesg("exit(%v)", status) 906 } 907 os.Exit(int(status)) 908 } 909 910 // void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function); 911 func X__assert_fail(t *TLS, assertion, file Intptr, line int32, function Intptr) { 912 if dmesgs { 913 dmesg("__assert_fail(%q, %q, %v, %q)", GoString(assertion), GoString(file), line, GoString(function)) 914 } 915 fmt.Fprintf(os.Stderr, "assertion failure: %s:%d.%s: %s\n", GoString(file), line, GoString(function), GoString(assertion)) 916 os.Exit(1) 917 } 918 919 // int getrusage(int who, struct rusage *usage); 920 func Xgetrusage(t *TLS, who int32, usage Intptr) int32 { 921 panic("CRT") 922 } 923 924 // int fprintf(FILE *stream, const char *format, ...); 925 func Xfprintf(t *TLS, stream, format Intptr, args uintptr) int32 { 926 // if dmesgs { 927 // dmesg("fprintf(%#x(%d), %q, %#x)", stream, *(*int32)(unsafe.Pointer(uintptr(stream))), GoString(format), args) 928 // } 929 fd := *(*int32)(unsafe.Pointer(uintptr(stream))) 930 switch fd { 931 case 0: 932 b := printf(format, args) 933 n, err := os.Stdout.Write(b) 934 if err != nil { 935 t.setErrno(err) 936 return -1 937 } 938 939 return int32(n) 940 case 2: 941 b := printf(format, args) 942 n, err := os.Stderr.Write(b) 943 if err != nil { 944 t.setErrno(err) 945 return -1 946 } 947 948 return int32(n) 949 } 950 panic("CRT") 951 } 952 953 // int fflush(FILE *stream); 954 func Xfflush(t *TLS, stream Intptr) int32 { 955 // if dmesgs { 956 // switch stream { 957 // case 0: 958 // dmesg("fflush(0)") 959 // default: 960 // dmesg("fflush(%#x(%d))", stream, *(*int32)(unsafe.Pointer(uintptr(stream)))) 961 // } 962 // } 963 var err error 964 switch stream { 965 case 0: 966 if err = os.Stdout.Sync(); err != nil { 967 break 968 } 969 970 err = os.Stderr.Sync() 971 default: 972 switch *(*int32)(unsafe.Pointer(uintptr(stream))) { 973 case 0: 974 os.Stdout.Sync() 975 case 2: 976 os.Stderr.Sync() 977 } 978 } 979 if err != nil { 980 t.setErrno(err) 981 if dmesgs { 982 dmesg("fflush(): %v", err) 983 dmesg("fflush(): -1") 984 } 985 return eof 986 } 987 988 return 0 989 } 990 991 // FILE *fopen(const char *pathname, const char *mode); 992 func Xfopen(t *TLS, pathname, mode Intptr) Intptr { return Xfopen64(t, pathname, mode) } 993 994 // FILE *fopen64(const char *pathname, const char *mode); 995 func Xfopen64(t *TLS, pathname, mode Intptr) Intptr { 996 s := GoString(pathname) 997 m := GoString(mode) 998 // if dmesgs { 999 // dmesg("fopen64(%q, %q)", s, m) 1000 // } 1001 switch s { 1002 case os.Stderr.Name(): 1003 panic("CRT") 1004 case os.Stdin.Name(): 1005 panic("CRT") 1006 case os.Stdout.Name(): 1007 panic("CRT") 1008 } 1009 1010 switch m { 1011 case "r", "rb": 1012 fd, err := syscall.Open(s, os.O_RDONLY, 0660) 1013 if err != nil { 1014 t.setErrno(err) 1015 if dmesgs { 1016 dmesg("fopen64(): %d, %v", 0, err) 1017 } 1018 return 0 1019 } 1020 1021 p := mustMalloc(4) 1022 *(*int32)(unsafe.Pointer(p)) = int32(fd) 1023 // if dmesgs { 1024 // dmesg("fopen64(%q, %q): %v", s, m, fd) 1025 // } 1026 return Intptr(p) 1027 default: 1028 panic(m) 1029 } 1030 } 1031 1032 // void rewind(FILE *stream); 1033 func Xrewind(t *TLS, stream Intptr) { 1034 // if dmesgs { 1035 // dmesg("rewind(%#x(%d))", stream, *(*int32)(unsafe.Pointer(uintptr(stream)))) 1036 // } 1037 Xfseek(t, stream, 0, stdio.DSEEK_SET) 1038 } 1039 1040 // int mkdir(const char *path, mode_t mode); 1041 func Xmkdir(t *TLS, path Intptr, mode int32) int32 { 1042 panic("CRT") 1043 } 1044 1045 // int symlink(const char *target, const char *linkpath); 1046 func Xsymlink(t *TLS, target, linkpath Intptr) int32 { 1047 panic("CRT") 1048 } 1049 1050 // int * __errno_location(void); 1051 func X__errno_location(t *TLS) Intptr { return Intptr(t.errnop) } 1052 1053 // int chmod(const char *pathname, mode_t mode) 1054 func Xchmod(t *TLS, pathname Intptr, mode int32) int32 { 1055 panic("CRT") 1056 } 1057 1058 // size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 1059 func Xfwrite(t *TLS, ptr, size, nmemb, stream Intptr) Intptr { 1060 panic("CRT") 1061 } 1062 1063 // time_t time(time_t *tloc); 1064 func Xtime(t *TLS, tloc Intptr) Intptr { 1065 panic("CRT") 1066 } 1067 1068 // int fputc(int c, FILE *stream); 1069 func Xfputc(t *TLS, c int32, stream Intptr) int32 { 1070 panic("CRT") 1071 } 1072 1073 // void *memmove(void *dest, const void *src, size_t n); 1074 func Xmemmove(t *TLS, dest, src, n Intptr) Intptr { 1075 // if dmesgs { 1076 // dmesg("memmove(%#x, %#x, %#x)", dest, src, n) 1077 // } 1078 copy((*RawMem)(unsafe.Pointer(uintptr(dest)))[:n], (*RawMem)(unsafe.Pointer(uintptr(src)))[:n]) 1079 return dest 1080 } 1081 1082 // int utimes(const char *filename, const struct timeval times[2]); 1083 func Xutimes(t *TLS, filename, times Intptr) int32 { 1084 panic("CRT") 1085 } 1086 1087 // int closedir(DIR *dirp); 1088 func Xclosedir(t *TLS, dir Intptr) int32 { 1089 panic("CRT") 1090 } 1091 1092 // DIR *opendir(const char *name); 1093 func Xopendir(t *TLS, dir Intptr) Intptr { 1094 panic("CRT") 1095 } 1096 1097 // struct dirent *readdir(DIR *dirp); 1098 func Xreaddir64(t *TLS, dir Intptr) Intptr { 1099 panic("CRT") 1100 } 1101 1102 // ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize); 1103 func Xreadlink(t *TLS, path, buf, bufsize Intptr) Intptr { 1104 panic("CRT") 1105 } 1106 1107 // char *getenv(const char *name); 1108 func Xgetenv(t *TLS, name Intptr) Intptr { 1109 // if dmesgs { 1110 // dmesg("getenv(%q)", GoString(name)) 1111 // } 1112 if os.Getenv(GoString(name)) == "" { 1113 // if dmesgs { 1114 // dmesg("getenv(): %q", "") 1115 // } 1116 return 0 1117 } 1118 panic("CRT") 1119 } 1120 1121 // char *strstr(const char *haystack, const char *needle); 1122 func Xstrstr(t *TLS, haystack, needle Intptr) Intptr { 1123 panic("CRT") 1124 } 1125 1126 // int atoi(const char *nptr); 1127 func Xatoi(t *TLS, nptr Intptr) int32 { 1128 return int32(Xatol(t, nptr)) 1129 } 1130 1131 // pid_t getpid(void); 1132 func Xgetpid(t *TLS) int32 { 1133 r := int32(os.Getpid()) 1134 // if dmesgs { 1135 // dmesg("getpid(): %d", r) 1136 // } 1137 return r 1138 } 1139 1140 // int fgetc(FILE *stream); 1141 func Xfgetc(t *TLS, stream Intptr) int32 { 1142 panic("CRT") 1143 } 1144 1145 // int access(const char *pathname, int mode); 1146 func Xaccess(t *TLS, pathname Intptr, mode int32) int32 { 1147 //TODO handle properly F_OK 1148 r, _, err := syscall.Syscall(syscall.SYS_ACCESS, uintptr(pathname), uintptr(mode), 0) 1149 if err != 0 { 1150 t.setErrno(err) 1151 if dmesgs { 1152 dmesg("access(): %v, %v", 1, err) 1153 } 1154 return -1 1155 } 1156 1157 // if dmesgs { 1158 // dmesg("access(): %v, %v", r, err) 1159 // } 1160 return int32(r) 1161 } 1162 1163 // int pclose(FILE *stream); 1164 func Xpclose(t *TLS, stream Intptr) int32 { 1165 panic("CRT") 1166 } 1167 1168 // int chdir(const char *path); 1169 func Xchdir(t *TLS, path Intptr) int32 { 1170 panic("CRT") 1171 } 1172 1173 // FILE *popen(const char *command, const char *type); 1174 func Xpopen(t *TLS, command, typ Intptr) Intptr { 1175 panic("CRT") 1176 } 1177 1178 // long int strtol(const char *nptr, char **endptr, int base); 1179 func Xstrtol(t *TLS, nptr, endptr Intptr, base int32) long { 1180 panic("CRT") 1181 } 1182 1183 // int tolower(int c); 1184 func Xtolower(t *TLS, c int32) int32 { 1185 panic("CRT") 1186 } 1187 1188 // uid_t getuid(void); 1189 func Xgetuid(t *TLS) int32 { 1190 r := os.Getuid() 1191 // if dmesgs { 1192 // dmesg("geuid(): %v", r) 1193 // } 1194 return int32(r) 1195 } 1196 1197 // int isatty(int fd); 1198 func Xisatty(t *TLS, fd int32) int32 { 1199 // if dmesgs { 1200 // dmesg("isatty(%v)", fd) 1201 // } 1202 return Bool32(isatty.IsTerminal(uintptr(fd))) 1203 } 1204 1205 func cString(s string) uintptr { 1206 n := len(s) 1207 p := mustMalloc(n + 1) 1208 copy((*RawMem)(unsafe.Pointer(p))[:n], s) 1209 (*RawMem)(unsafe.Pointer(p))[n] = 0 1210 return p 1211 } 1212 1213 // int setvbuf(FILE *stream, char *buf, int mode, size_t size); 1214 func Xsetvbuf(t *TLS, stream, buf Intptr, mode int32, size Intptr) int32 { 1215 // if dmesgs { 1216 // dmesg("setvbuf(%#x(%d), %#x, %#x, %#x)", stream, *(*int32)(unsafe.Pointer(uintptr(stream))), buf, mode, size) 1217 // } 1218 return 0 1219 } 1220 1221 // int raise(int sig); 1222 func Xraise(t *TLS, sig int32) int32 { 1223 panic("CRT") 1224 } 1225 1226 // sighandler_t signal(int signum, sighandler_t handler); 1227 func Xsignal(t *TLS, signum int32, handler Intptr) Intptr { 1228 // if dmesgs { 1229 // dmesg("signal(%d, %#x)", signum, handler) 1230 // } 1231 switch signum { 1232 case 2: // SIGINT 1233 return 0 1234 } 1235 panic("CRT") 1236 } 1237 1238 // char *strdup(const char *s); 1239 func Xstrdup(t *TLS, s Intptr) Intptr { 1240 panic("CRT") 1241 } 1242 1243 type tm struct { 1244 sec int32 // Seconds [0,60]. 1245 min int32 // Minutes [0,59]. 1246 hour int32 // Hour [0,23]. 1247 mday int32 // Day of month [1,31]. 1248 mon int32 // Month of year [0,11]. 1249 year int32 // Years since 1900. 1250 wday int32 // Day of week [0,6] (Sunday =0). 1251 yday int32 // Day of year [0,365]. 1252 isdst int32 // Daylight Savings flag. 1253 } 1254 1255 var localtime = mustCalloc(int(unsafe.Sizeof(tm{}))) 1256 1257 // struct tm *localtime(const time_t *timep); 1258 func Xlocaltime(_ *TLS, timep Intptr) Intptr { 1259 ut := *(*syscall.Time_t)(unsafe.Pointer(uintptr(timep))) 1260 t := time.Unix(int64(ut), 0) 1261 (*tm)(unsafe.Pointer(localtime)).sec = int32(t.Second()) 1262 (*tm)(unsafe.Pointer(localtime)).min = int32(t.Minute()) 1263 (*tm)(unsafe.Pointer(localtime)).hour = int32(t.Hour()) 1264 (*tm)(unsafe.Pointer(localtime)).mday = int32(t.Day()) 1265 (*tm)(unsafe.Pointer(localtime)).mon = int32(t.Month()) 1266 (*tm)(unsafe.Pointer(localtime)).year = int32(t.Year()) 1267 (*tm)(unsafe.Pointer(localtime)).wday = int32(t.Weekday()) 1268 (*tm)(unsafe.Pointer(localtime)).yday = int32(t.YearDay()) 1269 (*tm)(unsafe.Pointer(localtime)).isdst = -1 //TODO 1270 return Intptr(localtime) 1271 1272 } 1273 1274 // int open(const char *pathname, int flags, ...); 1275 func Xopen64(t *TLS, pathname Intptr, flags int32, args uintptr) int32 { 1276 var perm uint32 1277 if args != 0 { 1278 perm = *(*uint32)(unsafe.Pointer(args)) 1279 } 1280 1281 s := GoString(pathname) 1282 // if dmesgs { 1283 // dmesg("open64(%q, %#x, %#o)", s, flags, perm) 1284 // } 1285 fd, err := syscall.Open(s, int(flags), perm) 1286 // if dmesgs { 1287 // dmesg("open64(): fd %d, %v", fd, err) 1288 // } 1289 if err != nil { 1290 t.setErrno(err) 1291 if dmesgs { 1292 dmesg("open64(%q): %v", s, err) 1293 } 1294 return -1 1295 } 1296 1297 if dmesgs { 1298 dmesg("open64(%q): %v", s, int32(fd)) 1299 } 1300 return int32(fd) 1301 } 1302 1303 // char *strerror(int errnum); 1304 func Xstrerror(t *TLS, errnum int32) Intptr { 1305 p, _ := CString(fmt.Sprintf("errno: %d", errnum)) //TODO static table or map 1306 return p 1307 } 1308 1309 // void *dlopen(const char *filename, int flags); 1310 func Xdlopen(t *TLS, filename Intptr, flags int32) Intptr { 1311 panic("CRT") 1312 } 1313 1314 // char *dlerror(void); 1315 func Xdlerror(t *TLS) Intptr { 1316 panic("CRT") 1317 } 1318 1319 // void *dlsym(void *handle, const char *symbol); 1320 func Xdlsym(t *TLS, handle, symbol Intptr) Intptr { 1321 panic("CRT") 1322 } 1323 1324 // int dlclose(void *handle); 1325 func Xdlclose(t *TLS, handle Intptr) int32 { 1326 panic("CRT") 1327 } 1328 1329 // unsigned int sleep(unsigned int seconds); 1330 func Xsleep(t *TLS, seconds int32) int32 { 1331 // if dmesgs { 1332 // dmesg("sleep(%d)", seconds) 1333 // } 1334 time.Sleep(time.Duration(seconds) * time.Second) 1335 return 0 1336 } 1337 1338 // size_t strcspn(const char *s, const char *reject); 1339 func Xstrcspn(t *TLS, s, reject Intptr) (r Intptr) { 1340 bits := newBits(256) 1341 for { 1342 c := *(*byte)(unsafe.Pointer(uintptr(reject))) 1343 if c == 0 { 1344 break 1345 } 1346 1347 reject++ 1348 bits.set(int(c)) 1349 } 1350 for { 1351 c := *(*byte)(unsafe.Pointer(uintptr(s))) 1352 if bits.has(int(c)) { 1353 return r 1354 } 1355 1356 s++ 1357 r++ 1358 } 1359 } 1360 1361 // char *getcwd(char *buf, size_t size); 1362 func Xgetcwd(t *TLS, buf, size Intptr) Intptr { 1363 // if dmesgs { 1364 // dmesg("getcwd(%#x, %#x)", buf, size) 1365 // } 1366 _, err := syscall.Getcwd((*RawMem)(unsafe.Pointer(uintptr(buf)))[:size]) 1367 if err != nil { 1368 t.setErrno(err) 1369 if dmesgs { 1370 dmesg("getcwd(): 0, %v", err) 1371 } 1372 return 0 1373 } 1374 1375 // if dmesgs { 1376 // dmesg("getcwd(): %#x (%q)", buf, GoString(buf)) 1377 // } 1378 return buf 1379 } 1380 1381 // int fchmod(int fd, mode_t mode); 1382 func Xfchmod(t *TLS, fd, mode int32) int32 { 1383 panic("CRT") 1384 } 1385 1386 // int rmdir(const char *pathname); 1387 func Xrmdir(t *TLS, pathname Intptr) int32 { 1388 panic("CRT") 1389 } 1390 1391 // int fchown(int fd, uid_t owner, gid_t group); 1392 func Xfchown(t *TLS, fd, owner, grout int32) int32 { 1393 panic("CRT") 1394 } 1395 1396 // int backtrace(void **buffer, int size); 1397 func Xbacktrace(t *TLS, buf Intptr, size int32) int32 { 1398 return 0 1399 } 1400 1401 // double fmod(double x, double y); 1402 func Xfmod(t *TLS, x, y float64) float64 { return math.Mod(x, y) } 1403 1404 // double atan2(double y, double x); 1405 func Xatan2(t *TLS, x, y float64) float64 { return math.Atan2(x, y) } 1406 1407 // long atol(const char *nptr); 1408 func Xatol(t *TLS, nptr Intptr) (r long) { 1409 var c byte 1410 k := long(1) 1411 out: 1412 for { 1413 c = *(*byte)(unsafe.Pointer(uintptr(nptr))) 1414 switch c { 1415 case ' ', '\t', '\n', '\r', '\v', '\f': 1416 nptr++ 1417 case '+': 1418 nptr++ 1419 break out 1420 case '-': 1421 nptr++ 1422 k = -1 1423 break out 1424 default: 1425 break out 1426 } 1427 } 1428 for { 1429 c = *(*byte)(unsafe.Pointer(uintptr(nptr))) 1430 nptr++ 1431 switch { 1432 case c >= '0' && c <= '9': 1433 r = 10*r + long(c) - '0' 1434 default: 1435 return k * r 1436 } 1437 } 1438 } 1439 1440 // int fputs(const char *s, FILE *stream); 1441 func Xfputs(t *TLS, s, stream Intptr) int32 { 1442 // gs := GoString(s) 1443 // if dmesgs { 1444 // dmesg("fputs(%q, %#x(%d))", gs, stream, *(*int32)(unsafe.Pointer(uintptr(stream)))) 1445 // } 1446 // fd := *(*int32)(unsafe.Pointer(uintptr(stream))) 1447 panic("CRT") 1448 } 1449 1450 // void perror(const char *s); 1451 func Xperror(t *TLS, s Intptr) { 1452 gs := GoString(s) 1453 // if dmesgs { 1454 // dmesg("perror(%q)", gs) 1455 // } 1456 switch gs { 1457 case "": 1458 fmt.Fprintf(os.Stderr, "errno(%d)\n", *(*int32)(unsafe.Pointer(t.errnop))) 1459 default: 1460 fmt.Fprintf(os.Stderr, "%s: errno(%d)\n", gs, *(*int32)(unsafe.Pointer(t.errnop))) 1461 } 1462 } 1463 1464 // int toupper(int c); 1465 func Xtoupper(t *TLS, c int32) int32 { 1466 if c >= 'a' && c <= 'z' { 1467 return c - ('a' - 'A') 1468 } 1469 1470 return c 1471 } 1472 1473 // int _IO_putc(int c, _IO_FILE *fp); 1474 func X_IO_putc(t *TLS, c int32, fp Intptr) int32 { 1475 // if dmesgs { 1476 // dmesg("fputs(%#x, %#x(%d))", c, fp, *(*int32)(unsafe.Pointer(uintptr(fp)))) 1477 // } 1478 fd := *(*int32)(unsafe.Pointer(uintptr(fp))) 1479 switch fd { 1480 case 0: 1481 _, err := os.Stdout.Write([]byte{byte(c)}) 1482 if err != nil { 1483 t.setErrno(err) 1484 if dmesgs { 1485 dmesg("fputc(): %v", err) 1486 } 1487 return eof 1488 } 1489 1490 return int32(byte(c)) 1491 } 1492 panic("CRT") 1493 } 1494 1495 var nextRand = uint64(1) 1496 1497 // int rand(void); 1498 func Xrand(t *TLS) int32 { 1499 nextRand = nextRand*1103515245 + 12345 1500 return int32(uint32(nextRand / (math.MaxUint32 + 1) % math.MaxInt32)) 1501 } 1502 1503 type sorter struct { 1504 len int 1505 base Intptr 1506 sz Intptr 1507 f func(*TLS, Intptr, Intptr) int32 1508 t *TLS 1509 } 1510 1511 func (s *sorter) Len() int { return s.len } 1512 1513 func (s *sorter) Less(i, j int) bool { 1514 return s.f(s.t, s.base+Intptr(i)*s.sz, s.base+Intptr(j)*s.sz) < 0 1515 } 1516 1517 func (s *sorter) Swap(i, j int) { 1518 p := uintptr(s.base + Intptr(i)*s.sz) 1519 q := uintptr(s.base + Intptr(j)*s.sz) 1520 for i := 0; i < int(s.sz); i++ { 1521 *(*byte)(unsafe.Pointer(p)), *(*byte)(unsafe.Pointer(q)) = *(*byte)(unsafe.Pointer(q)), *(*byte)(unsafe.Pointer(p)) 1522 p++ 1523 q++ 1524 } 1525 } 1526 1527 // void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 1528 func Xqsort(t *TLS, base, nmemb, size, compar Intptr) { 1529 // if dmesgs { 1530 // dmesg("qsort(%#x, %d, size %d, %#x", base, nmemb, size, compar) 1531 // } 1532 sort.Sort(&sorter{ 1533 len: int(nmemb), 1534 base: base, 1535 sz: size, 1536 f: (*struct { 1537 f func(*TLS, Intptr, Intptr) int32 1538 })(unsafe.Pointer(&struct{ Intptr }{compar})).f, 1539 t: t, 1540 }) 1541 } 1542 1543 func CString(s string) (Intptr, error) { 1544 n := len(s) 1545 p := malloc(n + 1) 1546 if p == 0 { 1547 return 0, fmt.Errorf("CString: cannot allocate %d bytes", n+1) 1548 } 1549 1550 copy((*RawMem)(unsafe.Pointer(p))[:n], s) 1551 *(*byte)(unsafe.Pointer(p + uintptr(n))) = 0 1552 return Intptr(p), nil 1553 } 1554 1555 // int usleep(useconds_t usec); 1556 func Xusleep(t *TLS, usec int32) int32 { 1557 // if dmesgs { 1558 // dmesg("usleep(%d)", usec) 1559 // } 1560 time.Sleep(time.Duration(usec) * time.Microsecond) 1561 return 0 1562 }