// 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 (
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
)

const (
	allocatorPageOverhead = 4 * unsafe.Sizeof(int(0))
	stackHeaderSize       = unsafe.Sizeof(stackHeader{})
	stackSegmentSize      = 1<<12 - allocatorPageOverhead
	uintptrSize           = unsafe.Sizeof(uintptr(0))
)

var (
	Covered  = map[uintptr]struct{}{}
	CoveredC = map[string]struct{}{}
	fToken   uintptr
	tid      int32

	atExit   []func()
	atExitMu sync.Mutex

	signals   [signal.NSIG]uintptr
	signalsMu sync.Mutex

	objectMu sync.Mutex
	objects  = map[uintptr]interface{}{}

	tlsBalance int32

	_ = origin
	_ = trc
)

func () {
	if  := stackHeaderSize; %16 != 0 {
		panic(fmt.Errorf("internal error: stackHeaderSize %v == %v (mod 16)", , %16))
	}
}

func ( int) string {
	, , ,  := runtime.Caller()
	 := runtime.FuncForPC()
	var  string
	if  != nil {
		 = .Name()
		if  := strings.LastIndex(, ".");  > 0 {
			 = [+1:]
		}
	}
	return fmt.Sprintf("%s:%d:%s", filepath.Base(), , )
}

func ( string,  ...interface{}) string { //TODO-
	switch {
	case  == "":
		 = fmt.Sprintf(strings.Repeat("%v ", len()), ...)
	default:
		 = fmt.Sprintf(, ...)
	}
	 := fmt.Sprintf("%s: TRC %s", origin(2), )
	fmt.Fprintf(os.Stdout, "%s\n", )
	os.Stdout.Sync()
	return 
}

func ( string,  ...interface{}) string { //TODO-
	switch {
	case  == "":
		 = fmt.Sprintf(strings.Repeat("%v ", len()), ...)
	default:
		 = fmt.Sprintf(, ...)
	}
	 := fmt.Sprintf("%s: TODOTODO %s", origin(2), ) //TODOOK
	if dmesgs {
		dmesg("%s", )
	}
	fmt.Fprintf(os.Stdout, "%s\n", )
	fmt.Fprintf(os.Stdout, "%s\n", debug.Stack()) //TODO-
	os.Stdout.Sync()
	os.Exit(1)
	panic("unrechable")
}

var coverPCs [1]uintptr //TODO not concurrent safe

func () {
	runtime.Callers(2, coverPCs[:])
	Covered[coverPCs[0]] = struct{}{}
}

func ( io.Writer) error {
	var  []string
	 := make([]uintptr, 1)
	for  := range Covered {
		[0] = 
		,  := runtime.CallersFrames().Next()
		 = append(, fmt.Sprintf("%s:%07d:%s", filepath.Base(.File), .Line, .Func.Name()))
	}
	sort.Strings()
	,  := fmt.Fprintf(, "%s\n", strings.Join(, "\n"))
	return 
}

func ( string) {
	CoveredC[] = struct{}{}
}

func ( io.Writer) error {
	var  []string
	for  := range CoveredC {
		 = append(, )
	}
	sort.Strings()
	,  := fmt.Fprintf(, "%s\n", strings.Join(, "\n"))
	return 
}

func () uintptr { return atomic.AddUintptr(&fToken, 1) }

func ( interface{}) uintptr {
	 := token()
	objectMu.Lock()
	objects[] = 
	objectMu.Unlock()
	return 
}

func ( uintptr) interface{} {
	objectMu.Lock()
	 := objects[]
	if  == nil {
		panic(todo("", ))
	}

	objectMu.Unlock()
	return 
}

func ( uintptr) {
	objectMu.Lock()
	if ,  := objects[]; ! {
		panic(todo(""))
	}

	delete(objects, )
	objectMu.Unlock()
}

