Files
postmoogle/vendor/modernc.org/libc/libc_windows.go
2024-07-03 12:21:47 +03:00

1675 lines
40 KiB
Go

// Copyright 2020 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libc // import "modernc.org/libc"
import (
"fmt"
"math"
mbits "math/bits"
"os"
"reflect"
"runtime"
"runtime/debug"
"sort"
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
//UCRT "unicode"
"unicode/utf16"
"unsafe"
"modernc.org/mathutil"
"modernc.org/memory"
)
const iobEntries = 20
var (
allocator memory.Allocator
allocatorMu sync.Mutex
cR = [...]byte{'r', 0}
cW = [...]byte{'w', 0}
dll = syscall.NewLazyDLL("ucrtbase.dll")
iob [iobEntries]uintptr
isWindows = true
kdll = syscall.NewLazyDLL("kernel32.dll")
objects = map[uintptr]any{}
objectsMu sync.Mutex
threadCallback uintptr
token atomic.Uintptr
uintptrSize = unsafe.Sizeof(uintptr(0))
wenvValid atomic.Bool
wenviron uintptr
winEnviron = []uintptr{0}
)
var X__imp__wenviron = uintptr(unsafe.Pointer(&wenviron))
var X_imp___wenviron = uintptr(unsafe.Pointer(&wenviron))
var Xin6addr_any [16]byte
var Xstderr uintptr
var Xstdin uintptr
var Xstdout uintptr
var Xtimezone long // extern long timezone;
func init() {
threadCallback = syscall.NewCallback(threadProc)
iob[0] = X_fdopen(nil, 0, uintptr(unsafe.Pointer(&cR[0])))
iob[1] = X_fdopen(nil, 1, uintptr(unsafe.Pointer(&cW[0])))
iob[2] = X_fdopen(nil, 2, uintptr(unsafe.Pointer(&cW[0])))
Xstdin = iob[0]
Xstdout = iob[1]
Xstderr = iob[2]
}
func addObject(o any) uintptr {
t := token.Add(1)
objectsMu.Lock()
objects[t] = o
objectsMu.Unlock()
return t
}
func getObject(t uintptr) (r any) {
objectsMu.Lock()
r = objects[t]
objectsMu.Unlock()
return r
}
func removeObject(t uintptr) {
objectsMu.Lock()
delete(objects, t)
objectsMu.Unlock()
}
//TODO- type MemAuditError struct {
//TODO- Caller string
//TODO- Message string
//TODO- }
type long = int32
type ulong = uint32
type threadAdapter struct {
token uintptr
tls *TLS
param uintptr
threadFunc func(*TLS, uintptr) uint32
}
func (t *threadAdapter) run() uintptr {
runtime.LockOSThread()
t.tls.token = t.token
r := (t.threadFunc(t.tls, t.param))
t.tls.endthread(r)
return uintptr(r)
}
func threadProc(p uintptr) uintptr {
adp, ok := getObject(p).(*threadAdapter)
if !ok {
panic("invalid thread")
}
return adp.run()
}
var procCreateThread = kdll.NewProc("CreateThread")
var _ = procCreateThread.Addr()
// libkernel32: __attribute__((dllimport)) HANDLE CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
func CreateThread(tls *TLS, attr uintptr, stackSize Tsize_t, fn uintptr, param uintptr, flags uint32, threadID uintptr) (r uintptr) {
f := (*struct {
f func(*TLS, uintptr) uint32
})(unsafe.Pointer(&struct{ uintptr }{fn})).f
var adapter = threadAdapter{threadFunc: f, tls: NewTLS(), param: param}
adapter.token = addObject(&adapter)
r0, _, _ := syscall.SyscallN(procCreateThread.Addr(), attr, uintptr(stackSize), threadCallback, adapter.token, uintptr(flags), threadID)
return r0
}
// __attribute__ ((__dllimport__)) uintptr_t __attribute__((__cdecl__)) _beginthread(_beginthread_proc_type _StartAddress,unsigned _StackSize,void *_ArgList);
func X_beginthread(tls *TLS, __StartAddress T_beginthread_proc_type, __StackSize uint32, __ArgList uintptr) (r Tuintptr_t) {
f := (*struct {
f func(*TLS, uintptr) uint32
})(unsafe.Pointer(&struct{ uintptr }{__StartAddress})).f
var adapter = threadAdapter{threadFunc: f, tls: NewTLS(), param: __ArgList}
adapter.token = addObject(&adapter)
r0, _, _ := syscall.SyscallN(procCreateThread.Addr(), 0, uintptr(__StackSize), threadCallback, adapter.token, 0, 0)
return Tuintptr_t(r0)
}
// __attribute__ ((__dllimport__)) uintptr_t __attribute__((__cdecl__)) _beginthreadex(void *_Security,unsigned _StackSize,_beginthreadex_proc_type _StartAddress,void *_ArgList,unsigned _InitFlag,unsigned *_ThrdAddr);
func X_beginthreadex(tls *TLS, __Security uintptr, __StackSize uint32, __StartAddress T_beginthreadex_proc_type, __ArgList uintptr, __InitFlag uint32, __ThrdAddr uintptr) (r Tuintptr_t) {
f := (*struct {
f func(*TLS, uintptr) uint32
})(unsafe.Pointer(&struct{ uintptr }{__StartAddress})).f
var adapter = threadAdapter{threadFunc: f, tls: NewTLS(), param: __ArgList}
adapter.token = addObject(&adapter)
r0, _, _ := syscall.SyscallN(procCreateThread.Addr(), 0, uintptr(__StackSize), threadCallback, adapter.token, 0, 0)
return Tuintptr_t(r0)
}
// __attribute__ ((__dllimport__)) void __attribute__((__cdecl__)) _endthreadex(unsigned _Retval) __attribute__ ((__noreturn__));
func X_endthreadex(tls *TLS, __Retval uint32) {
tls.endthread(__Retval)
}
func Start(main func(*TLS, int32, uintptr) int32) {
runtime.LockOSThread()
argv := Xcalloc(nil, 1, Tsize_t((len(os.Args)+1)*int(uintptrSize)))
if argv == 0 {
panic("OOM")
}
p := argv
for _, v := range os.Args {
s := Xcalloc(nil, 1, Tsize_t(len(v)+1))
if s == 0 {
panic("OOM")
}
copy(unsafe.Slice((*byte)(unsafe.Pointer(s)), len(v)), v)
*(*uintptr)(unsafe.Pointer(p)) = s
p += uintptrSize
}
t := NewTLS()
rc := main(t, int32(len(os.Args)), argv)
Xexit(t, rc)
}
type tlsStackSlot struct {
p uintptr
sz Tsize_t
}
// TLS emulates thread local storage. TLS is not safe for concurrent use by
// multiple goroutines.
type TLS struct {
errnop uintptr
lastError uint32 // libkernel32.{SetLastError,GetLastError}
stack []tlsStackSlot
token uintptr
retval uint32
sp int
exited bool
}
// NewTLS returns a newly created TLS that must be eventually closed to prevent
// resource leaks.
func NewTLS() (r *TLS) {
p := mustMalloc(Tsize_t(unsafe.Sizeof(int32(0))))
*(*int32)(unsafe.Pointer(p)) = 0
return &TLS{
errnop: p,
}
}
var procexit = dll.NewProc("exit")
var _ = procexit.Addr()
// void __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) exit(int _Code) __attribute__ ((__noreturn__));
func Xexit(tls *TLS, __Code int32) {
Xfflush(tls, Xstdout)
Xfflush(tls, Xstderr)
syscall.SyscallN(procexit.Addr(), uintptr(__Code))
}
func (tls *TLS) endthread(retval uint32) {
if tls == nil || tls.exited {
return
}
tls.exited = true
tls.retval = retval
tls.Close()
removeObject(tls.token)
runtime.UnlockOSThread()
}
func (tls *TLS) SetLastError(_dwErrCode uint32) {
if tls != nil {
tls.lastError = _dwErrCode
}
}
// https://github.com/golang/go/issues/41220
func (tls *TLS) GetLastError() (r uint32) {
if tls == nil {
return 0
}
return tls.lastError
}
func (tls *TLS) setErrno(n int32) {
if __ccgo_strace {
trc("errno<-%v", n)
}
if tls == nil {
return
}
*(*int32)(unsafe.Pointer(tls.errnop)) = n
}
func X___errno_location(t *TLS) uintptr {
return t.errnop
}
// int * __errno_location(void);
func X__errno_location(t *TLS) uintptr {
return t.errnop
}
// __attribute__ ((__dllimport__)) extern int * __attribute__((__cdecl__)) _errno(void);
func X_errno(tls *TLS) (r uintptr) {
return tls.errnop
}
func malloc(n Tsize_t) (r uintptr) {
allocatorMu.Lock()
defer allocatorMu.Unlock()
if r, _ = allocator.UintptrMalloc(int(n)); r == 0 {
panic("OOM")
}
return r
}
func free(p uintptr) {
allocatorMu.Lock()
defer allocatorMu.Unlock()
allocator.UintptrFree(p)
}
func malloc_usable_size(p uintptr) (r Tsize_t) {
if p == 0 {
return 0
}
allocatorMu.Lock()
defer allocatorMu.Unlock()
return Tsize_t(memory.UintptrUsableSize(p))
}
func (tls *TLS) Close() {
if tls == nil {
return
}
// for _, v := range tls.allocas {
// free(tls, v)
// }
for _, v := range tls.stack /* shrink diabled[:tls.sp] */ {
free(v.p)
}
}
func (tls *TLS) Alloc(n0 int) (r uintptr) {
const shrinkSegment = 32
n := Tsize_t(n0)
if tls.sp < len(tls.stack) {
p := tls.stack[tls.sp].p
sz := tls.stack[tls.sp].sz
if sz >= n /* && sz <= shrinkSegment*n */ {
// Segment shrinking is nice to have but Tcl does some dirty hacks in coroutine
// handling that require stability of stack addresses, out of the C execution
// model. Disabled.
tls.sp++
return p
}
free(p)
r = malloc(n)
tls.stack[tls.sp] = tlsStackSlot{p: r, sz: malloc_usable_size(r)}
tls.sp++
return r
}
r = malloc(n)
tls.stack = append(tls.stack, tlsStackSlot{p: r, sz: malloc_usable_size(r)})
tls.sp++
return r
}
// Free manages memory of the preceding TLS.Alloc()
func (tls *TLS) Free(n int) {
tls.sp--
}
// VaList fills a varargs list at p with args and returns p. The list must
// have been allocated by the caller and it must not be in Go managed memory,
// ie. it must be pinned. The caller is responsible for freeing the list.
//
// This function supports code generated by ccgo/v4.
//
// Note: The C translated to Go varargs ABI alignment for all types is 8 on all
// architectures.
func VaList(p uintptr, args ...interface{}) (r uintptr) {
if p&7 != 0 {
panic("internal error")
}
r = p
for _, v := range args {
switch x := v.(type) {
case int:
*(*int64)(unsafe.Pointer(p)) = int64(x)
case int32:
*(*int64)(unsafe.Pointer(p)) = int64(x)
case int64:
*(*int64)(unsafe.Pointer(p)) = x
case uint:
*(*uint64)(unsafe.Pointer(p)) = uint64(x)
case uint16:
*(*uint64)(unsafe.Pointer(p)) = uint64(x)
case uint32:
*(*uint64)(unsafe.Pointer(p)) = uint64(x)
case uint64:
*(*uint64)(unsafe.Pointer(p)) = x
case float64:
*(*float64)(unsafe.Pointer(p)) = x
case uintptr:
*(*uintptr)(unsafe.Pointer(p)) = x
default:
sz := reflect.TypeOf(v).Size()
copy(unsafe.Slice((*byte)(unsafe.Pointer(p)), sz), unsafe.Slice((*byte)(unsafe.Pointer((*[2]uintptr)(unsafe.Pointer(&v))[1])), sz))
p += roundup(sz, 8)
continue
}
p += 8
}
return r
}
func roundup(n, to uintptr) uintptr {
if r := n % to; r != 0 {
return n + to - r
}
return n
}
func mustMalloc(sz Tsize_t) (r uintptr) {
if r = Xmalloc(nil, sz); r != 0 || sz == 0 {
return r
}
panic("OOM")
}
// CString returns a pointer to a zero-terminated version of s. The caller is
// responsible for freeing the allocated memory using Xfree.
func CString(s string) (uintptr, error) {
n := len(s)
p := Xmalloc(nil, Tsize_t(n)+1)
if p == 0 {
return 0, fmt.Errorf("CString: cannot allocate %d bytes", n+1)
}
copy(unsafe.Slice((*byte)(unsafe.Pointer(p)), n), s)
*(*byte)(unsafe.Pointer(p + uintptr(n))) = 0
return p, nil
}
// GoBytes returns a byte slice from a C char* having length len bytes.
func GoBytes(s uintptr, len int) []byte {
return unsafe.Slice((*byte)(unsafe.Pointer(s)), len)
}
// GoString returns the value of a C string at s.
func GoString(s uintptr) string {
if s == 0 {
return ""
}
var buf []byte
for {
b := *(*byte)(unsafe.Pointer(s))
if b == 0 {
return string(buf)
}
buf = append(buf, b)
s++
}
}
func X__ccgo_SyscallFP() {
s := fmt.Sprintf("%s\nTODO syscall: function pointer", debug.Stack())
panic(s)
}
func Bool(v bool) bool { return v }
func Bool32(b bool) int32 {
if b {
return 1
}
return 0
}
func fwrite(tls *TLS, f uintptr, b []byte) (int, error) {
if len(b) == 0 {
return 0, nil
}
n := Xfwrite(tls, uintptr(unsafe.Pointer(&b[0])), 1, Tsize_t(len(b)), f)
if int(n) != len(b) {
return int(n), fmt.Errorf("short write")
}
return len(b), nil
}
// int fprintf(FILE *stream, const char *format, ...);
func Xfprintf(tls *TLS, stream, format, args uintptr) int32 {
n, _ := fwrite(tls, stream, printf(format, args))
return int32(n)
}
func X__acrt_iob_func(tls *TLS, _index uint32) (r uintptr) {
return iob[_index]
}
// extern __attribute__((__format__ (gnu_printf, 2, 0))) __attribute__ ((__nonnull__ (2))) int __attribute__((__cdecl__)) __mingw_vfprintf (FILE * __restrict__ , const char * __restrict__ , va_list) __attribute__ ((__nothrow__));
func X__mingw_vfprintf(tls *TLS, _0 uintptr, _1 uintptr, _2 Tva_list) (r int32) {
return Xvfprintf(tls, _0, _1, _2)
}
func X__mingw_vsprintf(tls *TLS, _0 uintptr, _1 uintptr, _2 Tva_list) (r int32) {
return Xvsprintf(tls, _0, _1, _2)
}
func X__builtin_inff(tls *TLS) float32 {
return float32(math.Inf(1))
}
func X__builtin_nanf(tls *TLS, s uintptr) float32 {
return float32(math.NaN())
}
func X__builtin_printf(tls *TLS, fmt uintptr, va uintptr) (r int32) {
return Xprintf(tls, fmt, va)
}
func X__builtin_round(tls *TLS, x float64) (r float64) {
return Xround(tls, x)
}
func X__builtin_roundf(tls *TLS, x float32) (r float32) {
return Xroundf(tls, x)
}
func X__builtin_expect(t *TLS, exp, c long) long {
return exp
}
func X__builtin_abort(t *TLS) {
Xabort(t)
}
func X__builtin_abs(t *TLS, j int32) int32 {
return Xabs(t, j)
}
func X__builtin_ctz(t *TLS, n uint32) int32 {
return int32(mbits.TrailingZeros32(n))
}
func X__builtin_clz(t *TLS, n uint32) int32 {
return int32(mbits.LeadingZeros32(n))
}
func X__builtin_clzl(t *TLS, n ulong) int32 {
return int32(mbits.LeadingZeros32(n))
}
func X__builtin_clzll(t *TLS, n uint64) int32 {
return int32(mbits.LeadingZeros64(n))
}
func X__builtin_constant_p_impl() { panic("internal error: should never be called") }
func X__builtin_copysign(t *TLS, x, y float64) float64 {
return Xcopysign(t, x, y)
}
func X__builtin_copysignf(t *TLS, x, y float32) float32 {
return Xcopysignf(t, x, y)
}
func X__builtin_copysignl(t *TLS, x, y float64) float64 {
return Xcopysign(t, x, y)
}
func X__builtin_exit(t *TLS, status int32) {
Xexit(t, status)
}
func X__builtin_fabs(t *TLS, x float64) float64 {
return Xfabs(t, x)
}
func X__builtin_fabsf(t *TLS, x float32) float32 {
return Xfabsf(t, x)
}
func X__builtin_free(t *TLS, ptr uintptr) {
Xfree(t, ptr)
}
func X__builtin_huge_val(t *TLS) float64 {
return math.Inf(1)
}
func X__builtin_huge_valf(t *TLS) float32 {
return float32(math.Inf(1))
}
func X__builtin_inf(t *TLS) float64 {
return math.Inf(1)
}
func X__builtin_infl(t *TLS) float64 {
return math.Inf(1)
}
func X__builtin_malloc(t *TLS, size Tsize_t) uintptr {
return Xmalloc(t, size)
}
func X__builtin_memcmp(t *TLS, s1, s2 uintptr, n Tsize_t) int32 {
return Xmemcmp(t, s1, s2, n)
}
func X__builtin_nan(t *TLS, s uintptr) float64 {
return math.NaN()
}
func X__builtin_nanl(t *TLS, s uintptr) float64 {
return math.NaN()
}
func X__builtin_prefetch(t *TLS, addr, args uintptr) {
}
func X__builtin_strchr(t *TLS, s uintptr, c int32) uintptr {
return Xstrchr(t, s, c)
}
func X__builtin_strcmp(t *TLS, s1, s2 uintptr) int32 {
return Xstrcmp(t, s1, s2)
}
func X__builtin_strcpy(t *TLS, dest, src uintptr) uintptr {
return Xstrcpy(t, dest, src)
}
func X__builtin_strlen(t *TLS, s uintptr) Tsize_t {
return Xstrlen(t, s)
}
func X__builtin_trap(t *TLS) {
Xabort(t)
}
func X__builtin_popcount(t *TLS, x uint32) int32 {
return int32(mbits.OnesCount32(x))
}
// int __builtin_popcountl (unsigned long x)
func X__builtin_popcountl(t *TLS, x ulong) int32 {
return int32(mbits.OnesCount32(x))
}
// char * __builtin___strcpy_chk (char *dest, const char *src, size_t os);
func X__builtin___strcpy_chk(t *TLS, dest, src uintptr, os Tsize_t) uintptr {
return Xstrcpy(t, dest, src)
}
// uint16_t __builtin_bswap16 (uint32_t x)
func X__builtin_bswap16(t *TLS, x uint16) uint16 {
return x<<8 |
x>>8
}
// uint32_t __builtin_bswap32 (uint32_t x)
func X__builtin_bswap32(t *TLS, x uint32) uint32 {
return x<<24 |
x&0xff00<<8 |
x&0xff0000>>8 |
x>>24
}
// uint64_t __builtin_bswap64 (uint64_t x)
func X__builtin_bswap64(t *TLS, x uint64) uint64 {
return x<<56 |
x&0xff00<<40 |
x&0xff0000<<24 |
x&0xff000000<<8 |
x&0xff00000000>>8 |
x&0xff0000000000>>24 |
x&0xff000000000000>>40 |
x>>56
}
// bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
func X__builtin_add_overflowInt64(t *TLS, a, b int64, res uintptr) int32 {
r, ovf := mathutil.AddOverflowInt64(a, b)
*(*int64)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
// bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
func X__builtin_add_overflowUint32(t *TLS, a, b uint32, res uintptr) int32 {
r := a + b
*(*uint32)(unsafe.Pointer(res)) = r
return Bool32(r < a)
}
// bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
func X__builtin_add_overflowUint64(t *TLS, a, b uint64, res uintptr) int32 {
r := a + b
*(*uint64)(unsafe.Pointer(res)) = r
return Bool32(r < a)
}
// bool __builtin_sub_overflow (type1 a, type2 b, type3 *res)
func X__builtin_sub_overflowInt64(t *TLS, a, b int64, res uintptr) int32 {
r, ovf := mathutil.SubOverflowInt64(a, b)
*(*int64)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
func X__builtin_mul_overflowInt64(t *TLS, a, b int64, res uintptr) int32 {
r, ovf := mathutil.MulOverflowInt64(a, b)
*(*int64)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
func X__builtin_mul_overflowUint64(t *TLS, a, b uint64, res uintptr) int32 {
hi, lo := mbits.Mul64(a, b)
*(*uint64)(unsafe.Pointer(res)) = lo
return Bool32(hi != 0)
}
// bool __builtin_mul_overflow (type1 a, type2 b, type3 *res)
func X__builtin_mul_overflowUint128(t *TLS, a, b Uint128, res uintptr) int32 {
r, ovf := a.mulOvf(b)
*(*Uint128)(unsafe.Pointer(res)) = r
return Bool32(ovf)
}
func X__builtin_unreachable(t *TLS) {
fmt.Fprintf(os.Stderr, "unrechable\n")
os.Stderr.Sync()
Xexit(t, 1)
}
func X__builtin_sprintf(t *TLS, str, format, args uintptr) (r int32) {
return Xsprintf(t, str, format, args)
}
func X__builtin_memcpy(t *TLS, dest, src uintptr, n Tsize_t) (r uintptr) {
return Xmemcpy(t, dest, src, n)
}
// void * __builtin___memcpy_chk (void *dest, const void *src, size_t n, size_t os);
func X__builtin___memcpy_chk(t *TLS, dest, src uintptr, n, os Tsize_t) (r uintptr) {
if os != ^Tsize_t(0) && n < os {
Xabort(t)
}
return Xmemcpy(t, dest, src, n)
}
func X__builtin_memset(t *TLS, s uintptr, c int32, n Tsize_t) uintptr {
return Xmemset(t, s, c, n)
}
// void * __builtin___memset_chk (void *s, int c, size_t n, size_t os);
func X__builtin___memset_chk(t *TLS, s uintptr, c int32, n, os Tsize_t) uintptr {
if os < n {
Xabort(t)
}
return Xmemset(t, s, c, n)
}
// size_t __builtin_object_size (const void * ptr, int type)
func X__builtin_object_size(t *TLS, p uintptr, typ int32) Tsize_t {
return ^Tsize_t(0) //TODO frontend magic
}
// int __builtin___sprintf_chk (char *s, int flag, size_t os, const char *fmt, ...);
func X__builtin___sprintf_chk(t *TLS, s uintptr, flag int32, os Tsize_t, format, args uintptr) (r int32) {
return Xsprintf(t, s, format, args)
}
func X__builtin_isnan(t *TLS, x float64) int32 {
return Bool32(math.IsNaN(x))
}
func X__builtin_isnanf(t *TLS, x float32) int32 {
return Bool32(math.IsNaN(float64(x)))
}
func X__isnanl(t *TLS, arg float64) int32 {
return X__builtin_isnanl(t, arg)
}
func X__builtin_isnanl(t *TLS, x float64) int32 {
return Bool32(math.IsNaN(x))
}
func X__builtin_log2(t *TLS, x float64) float64 {
return Xlog2(t, x)
}
func X__builtin___strncpy_chk(t *TLS, dest, src uintptr, n, os Tsize_t) (r uintptr) {
if n != ^Tsize_t(0) && os < n {
Xabort(t)
}
return Xstrncpy(t, dest, src, n)
}
func X__builtin___strcat_chk(t *TLS, dest, src uintptr, os Tsize_t) (r uintptr) {
return Xstrcat(t, dest, src)
}
func X__builtin___memmove_chk(t *TLS, dest, src uintptr, n, os Tsize_t) uintptr {
if os != ^Tsize_t(0) && os < n {
Xabort(t)
}
return Xmemmove(t, dest, src, n)
}
func X__builtin_isunordered(t *TLS, a, b float64) int32 {
return Bool32(math.IsNaN(a) || math.IsNaN(b))
}
func X__builtin_rintf(tls *TLS, x float32) (r float32) {
return Xrintf(tls, x)
}
func X__builtin_lrintf(tls *TLS, x float32) (r long) {
return Xlrintf(tls, x)
}
func X__builtin_lrint(tls *TLS, x float64) (r long) {
return Xlrint(tls, x)
}
// double __builtin_fma(double x, double y, double z);
func X__builtin_fma(tls *TLS, x, y, z float64) (r float64) {
return math.FMA(x, y, z)
}
func X__builtin_isprint(tls *TLS, c int32) (r int32) {
return Xisprint(tls, c)
}
func X__builtin_trunc(tls *TLS, x float64) (r float64) {
return Xtrunc(tls, x)
}
func X__builtin_hypot(tls *TLS, x float64, y float64) (r float64) {
return Xhypot(tls, x, y)
}
func X__builtin_vsnprintf(t *TLS, str uintptr, size Tsize_t, format, va uintptr) int32 {
return Xsnprintf(t, str, size, format, va)
}
func X__mingw_vsnprintf(tls *TLS, str uintptr, size Tsize_t, format, va uintptr) int32 {
return Xsnprintf(tls, str, size, format, va)
}
func X__ms_vsnprintf(tls *TLS, str uintptr, size Tsize_t, format, va uintptr) int32 {
return Xsnprintf(tls, str, size, format, va)
}
func X_vsnprintf(tls *TLS, str uintptr, size Tsize_t, format, va uintptr) int32 {
return Xsnprintf(tls, str, size, format, va)
}
// int snprintf(char *str, size_t size, const char *format, ...);
func Xsnprintf(t *TLS, str uintptr, size Tsize_t, format, args uintptr) (r int32) {
if __ccgo_strace {
trc("t=%v str=%v size=%v args=%v, (%v:)", t, str, size, args, origin(2))
defer func() { trc("-> %v", r) }()
}
if format == 0 {
return 0
}
b := printf(format, args)
r = int32(len(b))
if size == 0 {
return r
}
if len(b)+1 > int(size) {
b = b[:size-1]
}
n := len(b)
copy(unsafe.Slice((*byte)(unsafe.Pointer(str)), n)[:n:n], b)
*(*byte)(unsafe.Pointer(str + uintptr(n))) = 0
return r
}
var proc_open = dll.NewProc("_open")
var _ = proc_open.Addr()
// int open(const char * __filename, int __flags, ...)
func X_open(tls *TLS, filename uintptr, flags int32, va uintptr) (r int32) {
var mode int32
if va != 0 {
mode = VaInt32(&va)
}
if __ccgo_strace {
trc("filename=%q flags=%v mode=%#0o", GoString(filename), flags, mode)
defer func() { trc(`X_open->%+v`, r) }()
}
r0, r1, err := syscall.SyscallN(proc_open.Addr(), filename, uintptr(flags), uintptr(mode))
_, _ = r0, r1
if err != 0 {
tls.setErrno(int32(err))
}
return int32(r0)
}
func Xopen(tls *TLS, filename uintptr, flags int32, va uintptr) int32 {
return X_open(tls, filename, flags, va)
}
// This version does include the zero terminator in the returned Go string.
func goWideString(p uintptr) string {
if p == 0 {
return ""
}
var w []uint16
for {
wc := *(*uint16)(unsafe.Pointer(p))
p += 2
w = append(w, wc)
// append until U0000
if wc == 0 {
break
}
}
s := utf16.Decode(w)
return string(s)
}
var proc_wopen = dll.NewProc("_wopen")
var _ = proc_wopen.Addr()
// int wopen(wchar * __filename, int __flags, ...)
func X_wopen(tls *TLS, filename uintptr, flags int32, va uintptr) (r int32) {
var mode int32
if va != 0 {
mode = VaInt32(&va)
}
if __ccgo_strace {
trc("filename=%q flags=%v mode=%#0o", goWideString(filename), flags, mode)
defer func() { trc(`X_wopen->%+v`, r) }()
}
r0, r1, err := syscall.SyscallN(proc_wopen.Addr(), filename, uintptr(flags), uintptr(mode))
_, _ = r0, r1
if err != 0 {
tls.setErrno(int32(err))
}
return int32(r0)
}
func Xwopen(tls *TLS, filename uintptr, flags int32, va uintptr) int32 {
return X_wopen(tls, filename, flags, va)
}
func Xread(tls *TLS, __FileHandle int32, __DstBuf uintptr, __MaxCharCount uint32) (r int32) {
return X_read(tls, __FileHandle, __DstBuf, __MaxCharCount)
}
func Xclose(tls *TLS, __FileHandle int32) (r int32) {
return X_close(tls, __FileHandle)
}
func Xwrite(tls *TLS, __FileHandle int32, __Buf uintptr, __MaxCharCount uint32) (r int32) {
return X_write(tls, __FileHandle, __Buf, __MaxCharCount)
}
func Xunlink(tls *TLS, __Filename uintptr) (r int32) {
return X_unlink(tls, __Filename)
}
func Xsetmode(tls *TLS, __FileHandle int32, __Mode int32) (r int32) {
return X_setmode(tls, __FileHandle, __Mode)
}
func Xfileno(tls *TLS, __File uintptr) (r int32) {
return X_fileno(tls, __File)
}
// void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
func Xqsort(tls *TLS, base uintptr, nmemb, size Tsize_t, compar uintptr) {
sort.Sort(&sorter{
len: int(nmemb),
base: base,
sz: uintptr(size),
f: (*struct {
f func(*TLS, uintptr, uintptr) int32
})(unsafe.Pointer(&struct{ uintptr }{compar})).f,
t: tls,
})
}
func Xprintf(tls *TLS, format, va uintptr) int32 {
b := printf(format, va)
if len(b) == 0 {
return 0
}
n, err := fwrite(tls, Xstdout, printf(format, va))
if err != nil {
return -1
}
return int32(n)
}
//UCRT // int __attribute__((__cdecl__)) putchar(int _Ch);
//UCRT func Xputchar(tls *TLS, __Ch int32) (r int32) {
//UCRT return Xputc(tls, __Ch, Xstdout)
//UCRT }
//UCRT // int __attribute__((__cdecl__)) puts(const char *_Str);
//UCRT func Xputs(tls *TLS, __Str uintptr) (r int32) {
//UCRT r = Xfputs(tls, __Str, Xstdout)
//UCRT return r + Xputc(tls, '\n', Xstdout)
//UCRT }
func Xtzset(tls *TLS) {
X_tzset(tls)
}
func GoWideString(p uintptr) string {
return goWideStringNZ(p)
}
func goWideStringNZ(p uintptr) string {
if p == 0 {
return ""
}
var w []uint16
for {
wc := *(*uint16)(unsafe.Pointer(p))
p += 2
if wc == 0 {
break
}
w = append(w, wc)
}
s := utf16.Decode(w)
return string(s)
}
func X_wgetenv(t *TLS, varname uintptr) uintptr {
if wenvValid.Swap(true) == false {
bootWinEnviron(t)
}
k := strings.ToLower(goWideStringNZ(varname))
for _, v := range winEnviron[:len(winEnviron)-1] {
s := strings.ToLower(goWideStringNZ(v))
x := strings.IndexByte(s, '=')
if s[:x] == k {
return v
}
}
return 0
}
func allocW(t *TLS, v string) (r uintptr) {
s := utf16.Encode([]rune(v))
p := Xcalloc(t, Tsize_t(len(s)+1), 2)
if p == 0 {
panic(todo(""))
}
r = p
for _, v := range s {
*(*uint16)(unsafe.Pointer(p)) = v
p += 2
}
return r
}
func X_wputenv(t *TLS, envstring uintptr) int32 {
if wenvValid.Swap(true) == false {
bootWinEnviron(t)
}
s0 := goWideStringNZ(envstring)
s := strings.ToLower(s0)
x := strings.IndexByte(s, '=')
k := s[:x]
for i, v := range winEnviron[:len(winEnviron)-1] {
s2 := strings.ToLower(goWideStringNZ(v))
x := strings.IndexByte(s2, '=')
if s2[:x] == k {
Xfree(t, v)
winEnviron[i] = allocW(t, s0)
return 0
}
}
np := allocW(t, s0)
winEnviron = winEnviron[:len(winEnviron)-1]
winEnviron = append(winEnviron, np, 0)
wenviron = uintptr(unsafe.Pointer(&winEnviron[0]))
return 0
}
func bootWinEnviron(t *TLS) {
winEnviron = winEnviron[:0]
for _, s := range os.Environ() {
r := allocW(t, s)
winEnviron = append(winEnviron, r)
}
wenviron = uintptr(unsafe.Pointer(&winEnviron[0]))
}
func X_copysign(t *TLS, x, y float64) float64 {
return Xcopysign(t, x, y)
}
func Xchmod(tls *TLS, __Filename uintptr, __Mode int32) (r int32) {
return X_chmod(tls, __Filename, __Mode)
}
func Xisatty(tls *TLS, __FileHandle int32) (r int32) {
return X_isatty(tls, __FileHandle)
}
func AtomicLoadNUint8(ptr uintptr, memorder int32) uint8 {
return byte(a_load_8(ptr))
}
func AtomicLoadNUint16(ptr uintptr, memorder int32) uint16 {
return uint16(a_load_16(ptr))
}
func AtomicStoreNUint8(ptr uintptr, val uint8, memorder int32) {
a_store_8(ptr, byte(val))
}
func AtomicStoreNUint16(ptr uintptr, val uint16, memorder int32) {
a_store_16(ptr, val)
}
func AtomicLoadPInt32(addr uintptr) (val int32) {
return atomic.LoadInt32((*int32)(unsafe.Pointer(addr)))
}
func AtomicLoadPInt64(addr uintptr) (val int64) {
return atomic.LoadInt64((*int64)(unsafe.Pointer(addr)))
}
func AtomicLoadPUint32(addr uintptr) (val uint32) {
return atomic.LoadUint32((*uint32)(unsafe.Pointer(addr)))
}
func AtomicLoadPUint64(addr uintptr) (val uint64) {
return atomic.LoadUint64((*uint64)(unsafe.Pointer(addr)))
}
func AtomicLoadPUintptr(addr uintptr) (val uintptr) {
return atomic.LoadUintptr((*uintptr)(unsafe.Pointer(addr)))
}
func AtomicLoadPFloat32(addr uintptr) (val float32) {
return math.Float32frombits(atomic.LoadUint32((*uint32)(unsafe.Pointer(addr))))
}
func AtomicLoadPFloat64(addr uintptr) (val float64) {
return math.Float64frombits(atomic.LoadUint64((*uint64)(unsafe.Pointer(addr))))
}
func AtomicStorePInt32(addr uintptr, val int32) {
atomic.StoreInt32((*int32)(unsafe.Pointer(addr)), val)
}
func AtomicStorePInt64(addr uintptr, val int64) {
atomic.StoreInt64((*int64)(unsafe.Pointer(addr)), val)
}
func AtomicStorePUint32(addr uintptr, val uint32) {
atomic.StoreUint32((*uint32)(unsafe.Pointer(addr)), val)
}
func AtomicStorePUint64(addr uintptr, val uint64) {
atomic.StoreUint64((*uint64)(unsafe.Pointer(addr)), val)
}
func AtomicStorePUintptr(addr uintptr, val uintptr) {
atomic.StoreUintptr((*uintptr)(unsafe.Pointer(addr)), val)
}
func AtomicStorePFloat32(addr uintptr, val float32) {
atomic.StoreUint32((*uint32)(unsafe.Pointer(addr)), math.Float32bits(val))
}
func AtomicStorePFloat64(addr uintptr, val float64) {
atomic.StoreUint64((*uint64)(unsafe.Pointer(addr)), math.Float64bits(val))
}
// int _snwprintf(
//
// wchar_t *buffer,
// size_t count,
// const wchar_t *format [,
// argument] ...
//
// );
func X_snwprintf(tls *TLS, buffer uintptr, count Tsize_t, format, va uintptr) int32 {
panic(todo(""))
}
func Xsnwprintf(tls *TLS, buffer uintptr, count Tsize_t, format, va uintptr) int32 {
return X_snwprintf(tls, buffer, count, format, va)
}
// int _vscprintf(const char *format, va_list va);
func X_vscprintf(t *TLS, format uintptr, va uintptr) int32 {
return int32(len(printf(format, va)))
}
func X_sscanf(t *TLS, str, format, va uintptr) int32 {
return scanf(strings.NewReader(GoString(str)), format, va)
}
// int sscanf(const char *str, const char *format, ...);
func Xsscanf(t *TLS, str, format, va uintptr) int32 {
return X_sscanf(t, str, format, va)
}
// pid_t getpid(void);
func Xgetpid(t *TLS) int32 {
return int32(os.Getpid())
}
// void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function);
func X__assert_fail(t *TLS, assertion, file uintptr, line uint32, function uintptr) {
if __ccgo_strace {
trc("t=%v file=%v line=%v function=%v, (%v:)", t, file, line, function, origin(2))
}
fmt.Fprintf(os.Stderr, "assertion failure: %s:%d.%s: %s\n", GoString(file), line, GoString(function), GoString(assertion))
os.Stderr.Sync()
Xexit(t, 1)
}
// unsigned long long strtoull(const char *nptr, char **endptr, int base);
//UCRT func Xstrtoull(t *TLS, nptr, endptr uintptr, base int32) uint64 {
//UCRT var s uintptr = nptr
//UCRT var acc uint64
//UCRT var c byte
//UCRT var cutoff uint64
//UCRT var neg int32
//UCRT var any int32
//UCRT var cutlim int32
//UCRT
//UCRT /*
//UCRT * Skip white space and pick up leading +/- sign if any.
//UCRT * If base is 0, allow 0x for hex and 0 for octal, else
//UCRT * assume decimal; if base is already 16, allow 0x.
//UCRT */
//UCRT for {
//UCRT c = *(*byte)(unsafe.Pointer(s))
//UCRT PostIncUintptr(&s, 1)
//UCRT var sp = strings.TrimSpace(string(c))
//UCRT if len(sp) > 0 {
//UCRT break
//UCRT }
//UCRT }
//UCRT
//UCRT if c == '-' {
//UCRT neg = 1
//UCRT c = *(*byte)(unsafe.Pointer(s))
//UCRT PostIncUintptr(&s, 1)
//UCRT } else if c == '+' {
//UCRT c = *(*byte)(unsafe.Pointer(s))
//UCRT PostIncUintptr(&s, 1)
//UCRT }
//UCRT
//UCRT sp := *(*byte)(unsafe.Pointer(s))
//UCRT
//UCRT if (base == 0 || base == 16) &&
//UCRT c == '0' && (sp == 'x' || sp == 'X') {
//UCRT PostIncUintptr(&s, 1)
//UCRT c = *(*byte)(unsafe.Pointer(s)) //s[1];
//UCRT PostIncUintptr(&s, 1)
//UCRT base = 16
//UCRT }
//UCRT if base == 0 {
//UCRT if c == '0' {
//UCRT base = 0
//UCRT } else {
//UCRT base = 10
//UCRT }
//UCRT }
//UCRT
//UCRT cutoff = math.MaxUint64 / uint64(base)
//UCRT cutlim = int32(math.MaxUint64 % uint64(base))
//UCRT
//UCRT acc = 0
//UCRT any = 0
//UCRT
//UCRT for {
//UCRT var cs = string(c)
//UCRT if unicode.IsDigit([]rune(cs)[0]) {
//UCRT c -= '0'
//UCRT } else if unicode.IsLetter([]rune(cs)[0]) {
//UCRT if unicode.IsUpper([]rune(cs)[0]) {
//UCRT c -= 'A' - 10
//UCRT } else {
//UCRT c -= 'a' - 10
//UCRT }
//UCRT } else {
//UCRT break
//UCRT }
//UCRT
//UCRT if int32(c) >= base {
//UCRT break
//UCRT }
//UCRT if any < 0 || acc > cutoff || (acc == cutoff && int32(c) > cutlim) {
//UCRT any = -1
//UCRT
//UCRT } else {
//UCRT any = 1
//UCRT acc *= uint64(base)
//UCRT acc += uint64(c)
//UCRT }
//UCRT
//UCRT c = *(*byte)(unsafe.Pointer(s))
//UCRT PostIncUintptr(&s, 1)
//UCRT }
//UCRT
//UCRT if any < 0 {
//UCRT acc = math.MaxUint64
//UCRT t.setErrno(ERANGE)
//UCRT } else if neg == 1 {
//UCRT acc = -acc
//UCRT }
//UCRT
//UCRT if endptr != 0 {
//UCRT if any == 1 {
//UCRT PostDecUintptr(&s, 1)
//UCRT AssignPtrUintptr(endptr, s)
//UCRT } else {
//UCRT AssignPtrUintptr(endptr, nptr)
//UCRT }
//UCRT }
//UCRT return acc
//UCRT }
// int _stat32i64(const char *path, struct _stat32i64 *buffer);
//UCRT func X_stat64i32(t *TLS, path uintptr, buffer uintptr) int32 {
//UCRT panic(todo(""))
//UCRT }
func X__mingw_strtod(t *TLS, s uintptr, p uintptr) float64 {
return Xstrtod(t, s, p)
}
// int vsscanf(const char *str, const char *format, va_list ap);
func X__ms_vsscanf(t *TLS, str, format, ap uintptr) int32 {
panic(todo(""))
}
// int vsscanf(const char *str, const char *format, va_list ap);
func X__mingw_vsscanf(t *TLS, str, format, ap uintptr) int32 {
return Xsscanf(t, str, format, ap)
}
// unsigned int _set_abort_behavior(
//
// unsigned int flags,
// unsigned int mask
//
// );
//UCRT func X_set_abort_behavior(t *TLS, _ ...interface{}) uint32 {
//UCRT panic(todo(""))
//UCRT }
// double atof(const char *nptr);
func Xatof(t *TLS, nptr uintptr) float64 {
n, _ := strconv.ParseFloat(GoString(nptr), 64)
return n
}
func X__builtin_snprintf(t *TLS, str uintptr, size Tsize_t, format, args uintptr) int32 {
return Xsnprintf(t, str, size, format, args)
}
// int _snprintf(char *str, size_t size, const char *format, ...);
func X_snprintf(t *TLS, str uintptr, size Tsize_t, format, args uintptr) int32 {
return Xsnprintf(t, str, size, format, args)
}
// intptr_t _findfirst64i32(const char *filespec, struct _finddata64i32_t *fileinfo);
//UCRT func X_findfirst64i32(t *TLS, filespec, fileinfo uintptr) Tintptr_t {
//UCRT panic(todo(""))
//UCRT }
// int _findnext64i32(intptr_t handle, struct _finddata64i32_t *fileinfo);
//UCRT func X_findnext64i32(t *TLS, handle Tintptr_t, fileinfo uintptr) int32 {
//UCRT panic(todo(""))
//UCRT }
func X__isnan(t *TLS, x float64) int32 {
return Bool32(math.IsNaN(x))
}
// int _stati64(char *path, struct _stati64 *buffer);
func X_stati64(t *TLS, path, buffer uintptr) int32 {
return X_stat64(t, path, buffer)
}
// int _fstati64(int fd, struct _stati64 *buffer);
func X_fstati64(t *TLS, fd int32, buffer uintptr) int32 {
return X_fstat64(t, fd, buffer)
}
func X_strcmpi(tls *TLS, __Str1 uintptr, __Str2 uintptr) (r int32) {
if __ccgo_strace {
trc("_Str1=%+v _Str2=%+v", __Str1, __Str2)
defer func() { trc(`X_strcmpi->%+v`, r) }()
}
r0, r1, err := syscall.SyscallN(proc_stricmp.Addr(), __Str1, __Str2)
if err != 0 {
if __ccgo_strace {
trc(`r0=%v r1=%v err=%v`, r0, r1, err)
}
tls.setErrno(int32(err))
}
return int32(r0)
}
// ------------------------------------------------------------------------ (A)
// https://chromium.googlesource.com/external/github.com/kripken/emscripten/+/refs/tags/1.2.9/system/lib/libc/stdlib/strtod.c
//
// /*
// * strtod.c --
// *
// * Source code for the "strtod" library procedure.
// *
// * Copyright (c) 1988-1993 The Regents of the University of California.
// * Copyright (c) 1994 Sun Microsystems, Inc.
// *
// * Permission to use, copy, modify, and distribute this
// * software and its documentation for any purpose and without
// * fee is hereby granted, provided that the above copyright
// * notice appear in all copies. The University of California
// * makes no representations about the suitability of this
// * software for any purpose. It is provided "as is" without
// * express or implied warranty.
// *
// * RCS: @(#) $Id$
// *
// * Taken from http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/missing/strtod.c
// */
//
// C documentation
//
// /*
// *----------------------------------------------------------------------
// *
// * strtod --
// *
// * This procedure converts a floating-point number from an ASCII
// * decimal representation to internal double-precision format.
// *
// * Results:
// * The return value is the double-precision floating-point
// * representation of the characters in string. If endPtr isn't
// * NULL, then *endPtr is filled in with the address of the
// * next character after the last one that was part of the
// * floating-point number.
// *
// * Side effects:
// * None.
// *
// *----------------------------------------------------------------------
// */
func Xstrtod(tls *TLS, string1 uintptr, endPtr uintptr) (r float64) {
/* If non-NULL, store terminating character's
* address here. */
var c, decPt, exp, expSign, frac1, frac2, fracExp, mantSize, sign, v1, v2 int32
var d, p, pExp uintptr
var dblExp, fraction float64
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = c, d, dblExp, decPt, exp, expSign, frac1, frac2, fracExp, fraction, mantSize, p, pExp, sign, v1, v2
expSign = FALSE
exp = 0 /* Exponent read from "EX" field. */
fracExp = 0 /* Temporarily holds location of exponent
* in string. */
/*
* Strip off leading blanks and check for a sign.
*/
p = string1
for {
v1 = int32(*(*int8)(unsafe.Pointer(p)))
v2 = BoolInt32(v1 == int32(' ') || uint32(v1)-uint32('\t') < uint32(5))
goto _3
_3:
if !(v2 != 0) {
break
}
p += uintptr(1)
}
if int32(*(*int8)(unsafe.Pointer(p))) == int32('-') {
sign = int32(TRUE)
p += uintptr(1)
} else {
if int32(*(*int8)(unsafe.Pointer(p))) == int32('+') {
p += uintptr(1)
}
sign = FALSE
}
/*
* Count the number of digits in the mantissa (including the decimal
* point), and also locate the decimal point.
*/
decPt = -int32(1)
mantSize = 0
for {
c = int32(*(*int8)(unsafe.Pointer(p)))
if !(BoolInt32(uint32(c)-Uint32FromUint8('0') < Uint32FromInt32(10)) != 0) {
if c != int32('.') || decPt >= 0 {
break
}
decPt = mantSize
}
p += uintptr(1)
goto _4
_4:
;
mantSize += int32(1)
}
/*
* Now suck up the digits in the mantissa. Use two integers to
* collect 9 digits each (this is faster than using floating-point).
* If the mantissa has more than 18 digits, ignore the extras, since
* they can't affect the value anyway.
*/
pExp = p
p -= uintptr(mantSize)
if decPt < 0 {
decPt = mantSize
} else {
mantSize -= int32(1) /* One of the digits was the point. */
}
if mantSize > int32(18) {
fracExp = decPt - int32(18)
mantSize = int32(18)
} else {
fracExp = decPt - mantSize
}
if mantSize == 0 {
fraction = float64(0)
p = string1
goto done
} else {
frac1 = 0
for {
if !(mantSize > int32(9)) {
break
}
c = int32(*(*int8)(unsafe.Pointer(p)))
p += uintptr(1)
if c == int32('.') {
c = int32(*(*int8)(unsafe.Pointer(p)))
p += uintptr(1)
}
frac1 = int32(10)*frac1 + (c - int32('0'))
goto _5
_5:
;
mantSize -= int32(1)
}
frac2 = 0
for {
if !(mantSize > 0) {
break
}
c = int32(*(*int8)(unsafe.Pointer(p)))
p += uintptr(1)
if c == int32('.') {
c = int32(*(*int8)(unsafe.Pointer(p)))
p += uintptr(1)
}
frac2 = int32(10)*frac2 + (c - int32('0'))
goto _6
_6:
;
mantSize -= int32(1)
}
fraction = float64(1e+09)*float64(float64(frac1)) + float64(float64(frac2))
}
/*
* Skim off the exponent.
*/
p = pExp
if int32(*(*int8)(unsafe.Pointer(p))) == int32('E') || int32(*(*int8)(unsafe.Pointer(p))) == int32('e') {
p += uintptr(1)
if int32(*(*int8)(unsafe.Pointer(p))) == int32('-') {
expSign = int32(TRUE)
p += uintptr(1)
} else {
if int32(*(*int8)(unsafe.Pointer(p))) == int32('+') {
p += uintptr(1)
}
expSign = FALSE
}
for BoolInt32(uint32(*(*int8)(unsafe.Pointer(p)))-uint32('0') < uint32(10)) != 0 {
exp = exp*int32(10) + (int32(*(*int8)(unsafe.Pointer(p))) - int32('0'))
p += uintptr(1)
}
}
if expSign != 0 {
exp = fracExp - exp
} else {
exp = fracExp + exp
}
/*
* Generate a floating-point number that represents the exponent.
* Do this by processing the exponent one bit at a time to combine
* many powers of 2 of 10. Then combine the exponent with the
* fraction.
*/
if exp < 0 {
expSign = int32(TRUE)
exp = -exp
} else {
expSign = FALSE
}
if exp > maxExponent {
exp = maxExponent
*(*int32)(unsafe.Pointer(X__errno_location(tls))) = int32(ERANGE)
}
dblExp = float64(1)
d = uintptr(unsafe.Pointer(&powersOf10))
for {
if !(exp != 0) {
break
}
if exp&int32(01) != 0 {
dblExp *= *(*float64)(unsafe.Pointer(d))
}
goto _7
_7:
;
exp >>= int32(1)
d += uintptr(1) * 8
}
if expSign != 0 {
fraction /= dblExp
} else {
fraction *= dblExp
}
goto done
done:
;
if endPtr != UintptrFromInt32(0) {
*(*uintptr)(unsafe.Pointer(endPtr)) = p
}
if sign != 0 {
return -fraction
}
return fraction
}
var maxExponent = int32(511) /* Largest possible base 10 exponent. Any
* exponent larger than this will already
* produce underflow or overflow, so there's
* no need to worry about additional digits.
*/
var powersOf10 = [9]float64{
0: float64(10),
1: float64(100),
2: float64(10000),
3: float64(1e+08),
4: float64(1e+16),
5: float64(1e+32),
6: float64(1e+64),
7: float64(1e+128),
8: float64(1e+256),
}
// ------------------------------------------------------------------------ (Z)