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  }