func ( *TLS) ( interface{}) {
	if memgrind {
		if atomic.SwapInt32(&.reentryGuard, 1) != 0 {
			panic(todo("concurrent use of TLS instance %p", ))
		}

		defer func() {
			if atomic.SwapInt32(&.reentryGuard, 0) != 1 {
				panic(todo("concurrent use of TLS instance %p", ))
			}
		}()
	}
	// if dmesgs {
	// 	dmesg("%v: %T(%v)\n%s", origin(1), err, err, debug.Stack())
	// }
:
	switch x := .(type) {
	case int:
		*(*int32)(unsafe.Pointer(.errnop)) = int32()
	case int32:
		*(*int32)(unsafe.Pointer(.errnop)) = 
	case *os.PathError:
		 = .Err
		goto 
	case syscall.Errno:
		*(*int32)(unsafe.Pointer(.errnop)) = int32()
	case *os.SyscallError:
		 = .Err
		goto 
	default:
		panic(todo("%T", ))
	}
}

// Close frees the resources of t.
func ( *TLS) () {
	.Free(int(unsafe.Sizeof(int32(0))))
	if memgrind {
		if .stackHeaderBalance != 0 {
			panic(todo("non zero stack header balance: %d", .stackHeaderBalance))
		}

		atomic.AddInt32(&tlsBalance, -1)
	}
}

// Alloc allocates n bytes of thread-local storage. It must be paired with a
// call to t.Free(n), using the same n. The order matters. This is ok:
//
//	t.Alloc(11)
//		t.Alloc(22)
//		t.Free(22)
//	t.Free(11)
//
// This is not correct:
//
//	t.Alloc(11)
//		t.Alloc(22)
//		t.Free(11)
//	t.Free(22)
func ( *TLS) ( int) ( uintptr) {
	if memgrind {
		if atomic.SwapInt32(&.reentryGuard, 1) != 0 {
			panic(todo("concurrent use of TLS instance %p", ))
		}

		defer func() {
			if atomic.SwapInt32(&.reentryGuard, 0) != 1 {
				panic(todo("concurrent use of TLS instance %p", ))
			}
		}()
	}
	 += 15
	 &^= 15
	if .stack.free >=  {
		 = .stack.sp
		.stack.free -= 
		.stack.sp += uintptr()
		return 
	}
	//if we have a next stack
	if  := .stack.next;  != 0 {
		if (*stackHeader)(unsafe.Pointer()).free >=  {
			*(*stackHeader)(unsafe.Pointer(.stack.page)) = .stack
			.stack = *(*stackHeader)(unsafe.Pointer())
			 = .stack.sp
			.stack.free -= 
			.stack.sp += uintptr()
			return 
		}
		 := *(*stackHeader)(unsafe.Pointer(.stack.next))
		for ; ;  = *(*stackHeader)(unsafe.Pointer(.next)) {
			if memgrind {
				if atomic.AddInt32(&.stackHeaderBalance, -1) < 0 {
					panic(todo("negative stack header balance"))
				}
			}
			Xfree(, .page)
			if .next == 0 {
				break
			}
		}
		.stack.next = 0
	}

	if .stack.page != 0 {
		*(*stackHeader)(unsafe.Pointer(.stack.page)) = .stack
	}

	 :=  + int(stackHeaderSize)
	if %int(stackSegmentSize) != 0 {
		 -=  % int(stackSegmentSize)
		 += int(stackSegmentSize)
	}
	.stack.free =  - int(stackHeaderSize)
	.stack.prev = .stack.page

	 += 15
	 &^= 15
	.stack.page = Xmalloc(, types.Size_t())
	if .stack.page == 0 {
		panic("OOM")
	}

	if memgrind {
		atomic.AddInt32(&.stackHeaderBalance, 1)
	}
	.stack.sp = .stack.page + stackHeaderSize

	 = .stack.sp
	.stack.free -= 
	.stack.sp += uintptr()
	if .stack.prev != 0 {
		(*stackHeader)(unsafe.Pointer(.stack.prev)).next = .stack.page
	}

	return 
}

//this declares how many stack frames are kept alive before being freed
const stackFrameKeepalive = 2

// Free deallocates n bytes of thread-local storage. See TLS.Alloc for details
// on correct usage.
func ( *TLS) ( int) {
	if memgrind {
		if atomic.SwapInt32(&.reentryGuard, 1) != 0 {
			panic(todo("concurrent use of TLS instance %p", ))
		}

		defer func() {
			if atomic.SwapInt32(&.reentryGuard, 0) != 1 {
				panic(todo("concurrent use of TLS instance %p", ))
			}
		}()
	}
	 += 15
	 &^= 15
	.stack.free += 
	.stack.sp -= uintptr()
	if .stack.sp != .stack.page+stackHeaderSize {
		return
	}

	 := .stack

	//if we are the first one, just free all of them
	if .stack.prev == 0 {
		for ; ;  = *(*stackHeader)(unsafe.Pointer(.next)) {
			if memgrind {
				if atomic.AddInt32(&.stackHeaderBalance, -1) < 0 {
					panic(todo("negative stack header balance"))
				}
			}
			Xfree(, .page)
			if .next == 0 {
				break
			}
		}
		.stack = stackHeader{}
		return
	}

	//look if we are in the last n stackframes (n=stackFrameKeepalive)
	//if we find something just return and set the current stack pointer to the previous one
	for  := 0;  < stackFrameKeepalive; ++ {
		if .next == 0 {
			*((*stackHeader)(unsafe.Pointer(.stack.page))) = .stack
			.stack = *(*stackHeader)(unsafe.Pointer(.stack.prev))
			return
		}
		 = *(*stackHeader)(unsafe.Pointer(.next))
	}

	//else only free the last
	if memgrind {
		if atomic.AddInt32(&.stackHeaderBalance, -1) < 0 {
			panic(todo("negative stack header balance"))
		}
	}
	Xfree(, .page)
	(*stackHeader)(unsafe.Pointer(.prev)).next = 0
	*(*stackHeader)(unsafe.Pointer(.stack.page)) = .stack
	.stack = *(*stackHeader)(unsafe.Pointer(.stack.prev))
}

type stackHeader struct {
	free int     // bytes left in page
	page uintptr // stack page
	prev uintptr // prev stack page = prev stack header
	next uintptr // next stack page = next stack header
	sp   uintptr // next allocation address
	_    stackHeaderPadding
}

func ( *TLS,  string) uintptr { //TODO-
	 := len()
	 := Xmalloc(, types.Size_t()+1)
	if  == 0 {
		panic("OOM")
	}

	copy((*RawMem)(unsafe.Pointer())[::], )
	*(*byte)(unsafe.Pointer( + uintptr())) = 0
	return 
}

// VaList fills a varargs list at p with args and returns uintptr(p).  The list
// must have been allocated by caller and it must not be in Go managed
// memory, ie. it must be pinned. Caller is responsible for freeing the list.
//
// Individual arguments must be one of int, uint, int32, uint32, int64, uint64,
// float64, uintptr or Intptr. Other types will panic.
//
// Note: The C translated to Go varargs ABI alignment for all types is 8 at all
// architectures.
func ( uintptr,  ...interface{}) ( uintptr) {
	if &7 != 0 {
		panic("internal error")
	}

	 = 
	for ,  := range  {
		switch x := .(type) {
		case int:
			*(*int64)(unsafe.Pointer()) = int64()
		case int32:
			*(*int64)(unsafe.Pointer()) = int64()
		case int64:
			*(*int64)(unsafe.Pointer()) = 
		case uint:
			*(*uint64)(unsafe.Pointer()) = uint64()
		case uint16:
			*(*uint64)(unsafe.Pointer()) = uint64()
		case uint32:
			*(*uint64)(unsafe.Pointer()) = uint64()
		case uint64:
			*(*uint64)(unsafe.Pointer()) = 
		case float64:
			*(*float64)(unsafe.Pointer()) = 
		case uintptr:
			*(*uintptr)(unsafe.Pointer()) = 
		default:
			panic(todo("invalid VaList argument type: %T", ))
		}
		 += 8
	}
	return 
}

func ( *uintptr) int32 {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := int32(*(*int64)(unsafe.Pointer()))
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return 
}

func ( *uintptr) uint32 {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := uint32(*(*uint64)(unsafe.Pointer()))
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return 
}

func ( *uintptr) int64 {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := *(*int64)(unsafe.Pointer())
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return 
}

func ( *uintptr) uint64 {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := *(*uint64)(unsafe.Pointer())
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return 
}

func ( *uintptr) float32 {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := *(*float64)(unsafe.Pointer())
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return float32()
}

func ( *uintptr) float64 {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := *(*float64)(unsafe.Pointer())
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return 
}

func ( *uintptr) uintptr {
	 := *(*uintptr)(unsafe.Pointer())
	if  == 0 {
		return 0
	}

	 = roundup(, 8)
	 := *(*uintptr)(unsafe.Pointer())
	 += 8
	*(*uintptr)(unsafe.Pointer()) = 
	return 
}

func (,  uintptr) uintptr {
	if  :=  % ;  != 0 {
		return  +  - 
	}

	return 
}

func ( uintptr) string {
	if  == 0 {
		return ""
	}

	var  []byte
	for {
		 := *(*byte)(unsafe.Pointer())
		if  == 0 {
			return string()
		}

		 = append(, )
		++
	}
}

// GoBytes returns a byte slice from a C char* having length len bytes.
func ( uintptr,  int) []byte {
	if  == 0 {
		return nil
	}

	return (*RawMem)(unsafe.Pointer())[::]
}

func ( bool) int32 {
	if  {
		return 1
	}

	return 0
}

func ( bool) int64 {
	if  {
		return 1
	}

	return 0
}

type sorter struct {
	len  int
	base uintptr
	sz   uintptr
	f    func(*TLS, uintptr, uintptr) int32
	t    *TLS
}

func ( *sorter) () int { return .len }

func ( *sorter) (,  int) bool {
	return .f(.t, .base+uintptr()*.sz, .base+uintptr()*.sz) < 0
}

func ( *sorter) (,  int) {
	 := uintptr(.base + uintptr()*.sz)
	 := uintptr(.base + uintptr()*.sz)
	for  := 0;  < int(.sz); ++ {
		*(*byte)(unsafe.Pointer()), *(*byte)(unsafe.Pointer()) = *(*byte)(unsafe.Pointer()), *(*byte)(unsafe.Pointer())
		++
		++
	}
}

func ( string) (uintptr, error) {
	 := len()
	 := Xmalloc(nil, types.Size_t()+1)
	if  == 0 {
		return 0, fmt.Errorf("CString: cannot allocate %d bytes", +1)
	}

	copy((*RawMem)(unsafe.Pointer())[::], )
	*(*byte)(unsafe.Pointer( + uintptr())) = 0
	return , nil
}

func () ( []string) {
	for  := Environ(); ;  += unsafe.Sizeof() {
		 := *(*uintptr)(unsafe.Pointer())
		if  == 0 {
			return 
		}

		 = append(, GoString())
	}
}

func ( *TLS,  uintptr,  int32) (,  bool,  uintptr,  uint64,  int32) {
	var  byte
:
	for {
		 = *(*byte)(unsafe.Pointer())
		switch  {
		case ' ', '\t', '\n', '\r', '\v', '\f':
			++
		case '+':
			++
			break 
		case '-':
			++
			 = true
			break 
		default:
			break 
		}
	}
	for {
		 = *(*byte)(unsafe.Pointer())
		var  uint64
		switch  {
		case 10:
			switch {
			case  >= '0' &&  <= '9':
				 = true
				 = uint64() - '0'
			default:
				return , , , , 0
			}
		case 16:
			if  >= 'A' &&  <= 'F' {
				 =  + ('a' - 'A')
			}
			switch {
			case  >= '0' &&  <= '9':
				 = true
				 = uint64() - '0'
			case  >= 'a' &&  <= 'f':
				 = true
				 = uint64() - 'a' + 10
			default:
				return , , , , 0
			}
		default:
			panic(todo("", ))
		}
		 := 
		 = uint64()* + 
		if  <  { // overflow
			return , , , , errno.ERANGE
		}

		++
	}
}

func ( *TLS,  uintptr,  int) ( float64,  int32) {
	var  []byte
	var  bool

	defer func() {
		var  error
		if ,  = strconv.ParseFloat(string(), );  != nil {
			panic(todo(""))
		}

		if  {
			 = -
		}
	}()

	var  byte
:
	for {
		 = *(*byte)(unsafe.Pointer())
		switch  {
		case ' ', '\t', '\n', '\r', '\v', '\f':
			++
		case '+':
			++
			break 
		case '-':
			++
			 = true
			break 
		default:
			break 
		}
	}
	for {
		 = *(*byte)(unsafe.Pointer())
		switch {
		case  >= '0' &&  <= '9':
			 = append(, )
		case  == '.':
			 = append(, )
			++
			for {
				 = *(*byte)(unsafe.Pointer())
				switch {
				case  >= '0' &&  <= '9':
					 = append(, )
				case  == 'e' ||  == 'E':
					 = append(, )
					++
					for {
						 = *(*byte)(unsafe.Pointer())
						switch {
						case  == '+' ||  == '-':
							 = append(, )
							++
							for {
								 = *(*byte)(unsafe.Pointer())
								switch {
								case  >= '0' &&  <= '9':
									 = append(, )
								default:
									return
								}

								++
							}
						default:
							panic(todo("%q %q", , string()))
						}
					}
				default:
					return
				}

				++
			}
		default:
			panic(todo("%q %q", , string()))
		}

		++
	}
}

func ( string) ( string,  int) {
	_, , , _ = parseZoneOffset(, false)
	return , 
}

func ( string,  bool) (string, string, int, bool) {
	 := 
	 := 
	for len() != 0 {
		switch  := [0]; {
		case  >= 'A' &&  <= 'Z',  >= 'a' &&  <= 'z',  == '_',  == '/':
			 = [1:]
		default:
			 = [:len()-len()]
			if len() < 3 {
				panic(todo("%q", ))
			}

			if  {
				if len() == 0 {
					return "", , 0, false
				}

				if  := [0]; ( < '0' ||  > '9') &&  != '+' &&  != '-' {
					return , , 0, false
				}
			}

			,  := parseOffset()
			return , , , true
		}
	}
	return "", , 0, true
}

//  [+|-]hh[:mm[:ss]]
func ( string) (string, int) {
	if len() == 0 {
		panic(todo(""))
	}

	 := 1
	switch [0] {
	case '+':
		// nop
		 = [1:]
	case '-':
		 = -1
		 = [1:]
	}
	, ,  := parseUint()
	if ! {
		panic(todo(""))
	}

	 :=  * 3600
	if len() == 0 || [0] != ':' {
		return ,  * 
	}

	 = [1:] // ':'
	if len() == 0 {
		panic(todo(""))
	}

	, ,  := parseUint()
	if ! {
		panic(todo(""))
	}

	 +=  * 60
	if len() == 0 || [0] != ':' {
		return ,  * 
	}

	 = [1:] // ':'
	if len() == 0 {
		panic(todo(""))
	}

	, ,  := parseUint()
	return ,  * ( + )
}

func ( string) (string, int, bool) {
	var  bool
	var  int
	for len() != 0 {
		switch  := [0]; {
		case  >= '0' &&  <= '9':
			 = true
			 := 
			 = 10* + int() - '0'
			if  <  {
				panic(todo(""))
			}

			 = [1:]
		default:
			return , , 
		}
	}
	return , , 
}

// https://stackoverflow.com/a/53052382
//
// isTimeDST returns true if time t occurs within daylight saving time
// for its time zone.
func ( time.Time) bool {
	// If the most recent (within the last year) clock change
	// was forward then assume the change was from std to dst.
	, ,  := .UTC().Clock()
	 := *60 + 
	for  := -1;  > -12; -- {
		// assume dst lasts for at least one month
		, ,  := .AddDate(0, , 0).UTC().Clock()
		 := *60 + 
		if  !=  {
			return  > 
		}
	}
	// assume no dst
	return false
}