runtime: testing runtime
This commit is contained in:
@@ -536,6 +536,9 @@ source_filename = "main"
|
|||||||
%s
|
%s
|
||||||
declare void @"%s.init"()
|
declare void @"%s.init"()
|
||||||
declare void @"%s.main"()
|
declare void @"%s.main"()
|
||||||
|
define weak void @runtime.init() {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
; TODO(lijie): workaround for syscall patch
|
; TODO(lijie): workaround for syscall patch
|
||||||
define weak void @"syscall.init"() {
|
define weak void @"syscall.init"() {
|
||||||
@@ -548,6 +551,7 @@ _llgo_0:
|
|||||||
store i32 %%0, ptr @__llgo_argc, align 4
|
store i32 %%0, ptr @__llgo_argc, align 4
|
||||||
store ptr %%1, ptr @__llgo_argv, align 8
|
store ptr %%1, ptr @__llgo_argv, align 8
|
||||||
%s
|
%s
|
||||||
|
call void @runtime.init()
|
||||||
call void @"%s.init"()
|
call void @"%s.init"()
|
||||||
call void @"%s.main"()
|
call void @"%s.main"()
|
||||||
ret i32 0
|
ret i32 0
|
||||||
@@ -893,14 +897,16 @@ var hasAltPkg = map[string]none{
|
|||||||
"crypto/sha256": {},
|
"crypto/sha256": {},
|
||||||
"crypto/sha512": {},
|
"crypto/sha512": {},
|
||||||
"crypto/subtle": {},
|
"crypto/subtle": {},
|
||||||
"fmt": {},
|
|
||||||
"go/parser": {},
|
"go/parser": {},
|
||||||
"hash/crc32": {},
|
"hash/crc32": {},
|
||||||
"internal/abi": {},
|
"internal/abi": {},
|
||||||
"internal/bytealg": {},
|
"internal/bytealg": {},
|
||||||
|
"internal/cpu": {},
|
||||||
"internal/itoa": {},
|
"internal/itoa": {},
|
||||||
"internal/filepathlite": {},
|
"internal/filepathlite": {},
|
||||||
|
"internal/godebug": {},
|
||||||
"internal/oserror": {},
|
"internal/oserror": {},
|
||||||
|
"internal/poll": {},
|
||||||
"internal/race": {},
|
"internal/race": {},
|
||||||
"internal/reflectlite": {},
|
"internal/reflectlite": {},
|
||||||
"internal/stringslite": {},
|
"internal/stringslite": {},
|
||||||
@@ -917,7 +923,12 @@ var hasAltPkg = map[string]none{
|
|||||||
"time": {},
|
"time": {},
|
||||||
"os": {},
|
"os": {},
|
||||||
"os/exec": {},
|
"os/exec": {},
|
||||||
|
"os/signal": {},
|
||||||
"runtime": {},
|
"runtime": {},
|
||||||
|
"runtime/debug": {},
|
||||||
|
"runtime/pprof": {},
|
||||||
|
"runtime/trace": {},
|
||||||
|
"runtime/internal/syscall": {},
|
||||||
"io": {},
|
"io": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
runtime/internal/clite/libuv/README.md
Normal file
44
runtime/internal/clite/libuv/README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
LLGo wrapper of libuv
|
||||||
|
=====
|
||||||
|
|
||||||
|
## How to install
|
||||||
|
|
||||||
|
### on macOS (Homebrew)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install libuv
|
||||||
|
```
|
||||||
|
|
||||||
|
### on Linux (Debian/Ubuntu)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apt-get install -y libuv1-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### on Linux (CentOS/RHEL)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yum install -y libuv-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
### on Linux (Arch Linux)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pacman -S libuv
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demos
|
||||||
|
|
||||||
|
The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it):
|
||||||
|
|
||||||
|
* [async_fs](_demo/async_fs/async_fs.go): a simple async file read demo
|
||||||
|
* [echo_server](_demo/echo_server/echo_server.go): a basic async tcp echo server
|
||||||
|
|
||||||
|
### How to run demos
|
||||||
|
|
||||||
|
To run the demos in directory `_demo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _demo/sqlitedemo
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
41
runtime/internal/clite/libuv/_demo/async/async.go
Normal file
41
runtime/internal/clite/libuv/_demo/async/async.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/libuv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ensure(b bool, msg string) {
|
||||||
|
if !b {
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
loop := libuv.LoopNew()
|
||||||
|
defer loop.Close()
|
||||||
|
|
||||||
|
a := &libuv.Async{}
|
||||||
|
r := loop.Async(a, func(a *libuv.Async) {
|
||||||
|
println("async callback")
|
||||||
|
a.Close(nil) // or loop.Stop()
|
||||||
|
})
|
||||||
|
ensure(r == 0, "Async failed")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
println("begin async task")
|
||||||
|
c.Usleep(100 * 1000)
|
||||||
|
println("send async event")
|
||||||
|
ensure(a.Send() == 0, "Send failed")
|
||||||
|
}()
|
||||||
|
|
||||||
|
loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
println("done")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Expected Output:
|
||||||
|
begin async task
|
||||||
|
send async event
|
||||||
|
async callback
|
||||||
|
done
|
||||||
|
*/
|
||||||
116
runtime/internal/clite/libuv/_demo/async_fs/async_fs.go
Normal file
116
runtime/internal/clite/libuv/_demo/async_fs/async_fs.go
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/libuv"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const BUFFER_SIZE = 1024
|
||||||
|
|
||||||
|
var (
|
||||||
|
loop *libuv.Loop
|
||||||
|
openReq libuv.Fs
|
||||||
|
closeReq libuv.Fs
|
||||||
|
|
||||||
|
buffer [BUFFER_SIZE]c.Char
|
||||||
|
iov libuv.Buf
|
||||||
|
file libuv.File
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Print the libuv version
|
||||||
|
c.Printf(c.Str("libuv version: %d\n"), libuv.Version())
|
||||||
|
|
||||||
|
// Initialize the loop
|
||||||
|
loop = libuv.DefaultLoop()
|
||||||
|
|
||||||
|
// Open the file
|
||||||
|
libuv.FsOpen(loop, &openReq, c.Str("example.txt"), os.O_RDONLY, 0, onOpen)
|
||||||
|
|
||||||
|
// Run the loop
|
||||||
|
result := loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
|
||||||
|
if result != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Error in Run: %s\n"), libuv.Strerror(libuv.Errno(result)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
defer cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func onOpen(req *libuv.Fs) {
|
||||||
|
// Check for errors
|
||||||
|
if req.GetResult() < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Error opening file: %s\n"), libuv.Strerror(libuv.Errno(req.GetResult())))
|
||||||
|
loop.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the file descriptor
|
||||||
|
file = libuv.File(req.GetResult())
|
||||||
|
|
||||||
|
// Init buffer
|
||||||
|
iov = libuv.InitBuf((*c.Char)(unsafe.Pointer(&buffer[0])), c.Uint(unsafe.Sizeof(buffer)))
|
||||||
|
|
||||||
|
// Read the file
|
||||||
|
readFile()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func readFile() {
|
||||||
|
// Initialize the request every time
|
||||||
|
var readReq libuv.Fs
|
||||||
|
|
||||||
|
// Read the file
|
||||||
|
readRes := libuv.FsRead(loop, &readReq, file, &iov, 1, -1, onRead)
|
||||||
|
if readRes != 0 {
|
||||||
|
c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(readRes)), readRes)
|
||||||
|
readReq.ReqCleanup()
|
||||||
|
loop.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func onRead(req *libuv.Fs) {
|
||||||
|
// Cleanup the request
|
||||||
|
defer req.ReqCleanup()
|
||||||
|
// Check for errors
|
||||||
|
if req.GetResult() < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(libuv.Errno(req.GetResult())))
|
||||||
|
} else if req.GetResult() == 0 {
|
||||||
|
// Close the file
|
||||||
|
closeRes := libuv.FsClose(loop, &closeReq, libuv.File(openReq.GetResult()), onClose)
|
||||||
|
if closeRes != 0 {
|
||||||
|
c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(closeRes)), closeRes)
|
||||||
|
loop.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("Read %d bytes\n"), req.GetResult())
|
||||||
|
c.Printf(c.Str("Read content: %.*s\n"), req.GetResult(), (*c.Char)(unsafe.Pointer(&buffer[0])))
|
||||||
|
// Read the file again
|
||||||
|
readFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func onClose(req *libuv.Fs) {
|
||||||
|
// Check for errors
|
||||||
|
if req.GetResult() < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Error closing file: %s\n"), libuv.Strerror(libuv.Errno(req.GetResult())))
|
||||||
|
} else {
|
||||||
|
c.Printf(c.Str("\nFile closed successfully.\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanup() {
|
||||||
|
// Cleanup the requests
|
||||||
|
openReq.ReqCleanup()
|
||||||
|
closeReq.ReqCleanup()
|
||||||
|
// Close the loop
|
||||||
|
result := loop.Close()
|
||||||
|
if result != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Error in LoopClose: %s\n"), libuv.Strerror(libuv.Errno(result)))
|
||||||
|
}
|
||||||
|
}
|
||||||
1
runtime/internal/clite/libuv/_demo/async_fs/example.txt
Executable file
1
runtime/internal/clite/libuv/_demo/async_fs/example.txt
Executable file
@@ -0,0 +1 @@
|
|||||||
|
123
|
||||||
112
runtime/internal/clite/libuv/_demo/echo_server/echo_server.go
Normal file
112
runtime/internal/clite/libuv/_demo/echo_server/echo_server.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/libuv"
|
||||||
|
"github.com/goplus/llgo/c/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DEFAULT_PORT c.Int = 8080
|
||||||
|
var DEFAULT_BACKLOG c.Int = 128
|
||||||
|
|
||||||
|
type WriteReq struct {
|
||||||
|
Req libuv.Write
|
||||||
|
Buf libuv.Buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialize the default event loop
|
||||||
|
var loop = libuv.DefaultLoop()
|
||||||
|
|
||||||
|
// Initialize a TCP server
|
||||||
|
server := &libuv.Tcp{}
|
||||||
|
libuv.InitTcp(loop, server)
|
||||||
|
|
||||||
|
// Set up the address to bind the server to
|
||||||
|
var addr net.SockaddrIn
|
||||||
|
libuv.Ip4Addr(c.Str("0.0.0.0"), DEFAULT_PORT, &addr)
|
||||||
|
c.Printf(c.Str("Listening on %s:%d\n"), c.Str("0.0.0.0"), DEFAULT_PORT)
|
||||||
|
|
||||||
|
// Bind the server to the specified address and port
|
||||||
|
server.Bind((*net.SockAddr)(c.Pointer(&addr)), 0)
|
||||||
|
res := (*libuv.Stream)(server).Listen(DEFAULT_BACKLOG, OnNewConnection)
|
||||||
|
if res != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Listen error: %s\n"), libuv.Strerror(libuv.Errno(res)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening for incoming connections
|
||||||
|
loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FreeWriteReq(req *libuv.Write) {
|
||||||
|
wr := (*WriteReq)(c.Pointer(req))
|
||||||
|
// Free the buffer base.
|
||||||
|
if wr.Buf.Base != nil {
|
||||||
|
c.Free(c.Pointer(wr.Buf.Base))
|
||||||
|
wr.Buf.Base = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) {
|
||||||
|
// Allocate memory for the buffer based on the suggested size.
|
||||||
|
buf.Base = (*c.Char)(c.Malloc(suggestedSize))
|
||||||
|
buf.Len = suggestedSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoWrite(req *libuv.Write, status c.Int) {
|
||||||
|
if status != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Write error: %s\n"), libuv.Strerror(libuv.Errno(status)))
|
||||||
|
}
|
||||||
|
FreeWriteReq(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoRead(client *libuv.Stream, nread c.Long, buf *libuv.Buf) {
|
||||||
|
if nread > 0 {
|
||||||
|
req := new(WriteReq)
|
||||||
|
// Initialize the buffer with the data read.
|
||||||
|
req.Buf = libuv.InitBuf(buf.Base, c.Uint(nread))
|
||||||
|
// Write the data back to the client.
|
||||||
|
req.Req.Write(client, &req.Buf, 1, EchoWrite)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if nread < 0 {
|
||||||
|
// Handle read errors and EOF.
|
||||||
|
if (libuv.Errno)(nread) != libuv.EOF {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(libuv.Errno(nread)))
|
||||||
|
}
|
||||||
|
(*libuv.Handle)(c.Pointer(client)).Close(nil)
|
||||||
|
}
|
||||||
|
// Free the buffer if it's no longer needed.
|
||||||
|
if buf.Base != nil {
|
||||||
|
c.Free(c.Pointer(buf.Base))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnNewConnection(server *libuv.Stream, status c.Int) {
|
||||||
|
if status < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("New connection error: %s\n"), libuv.Strerror(libuv.Errno(status)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory for a new client.
|
||||||
|
client := &libuv.Tcp{}
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for client\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the client TCP handle.
|
||||||
|
if libuv.InitTcp(libuv.DefaultLoop(), client) < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to initialize client\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept the new connection and start reading data.
|
||||||
|
if server.Accept((*libuv.Stream)(client)) == 0 {
|
||||||
|
(*libuv.Stream)(client).StartRead(AllocBuffer, EchoRead)
|
||||||
|
} else {
|
||||||
|
(*libuv.Handle)(c.Pointer(client)).Close(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
5
runtime/internal/clite/libuv/_wrap/libuv.c
Normal file
5
runtime/internal/clite/libuv/_wrap/libuv.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
int uv_tcp_get_io_watcher_fd (uv_tcp_t* handle) {
|
||||||
|
return handle->io_watcher.fd;
|
||||||
|
}
|
||||||
50
runtime/internal/clite/libuv/async.go
Normal file
50
runtime/internal/clite/libuv/async.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
// struct uv_async_t
|
||||||
|
type Async struct {
|
||||||
|
Handle
|
||||||
|
// On macOS arm64, sizeof uv_async_t is 128 bytes.
|
||||||
|
// Handle is 92 bytes, so we need 36 bytes to fill the gap.
|
||||||
|
// Maybe reserve more for future use.
|
||||||
|
Unused [36]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef void (*uv_async_cb)(uv_async_t* handle);
|
||||||
|
// llgo:type C
|
||||||
|
type AsyncCb func(*Async)
|
||||||
|
|
||||||
|
// int uv_async_init(uv_loop_t*, uv_async_t* async, uv_async_cb async_cb);
|
||||||
|
//
|
||||||
|
// llgo:link (*Loop).Async C.uv_async_init
|
||||||
|
func (loop *Loop) Async(a *Async, cb AsyncCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// int uv_async_send(uv_async_t* async);
|
||||||
|
//
|
||||||
|
// llgo:link (*Async).Send C.uv_async_send
|
||||||
|
func (a *Async) Send() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
27
runtime/internal/clite/libuv/check.go
Normal file
27
runtime/internal/clite/libuv/check.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Check struct {
|
||||||
|
Unused [120]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type CheckCb func(Check *Check)
|
||||||
|
|
||||||
|
//go:linkname InitCheck C.uv_check_init
|
||||||
|
func InitCheck(loop *Loop, Check *Check) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Check).Start C.uv_check_start
|
||||||
|
func (Check *Check) Start(CheckCb CheckCb) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*Check).Stop C.uv_check_stop
|
||||||
|
func (Check *Check) Stop() c.Int { return 0 }
|
||||||
118
runtime/internal/clite/libuv/error.go
Normal file
118
runtime/internal/clite/libuv/error.go
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/net"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
E2BIG = Errno(syscall.E2BIG)
|
||||||
|
EACCES = Errno(syscall.EACCES)
|
||||||
|
EADDRINUSE = Errno(syscall.EADDRINUSE)
|
||||||
|
EADDRNOTAVAIL = Errno(syscall.EADDRNOTAVAIL)
|
||||||
|
EAFNOSUPPORT = Errno(syscall.EAFNOSUPPORT)
|
||||||
|
EAGAIN = Errno(syscall.EAGAIN)
|
||||||
|
EALREADY = Errno(syscall.EALREADY)
|
||||||
|
EBADF = Errno(syscall.EBADF)
|
||||||
|
EBUSY = Errno(syscall.EBUSY)
|
||||||
|
ECANCELED = Errno(syscall.ECANCELED)
|
||||||
|
ECONNABORTED = Errno(syscall.ECONNABORTED)
|
||||||
|
ECONNREFUSED = Errno(syscall.ECONNREFUSED)
|
||||||
|
ECONNRESET = Errno(syscall.ECONNRESET)
|
||||||
|
EDESTADDRREQ = Errno(syscall.EDESTADDRREQ)
|
||||||
|
EEXIST = Errno(syscall.EEXIST)
|
||||||
|
EFAULT = Errno(syscall.EFAULT)
|
||||||
|
EFBIG = Errno(syscall.EFBIG)
|
||||||
|
EHOSTUNREACH = Errno(syscall.EHOSTUNREACH)
|
||||||
|
EINTR = Errno(syscall.EINTR)
|
||||||
|
EINVAL = Errno(syscall.EINVAL)
|
||||||
|
EIO = Errno(syscall.EIO)
|
||||||
|
EISCONN = Errno(syscall.EISCONN)
|
||||||
|
EISDIR = Errno(syscall.EISDIR)
|
||||||
|
ELOOP = Errno(syscall.ELOOP)
|
||||||
|
EMFILE = Errno(syscall.EMFILE)
|
||||||
|
EMSGSIZE = Errno(syscall.EMSGSIZE)
|
||||||
|
ENAMETOOLONG = Errno(syscall.ENAMETOOLONG)
|
||||||
|
ENETDOWN = Errno(syscall.ENETDOWN)
|
||||||
|
ENETUNREACH = Errno(syscall.ENETUNREACH)
|
||||||
|
ENFILE = Errno(syscall.ENFILE)
|
||||||
|
ENOBUFS = Errno(syscall.ENOBUFS)
|
||||||
|
ENODEV = Errno(syscall.ENODEV)
|
||||||
|
ENOENT = Errno(syscall.ENOENT)
|
||||||
|
ENOMEM = Errno(syscall.ENOMEM)
|
||||||
|
ENOPROTOOPT = Errno(syscall.ENOPROTOOPT)
|
||||||
|
ENOSPC = Errno(syscall.ENOSPC)
|
||||||
|
ENOSYS = Errno(syscall.ENOSYS)
|
||||||
|
ENOTCONN = Errno(syscall.ENOTCONN)
|
||||||
|
ENOTDIR = Errno(syscall.ENOTDIR)
|
||||||
|
ENOTEMPTY = Errno(syscall.ENOTEMPTY)
|
||||||
|
ENOTSOCK = Errno(syscall.ENOTSOCK)
|
||||||
|
ENOTSUP = Errno(syscall.ENOTSUP)
|
||||||
|
EOVERFLOW = Errno(syscall.EOVERFLOW)
|
||||||
|
EPERM = Errno(syscall.EPERM)
|
||||||
|
EPIPE = Errno(syscall.EPIPE)
|
||||||
|
EPROTO = Errno(syscall.EPROTO)
|
||||||
|
EPROTONOSUPPORT = Errno(syscall.EPROTONOSUPPORT)
|
||||||
|
EPROTOTYPE = Errno(syscall.EPROTOTYPE)
|
||||||
|
ERANGE = Errno(syscall.ERANGE)
|
||||||
|
EROFS = Errno(syscall.EROFS)
|
||||||
|
ESHUTDOWN = Errno(syscall.ESHUTDOWN)
|
||||||
|
ESPIPE = Errno(syscall.ESPIPE)
|
||||||
|
ESRCH = Errno(syscall.ESRCH)
|
||||||
|
ETIMEDOUT = Errno(syscall.ETIMEDOUT)
|
||||||
|
ETXTBSY = Errno(syscall.ETXTBSY)
|
||||||
|
EXDEV = Errno(syscall.EXDEV)
|
||||||
|
ENXIO = Errno(syscall.ENXIO)
|
||||||
|
EMLINK = Errno(syscall.EMLINK)
|
||||||
|
EHOSTDOWN = Errno(syscall.EHOSTDOWN)
|
||||||
|
ENOTTY = Errno(syscall.ENOTTY)
|
||||||
|
//EFTYPE = Errno(syscall.EFTYPE)
|
||||||
|
EILSEQ = Errno(syscall.EILSEQ)
|
||||||
|
ESOCKTNOSUPPORT = Errno(syscall.ESOCKTNOSUPPORT)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EAI_ADDRFAMILY = Errno(net.EAI_ADDRFAMILY)
|
||||||
|
EAI_AGAIN = Errno(net.EAI_AGAIN)
|
||||||
|
EAI_BADFLAGS = Errno(net.EAI_BADFLAGS)
|
||||||
|
EAI_BADHINTS = Errno(net.EAI_BADHINTS)
|
||||||
|
EAI_FAIL = Errno(net.EAI_FAIL)
|
||||||
|
EAI_FAMILY = Errno(net.EAI_FAMILY)
|
||||||
|
EAI_MEMORY = Errno(net.EAI_MEMORY)
|
||||||
|
EAI_NODATA = Errno(net.EAI_NODATA)
|
||||||
|
EAI_NONAME = Errno(net.EAI_NONAME)
|
||||||
|
EAI_OVERFLOW = Errno(net.EAI_OVERFLOW)
|
||||||
|
EAI_PROTOCOL = Errno(net.EAI_PROTOCOL)
|
||||||
|
EAI_SERVICE = Errno(net.EAI_SERVICE)
|
||||||
|
EAI_SOCKTYPE = Errno(net.EAI_SOCKTYPE)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EAI_CANCELED Errno = -3003
|
||||||
|
ECHARSET Errno = -4080
|
||||||
|
ENONET Errno = -4056
|
||||||
|
UNKNOWN Errno = -4094
|
||||||
|
EOF Errno = -4095
|
||||||
|
EREMOTEIO Errno = -4030
|
||||||
|
ERRNO_MAX Errno = EOF - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type Errno c.Int
|
||||||
|
|
||||||
|
//go:linkname TranslateSysError C.uv_translate_sys_error
|
||||||
|
func TranslateSysError(sysErrno c.Int) Errno
|
||||||
|
|
||||||
|
//go:linkname Strerror C.uv_strerror
|
||||||
|
func Strerror(err Errno) *c.Char
|
||||||
|
|
||||||
|
//go:linkname StrerrorR C.uv_strerror_r
|
||||||
|
func StrerrorR(err Errno, buf *c.Char, bufLen uintptr) *c.Char
|
||||||
|
|
||||||
|
//go:linkname ErrName C.uv_err_name
|
||||||
|
func ErrName(err Errno) *c.Char
|
||||||
|
|
||||||
|
//go:linkname ErrNameR C.uv_err_name_r
|
||||||
|
func ErrNameR(err Errno, buf *c.Char, bufLen uintptr) *c.Char
|
||||||
307
runtime/internal/clite/libuv/fs.go
Normal file
307
runtime/internal/clite/libuv/fs.go
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FS_UNKNOWN FsType = -1
|
||||||
|
FS_CUSTOM FsType = 0
|
||||||
|
FS_OPEN FsType = 1
|
||||||
|
FS_CLOSE FsType = 2
|
||||||
|
FS_READ FsType = 3
|
||||||
|
FS_WRITE FsType = 4
|
||||||
|
FS_SENDFILE FsType = 5
|
||||||
|
FS_STAT FsType = 6
|
||||||
|
FS_LSTAT FsType = 7
|
||||||
|
FS_FSTAT FsType = 8
|
||||||
|
FS_FTRUNCATE FsType = 9
|
||||||
|
FS_UTIME FsType = 10
|
||||||
|
FS_FUTIME FsType = 11
|
||||||
|
FS_ACCESS FsType = 12
|
||||||
|
FS_CHMOD FsType = 13
|
||||||
|
FS_FCHMOD FsType = 14
|
||||||
|
FS_FSYNC FsType = 15
|
||||||
|
FS_FDATASYNC FsType = 16
|
||||||
|
FS_UNLINK FsType = 17
|
||||||
|
FS_RMDIR FsType = 18
|
||||||
|
FS_MKDIR FsType = 19
|
||||||
|
FS_MKDTEMP FsType = 20
|
||||||
|
FS_RENAME FsType = 21
|
||||||
|
FS_SCANDIR FsType = 22
|
||||||
|
FS_LINK FsType = 23
|
||||||
|
FS_SYMLINK FsType = 24
|
||||||
|
FS_READLINK FsType = 25
|
||||||
|
FS_CHOWN FsType = 26
|
||||||
|
FS_FCHOWN FsType = 27
|
||||||
|
FS_REALPATH FsType = 28
|
||||||
|
FS_COPYFILE FsType = 29
|
||||||
|
FS_LCHOWN FsType = 30
|
||||||
|
FS_OPENDIR FsType = 31
|
||||||
|
FS_READDIR FsType = 32
|
||||||
|
FS_CLOSEDIR FsType = 33
|
||||||
|
FS_STATFS FsType = 34
|
||||||
|
FS_MKSTEMP FsType = 35
|
||||||
|
FS_LUTIME FsType = 36
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DirentUnknown DirentType = iota
|
||||||
|
DirentFile
|
||||||
|
DirentDir
|
||||||
|
DirentLink
|
||||||
|
DirentFifo
|
||||||
|
DirentSocket
|
||||||
|
DirentChar
|
||||||
|
DirentBlock
|
||||||
|
)
|
||||||
|
|
||||||
|
type FsType c.Int
|
||||||
|
|
||||||
|
type DirentType c.Int
|
||||||
|
|
||||||
|
type File c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Fs struct {
|
||||||
|
Unused [440]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type FsEvent struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type FsPoll struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dirent struct {
|
||||||
|
Name *c.Char
|
||||||
|
Type DirentType
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stat struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type FsCb func(req *Fs)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type FsEventCb func(handle *FsEvent, filename *c.Char, events c.Int, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type FsPollCb func(handle *FsPoll, status c.Int, events c.Int)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Fs related function and method */
|
||||||
|
|
||||||
|
// llgo:link (*Fs).GetType C.uv_fs_get_type
|
||||||
|
func (req *Fs) GetType() FsType {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Fs).GetPath C.uv_fs_get_path
|
||||||
|
func (req *Fs) GetPath() *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Fs).GetResult C.uv_fs_get_result
|
||||||
|
func (req *Fs) GetResult() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Fs).GetPtr C.uv_fs_get_ptr
|
||||||
|
func (req *Fs) GetPtr() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Fs).GetSystemError C.uv_fs_get_system_error
|
||||||
|
func (req *Fs) GetSystemError() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Fs).GetStatBuf C.uv_fs_get_statbuf
|
||||||
|
func (req *Fs) GetStatBuf() *Stat {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Fs).ReqCleanup C.uv_fs_req_cleanup
|
||||||
|
func (req *Fs) ReqCleanup() {
|
||||||
|
// No return value needed for this method
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname FsOpen C.uv_fs_open
|
||||||
|
func FsOpen(loop *Loop, req *Fs, path *c.Char, flags c.Int, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsClose C.uv_fs_close
|
||||||
|
func FsClose(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsRead C.uv_fs_read
|
||||||
|
func FsRead(loop *Loop, req *Fs, file File, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsWrite C.uv_fs_write
|
||||||
|
func FsWrite(loop *Loop, req *Fs, file File, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsUnlink C.uv_fs_unlink
|
||||||
|
func FsUnlink(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsMkdir C.uv_fs_mkdir
|
||||||
|
func FsMkdir(loop *Loop, req *Fs, path *c.Char, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsMkdtemp C.uv_fs_mkdtemp
|
||||||
|
func FsMkdtemp(loop *Loop, req *Fs, tpl *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsMkStemp C.uv_fs_mkstemp
|
||||||
|
func FsMkStemp(loop *Loop, req *Fs, tpl *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsRmdir C.uv_fs_rmdir
|
||||||
|
func FsRmdir(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsStat C.uv_fs_stat
|
||||||
|
func FsStat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFstat C.uv_fs_fstat
|
||||||
|
func FsFstat(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsRename C.uv_fs_rename
|
||||||
|
func FsRename(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFsync C.uv_fs_fsync
|
||||||
|
func FsFsync(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFdatasync C.uv_fs_fdatasync
|
||||||
|
func FsFdatasync(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFtruncate C.uv_fs_ftruncate
|
||||||
|
func FsFtruncate(loop *Loop, req *Fs, file File, offset c.LongLong, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsSendfile C.uv_fs_sendfile
|
||||||
|
func FsSendfile(loop *Loop, req *Fs, outFd c.Int, inFd c.Int, inOffset c.LongLong, length c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsAccess C.uv_fs_access
|
||||||
|
func FsAccess(loop *Loop, req *Fs, path *c.Char, flags c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsChmod C.uv_fs_chmod
|
||||||
|
func FsChmod(loop *Loop, req *Fs, path *c.Char, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFchmod C.uv_fs_fchmod
|
||||||
|
func FsFchmod(loop *Loop, req *Fs, file File, mode c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsUtime C.uv_fs_utime
|
||||||
|
func FsUtime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFutime C.uv_fs_futime
|
||||||
|
func FsFutime(loop *Loop, req *Fs, file File, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsLutime C.uv_fs_lutime
|
||||||
|
func FsLutime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsLink C.uv_fs_link
|
||||||
|
func FsLink(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsSymlink C.uv_fs_symlink
|
||||||
|
func FsSymlink(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, flags c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsReadlink C.uv_fs_read
|
||||||
|
func FsReadlink(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsRealpath C.uv_fs_realpath
|
||||||
|
func FsRealpath(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsCopyfile C.uv_fs_copyfile
|
||||||
|
func FsCopyfile(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, flags c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsScandir C.uv_fs_scandir
|
||||||
|
func FsScandir(loop *Loop, req *Fs, path *c.Char, flags c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsScandirNext C.uv_fs_scandir_next
|
||||||
|
func FsScandirNext(req *Fs, ent *Dirent) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsOpenDir C.uv_fs_opendir
|
||||||
|
func FsOpenDir(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsReaddir C.uv_fs_readdir
|
||||||
|
func FsReaddir(loop *Loop, req *Fs, dir c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsCloseDir C.uv_fs_closedir
|
||||||
|
func FsCloseDir(loop *Loop, req *Fs) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsStatfs C.uv_fs_statfs
|
||||||
|
func FsStatfs(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsChown C.uv_fs_chown
|
||||||
|
func FsChown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsFchown C.uv_fs_fchown
|
||||||
|
func FsFchown(loop *Loop, req *Fs, file File, uid c.Int, gid c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsLchown C.uv_fs_lchown
|
||||||
|
func FsLchown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int
|
||||||
|
|
||||||
|
//go:linkname FsLstat C.uv_fs_lstat
|
||||||
|
func FsLstat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* FsEvent related function and method */
|
||||||
|
|
||||||
|
//go:linkname FsEventInit C.uv_fs_event_init
|
||||||
|
func FsEventInit(loop *Loop, handle *FsEvent) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*FsEvent).Start C.uv_fs_event_start
|
||||||
|
func (handle *FsEvent) Start(cb FsEventCb, path *c.Char, flags c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*FsEvent).Stop C.uv_fs_event_stop
|
||||||
|
func (handle *FsEvent) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*FsEvent).Close C.uv_fs_event_close
|
||||||
|
func (handle *FsEvent) Close() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*FsEvent).Getpath C.uv_fs_event_getpath
|
||||||
|
func (handle *FsEvent) Getpath() *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* FsPoll related function and method */
|
||||||
|
|
||||||
|
//go:linkname FsPollInit C.uv_fs_poll_init
|
||||||
|
func FsPollInit(loop *Loop, handle *FsPoll) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*FsPoll).Start C.uv_fs_poll_start
|
||||||
|
func (handle *FsPoll) Start(cb FsPollCb, path *c.Char, interval uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*FsPoll).Stop C.uv_fs_poll_stop
|
||||||
|
func (handle *FsPoll) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*FsPoll).Close C.uv_fs_poll_close
|
||||||
|
func (handle *FsPoll) Close() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*FsPoll).GetPath C.uv_fs_poll_getpath
|
||||||
|
func (handle *FsPoll) GetPath() *c.Char {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
27
runtime/internal/clite/libuv/idle.go
Normal file
27
runtime/internal/clite/libuv/idle.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Idle struct {
|
||||||
|
Unused [120]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type IdleCb func(idle *Idle)
|
||||||
|
|
||||||
|
//go:linkname InitIdle C.uv_idle_init
|
||||||
|
func InitIdle(loop *Loop, idle *Idle) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Idle).Start C.uv_idle_start
|
||||||
|
func (idle *Idle) Start(idleCb IdleCb) c.Int { return 0 }
|
||||||
|
|
||||||
|
// llgo:link (*Idle).Stop C.uv_idle_stop
|
||||||
|
func (idle *Idle) Stop() c.Int { return 0 }
|
||||||
276
runtime/internal/clite/libuv/libuv.go
Normal file
276
runtime/internal/clite/libuv/libuv.go
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: $(pkg-config --libs libuv); -luv"
|
||||||
|
LLGoFiles = "$(pkg-config --cflags libuv): _wrap/libuv.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
const (
|
||||||
|
RUN_DEFAULT RunMode = iota
|
||||||
|
RUN_ONCE
|
||||||
|
RUN_NOWAIT
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LOOP_BLOCK_SIGNAL LoopOption = iota
|
||||||
|
METRICS_IDLE_TIME
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UV_LEAVE_GROUP Membership = iota
|
||||||
|
UV_JOIN_GROUP
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UNKNOWN_HANDLE HandleType = iota
|
||||||
|
ASYNC
|
||||||
|
CHECK
|
||||||
|
FS_EVENT
|
||||||
|
FS_POLL
|
||||||
|
HANDLE
|
||||||
|
IDLE
|
||||||
|
NAMED_PIPE
|
||||||
|
POLL
|
||||||
|
PREPARE
|
||||||
|
PROCESS
|
||||||
|
STREAM
|
||||||
|
TCP
|
||||||
|
TIMER
|
||||||
|
TTY
|
||||||
|
UDP
|
||||||
|
SIGNAL
|
||||||
|
FILE
|
||||||
|
HANDLE_TYPE_MAX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UNKNOWN_REQ ReqType = iota
|
||||||
|
REQ
|
||||||
|
CONNECT
|
||||||
|
WRITE
|
||||||
|
SHUTDOWN
|
||||||
|
UDP_SEND
|
||||||
|
FS
|
||||||
|
WORK
|
||||||
|
GETADDRINFO
|
||||||
|
GETNAMEINFO
|
||||||
|
RANDOM
|
||||||
|
REQ_TYPE_PRIVATE
|
||||||
|
REQ_TYPE_MAX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
READABLE PollEvent = 1 << iota
|
||||||
|
WRITABLE
|
||||||
|
DISCONNECT
|
||||||
|
PRIPRIORITIZED
|
||||||
|
)
|
||||||
|
|
||||||
|
type RunMode c.Int
|
||||||
|
|
||||||
|
type LoopOption c.Int
|
||||||
|
|
||||||
|
type Membership c.Int
|
||||||
|
|
||||||
|
type HandleType c.Int
|
||||||
|
|
||||||
|
type ReqType c.Int
|
||||||
|
|
||||||
|
type OsSock c.Int
|
||||||
|
|
||||||
|
type OsFd c.Int
|
||||||
|
|
||||||
|
type PollEvent c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Loop struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Poll struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [160]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request types. */
|
||||||
|
|
||||||
|
type Buf struct {
|
||||||
|
Base *c.Char
|
||||||
|
Len uintptr
|
||||||
|
} // ----------------------------------------------
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type MallocFunc func(size uintptr) c.Pointer
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ReallocFunc func(ptr c.Pointer, size uintptr) c.Pointer
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type CallocFunc func(count uintptr, size uintptr) c.Pointer
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type FreeFunc func(ptr c.Pointer)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type AllocCb func(handle *Handle, suggestedSize uintptr, buf *Buf)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type GetaddrinfoCb func(req *GetAddrInfo, status c.Int, res *net.AddrInfo)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type GetnameinfoCb func(req *GetNameInfo, status c.Int, hostname *c.Char, service *c.Char)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type WalkCb func(handle *Handle, arg c.Pointer)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type PollCb func(handle *Poll, status c.Int, events c.Int)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Version C.uv_version
|
||||||
|
func Version() c.Uint
|
||||||
|
|
||||||
|
//go:linkname VersionString C.uv_version_string
|
||||||
|
func VersionString() *c.Char
|
||||||
|
|
||||||
|
//go:linkname LibraryShutdown C.uv_library_shutdown
|
||||||
|
func LibraryShutdown()
|
||||||
|
|
||||||
|
//go:linkname ReplaceAllocator C.uv_replace_allocator
|
||||||
|
func ReplaceAllocator(mallocFunc MallocFunc, reallocFunc ReallocFunc, callocFunc CallocFunc, freeFunc FreeFunc) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Loop related functions and method. */
|
||||||
|
|
||||||
|
//go:linkname DefaultLoop C.uv_default_loop
|
||||||
|
func DefaultLoop() *Loop
|
||||||
|
|
||||||
|
//go:linkname LoopSize C.uv_loop_size
|
||||||
|
func LoopSize() uintptr
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Run C.uv_run
|
||||||
|
func (loop *Loop) Run(mode RunMode) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Alive C.uv_loop_alive
|
||||||
|
func (loop *Loop) Alive() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// void uv_stop(uv_loop_t *loop)
|
||||||
|
//
|
||||||
|
// llgo:link (*Loop).Stop C.uv_stop
|
||||||
|
func (loop *Loop) Stop() {}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Close C.uv_loop_close
|
||||||
|
func (loop *Loop) Close() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Configure C.uv_loop_configure
|
||||||
|
func (loop *Loop) Configure(option LoopOption, arg c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link LoopDefault C.uv_default_loop
|
||||||
|
func LoopDefault() *Loop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Delete C.uv_loop_delete
|
||||||
|
func (loop *Loop) Delete() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Fork C.uv_loop_fork
|
||||||
|
func (loop *Loop) Fork() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Init C.uv_loop_init
|
||||||
|
func (loop *Loop) Init() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link LoopNew C.uv_loop_new
|
||||||
|
func LoopNew() *Loop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).SetData C.uv_loop_set_data
|
||||||
|
func (loop *Loop) SetData(data c.Pointer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).GetData C.uv_loop_get_data
|
||||||
|
func (loop *Loop) GetData() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Now C.uv_now
|
||||||
|
func (loop *Loop) Now() c.UlongLong {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).UpdateTime C.uv_update_time
|
||||||
|
func (loop *Loop) UpdateTime() {
|
||||||
|
// No return value needed for this method
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).BackendFd C.uv_backend_fd
|
||||||
|
func (loop *Loop) BackendFd() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).BackendTimeout C.uv_backend_timeout
|
||||||
|
func (loop *Loop) BackendTimeout() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Loop).Walk C.uv_walk
|
||||||
|
func (loop *Loop) Walk(walkCb WalkCb, arg c.Pointer) {
|
||||||
|
// No return value needed for this method
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Buf related functions and method. */
|
||||||
|
|
||||||
|
//go:linkname InitBuf C.uv_buf_init
|
||||||
|
func InitBuf(base *c.Char, len c.Uint) Buf
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Poll related function and method */
|
||||||
|
|
||||||
|
//go:linkname PollInit C.uv_poll_init
|
||||||
|
func PollInit(loop *Loop, handle *Poll, fd OsFd) c.Int
|
||||||
|
|
||||||
|
//go:linkname PollInitSocket C.uv_poll_init_socket
|
||||||
|
func PollInitSocket(loop *Loop, handle *Poll, socket c.Int) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Poll).Start C.uv_poll_start
|
||||||
|
func (handle *Poll) Start(events c.Int, cb PollCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Poll).Stop C.uv_poll_stop
|
||||||
|
func (handle *Poll) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
543
runtime/internal/clite/libuv/net.go
Normal file
543
runtime/internal/clite/libuv/net.go
Normal file
@@ -0,0 +1,543 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
/* Used with uv_tcp_bind, when an IPv6 address is used. */
|
||||||
|
TCP_IPV6ONLY TcpFlags = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UDP support.
|
||||||
|
*/
|
||||||
|
const (
|
||||||
|
/* Disables dual stack mode. */
|
||||||
|
UDP_IPV6ONLY UdpFlags = 1
|
||||||
|
/*
|
||||||
|
* Indicates message was truncated because read buffer was too small. The
|
||||||
|
* remainder was discarded by the OS. Used in uv_udp_recv_cb.
|
||||||
|
*/
|
||||||
|
UDP_PARTIAL UdpFlags = 2
|
||||||
|
/*
|
||||||
|
* Indicates if SO_REUSEADDR will be set when binding the handle.
|
||||||
|
* This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
|
||||||
|
* Unix platforms, it sets the SO_REUSEADDR flag. What that means is that
|
||||||
|
* multiple threads or processes can bind to the same address without error
|
||||||
|
* (provided they all set the flag) but only the last one to bind will receive
|
||||||
|
* any traffic, in effect "stealing" the port from the previous listener.
|
||||||
|
*/
|
||||||
|
UDP_REUSEADDR UdpFlags = 4
|
||||||
|
/*
|
||||||
|
* Indicates that the message was received by recvmmsg, so the buffer provided
|
||||||
|
* must not be freed by the recv_cb callback.
|
||||||
|
*/
|
||||||
|
UDP_MMSG_CHUNK UdpFlags = 8
|
||||||
|
/*
|
||||||
|
* Indicates that the buffer provided has been fully utilized by recvmmsg and
|
||||||
|
* that it should now be freed by the recv_cb callback. When this flag is set
|
||||||
|
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
|
||||||
|
*/
|
||||||
|
UDP_MMSG_FREE UdpFlags = 16
|
||||||
|
/*
|
||||||
|
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||||
|
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||||
|
* Linux. This stops the Linux kernel from suppressing some ICMP error
|
||||||
|
* messages and enables full ICMP error reporting for faster failover.
|
||||||
|
* This flag is no-op on platforms other than Linux.
|
||||||
|
*/
|
||||||
|
UDP_LINUX_RECVERR UdpFlags = 32
|
||||||
|
/*
|
||||||
|
* Indicates that recvmmsg should be used, if available.
|
||||||
|
*/
|
||||||
|
UDP_RECVMMSG UdpFlags = 256
|
||||||
|
)
|
||||||
|
|
||||||
|
type TcpFlags c.Int
|
||||||
|
|
||||||
|
type UdpFlags c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
// TODO(spongehah): Handle
|
||||||
|
type Handle struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [88]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Stream
|
||||||
|
type Stream struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [256]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Tcp
|
||||||
|
type Tcp struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [256]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Udp
|
||||||
|
type Udp struct {
|
||||||
|
Unused [224]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request types. */
|
||||||
|
|
||||||
|
// TODO(spongehah): Req
|
||||||
|
type Req struct {
|
||||||
|
Unused [64]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): UdpSend
|
||||||
|
type UdpSend struct {
|
||||||
|
Unused [320]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Write
|
||||||
|
type Write struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [184]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Connect
|
||||||
|
type Connect struct {
|
||||||
|
Data c.Pointer
|
||||||
|
Unused [88]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): GetAddrInfo
|
||||||
|
type GetAddrInfo struct {
|
||||||
|
Unused [160]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): GetNameInfo
|
||||||
|
type GetNameInfo struct {
|
||||||
|
Unused [1320]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(spongehah): Shutdown
|
||||||
|
type Shutdown struct {
|
||||||
|
Unused [80]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type CloseCb func(handle *Handle)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ConnectCb func(req *Connect, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type UdpSendCb func(req *UdpSend, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type UdpRecvCb func(handle *Udp, nread c.Long, buf *Buf, addr *net.SockAddr, flags c.Uint)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ReadCb func(stream *Stream, nread c.Long, buf *Buf)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type WriteCb func(req *Write, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ConnectionCb func(server *Stream, status c.Int)
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ShutdownCb func(req *Shutdown, status c.Int)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle related function and method */
|
||||||
|
|
||||||
|
//go:linkname HandleSize C.uv_handle_size
|
||||||
|
func HandleSize(handleType HandleType) uintptr
|
||||||
|
|
||||||
|
//go:linkname HandleTypeName C.uv_handle_type_name
|
||||||
|
func HandleTypeName(handleType HandleType) *c.Char
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Ref C.uv_ref
|
||||||
|
func (handle *Handle) Ref() {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Unref C.uv_unref
|
||||||
|
func (handle *Handle) Unref() {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).HasRef C.uv_has_ref
|
||||||
|
func (handle *Handle) HasRef() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).GetType C.uv_handle_get_type
|
||||||
|
func (handle *Handle) GetType() HandleType {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).GetData C.uv_handle_get_data
|
||||||
|
func (handle *Handle) GetData() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).GetLoop C.uv_handle_get_loop
|
||||||
|
func (handle *Handle) GetLoop() *Loop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).SetData C.uv_handle_set_data
|
||||||
|
func (handle *Handle) SetData(data c.Pointer) {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsActive C.uv_is_active
|
||||||
|
func (handle *Handle) IsActive() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Close C.uv_close
|
||||||
|
func (handle *Handle) Close(closeCb CloseCb) {}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).SendBufferSize C.uv_send_buffer_size
|
||||||
|
func (handle *Handle) SendBufferSize(value *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).RecvBufferSize C.uv_recv_buffer_size
|
||||||
|
func (handle *Handle) RecvBufferSize(value *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).Fileno C.uv_fileno
|
||||||
|
func (handle *Handle) Fileno(fd *OsFd) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsClosing C.uv_is_closing
|
||||||
|
func (handle *Handle) IsClosing() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsReadable C.uv_is_readable
|
||||||
|
func (handle *Handle) IsReadable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Handle).IsWritable C.uv_is_writable
|
||||||
|
func (handle *Handle) IsWritable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Pipe C.uv_pipe
|
||||||
|
func Pipe(fds [2]File, readFlags c.Int, writeFlags c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Socketpair C.uv_socketpair
|
||||||
|
func Socketpair(_type c.Int, protocol c.Int, socketVector [2]OsSock, flag0 c.Int, flag1 c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Req related function and method */
|
||||||
|
|
||||||
|
//go:linkname ReqSize C.uv_req_size
|
||||||
|
func ReqSize(reqType ReqType) uintptr
|
||||||
|
|
||||||
|
//go:linkname TypeName C.uv_req_type_name
|
||||||
|
func TypeName(reqType ReqType) *c.Char
|
||||||
|
|
||||||
|
// llgo:link (*Req).GetData C.uv_req_get_data
|
||||||
|
func (req *Req) GetData() c.Pointer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Req).SetData C.uv_req_set_data
|
||||||
|
func (req *Req) SetData(data c.Pointer) {}
|
||||||
|
|
||||||
|
// llgo:link (*Req).GetType C.uv_req_get_type
|
||||||
|
func (req *Req) GetType() ReqType {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Req).Cancel C.uv_cancel
|
||||||
|
func (req *Req) Cancel() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Stream related function and method */
|
||||||
|
|
||||||
|
// llgo:link (*Stream).GetWriteQueueSize C.uv_stream_get_write_queue_size
|
||||||
|
func (stream *Stream) GetWriteQueueSize() uintptr {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).Listen C.uv_listen
|
||||||
|
func (stream *Stream) Listen(backlog c.Int, connectionCb ConnectionCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).Accept C.uv_accept
|
||||||
|
func (server *Stream) Accept(client *Stream) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).StartRead C.uv_read_start
|
||||||
|
func (stream *Stream) StartRead(allocCb AllocCb, readCb ReadCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).StopRead C.uv_read_stop
|
||||||
|
func (stream *Stream) StopRead() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Write).Write C.uv_write
|
||||||
|
func (req *Write) Write(stream *Stream, bufs *Buf, nbufs c.Uint, writeCb WriteCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Write).Write2 C.uv_write2
|
||||||
|
func (req *Write) Write2(stream *Stream, bufs *Buf, nbufs c.Uint, sendStream *Stream, writeCb WriteCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).TryWrite C.uv_try_write
|
||||||
|
func (stream *Stream) TryWrite(bufs *Buf, nbufs c.Uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).TryWrite2 C.uv_try_write2
|
||||||
|
func (stream *Stream) TryWrite2(bufs *Buf, nbufs c.Uint, sendStream *Stream) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).IsReadable C.uv_is_readable
|
||||||
|
func (stream *Stream) IsReadable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).IsWritable C.uv_is_writable
|
||||||
|
func (stream *Stream) IsWritable() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Stream).SetBlocking C.uv_stream_set_blocking
|
||||||
|
func (stream *Stream) SetBlocking(blocking c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname StreamShutdown C.uv_shutdown
|
||||||
|
func StreamShutdown(shutdown *Shutdown, stream *Stream, shutdownCb ShutdownCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Tcp related function and method */
|
||||||
|
|
||||||
|
//go:linkname InitTcp C.uv_tcp_init
|
||||||
|
func InitTcp(loop *Loop, tcp *Tcp) c.Int
|
||||||
|
|
||||||
|
//go:linkname InitTcpEx C.uv_tcp_init_ex
|
||||||
|
func InitTcpEx(loop *Loop, tcp *Tcp, flags c.Uint) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).Open C.uv_tcp_open
|
||||||
|
func (tcp *Tcp) Open(sock OsSock) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).Nodelay C.uv_tcp_nodelay
|
||||||
|
func (tcp *Tcp) Nodelay(enable c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).KeepAlive C.uv_tcp_keepalive
|
||||||
|
func (tcp *Tcp) KeepAlive(enable c.Int, delay c.Uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).SimultaneousAccepts C.uv_tcp_simultaneous_accepts
|
||||||
|
func (tcp *Tcp) SimultaneousAccepts(enable c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).Bind C.uv_tcp_bind
|
||||||
|
func (tcp *Tcp) Bind(addr *net.SockAddr, flags c.Uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).Getsockname C.uv_tcp_getsockname
|
||||||
|
func (tcp *Tcp) Getsockname(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).Getpeername C.uv_tcp_getpeername
|
||||||
|
func (tcp *Tcp) Getpeername(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).CloseReset C.uv_tcp_close_reset
|
||||||
|
func (tcp *Tcp) CloseReset(closeCb CloseCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Tcp).GetIoWatcherFd C.uv_tcp_get_io_watcher_fd
|
||||||
|
func (tcp *Tcp) GetIoWatcherFd() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname TcpConnect C.uv_tcp_connect
|
||||||
|
func TcpConnect(req *Connect, tcp *Tcp, addr *net.SockAddr, connectCb ConnectCb) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Udp related function and method */
|
||||||
|
|
||||||
|
//go:linkname InitUdp C.uv_udp_init
|
||||||
|
func InitUdp(loop *Loop, udp *Udp) c.Int
|
||||||
|
|
||||||
|
//go:linkname InitUdpEx C.uv_udp_init_ex
|
||||||
|
func InitUdpEx(loop *Loop, udp *Udp, flags c.Uint) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Udp).Open C.uv_udp_open
|
||||||
|
func (udp *Udp) Open(sock OsSock) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).Bind C.uv_udp_bind
|
||||||
|
func (udp *Udp) Bind(addr *net.SockAddr, flags c.Uint) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).Connect C.uv_udp_connect
|
||||||
|
func (udp *Udp) Connect(addr *net.SockAddr) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).Getpeername C.uv_udp_getpeername
|
||||||
|
func (udp *Udp) Getpeername(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).Getsockname C.uv_udp_getsockname
|
||||||
|
func (udp *Udp) Getsockname(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SetMembership C.uv_udp_set_membership
|
||||||
|
func (udp *Udp) SetMembership(multicastAddr *c.Char, interfaceAddr *c.Char, membership Membership) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SourceMembership C.uv_udp_set_source_membership
|
||||||
|
func (udp *Udp) SourceMembership(multicastAddr *c.Char, interfaceAddr *c.Char, sourceAddr *c.Char, membership Membership) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SetMulticastLoop C.uv_udp_set_multicast_loop
|
||||||
|
func (udp *Udp) SetMulticastLoop(on c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SetMulticastTTL C.uv_udp_set_multicast_ttl
|
||||||
|
func (udp *Udp) SetMulticastTTL(ttl c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SetMulticastInterface C.uv_udp_set_multicast_interface
|
||||||
|
func (udp *Udp) SetMulticastInterface(interfaceAddr *c.Char) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SetBroadcast C.uv_udp_set_broadcast
|
||||||
|
func (udp *Udp) SetBroadcast(on c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).SetTTL C.uv_udp_set_ttl
|
||||||
|
func (udp *Udp) SetTTL(ttl c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).TrySend C.uv_udp_try_send
|
||||||
|
func (udp *Udp) TrySend(bufs *Buf, nbufs c.Uint, addr *net.SockAddr) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).StartRecv C.uv_udp_recv_start
|
||||||
|
func (udp *Udp) StartRecv(allocCb AllocCb, recvCb UdpRecvCb) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).UsingRecvmmsg C.uv_udp_using_recvmmsg
|
||||||
|
func (udp *Udp) UsingRecvmmsg() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).StopRecv C.uv_udp_recv_stop
|
||||||
|
func (udp *Udp) StopRecv() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).GetSendQueueSize C.uv_udp_get_send_queue_size
|
||||||
|
func (udp *Udp) GetSendQueueSize() uintptr {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Udp).GetSendQueueCount C.uv_udp_get_send_queue_count
|
||||||
|
func (udp *Udp) GetSendQueueCount() uintptr {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Send C.uv_udp_send
|
||||||
|
func Send(req *UdpSend, udp *Udp, bufs *Buf, nbufs c.Uint, addr *net.SockAddr, sendCb UdpSendCb) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* DNS related function and method */
|
||||||
|
|
||||||
|
//go:linkname Ip4Addr C.uv_ip4_addr
|
||||||
|
func Ip4Addr(ip *c.Char, port c.Int, addr *net.SockaddrIn) c.Int
|
||||||
|
|
||||||
|
//go:linkname Ip6Addr C.uv_ip6_addr
|
||||||
|
func Ip6Addr(ip *c.Char, port c.Int, addr *net.SockaddrIn6) c.Int
|
||||||
|
|
||||||
|
//go:linkname Ip4Name C.uv_ip4_name
|
||||||
|
func Ip4Name(src *net.SockaddrIn, dst *c.Char, size uintptr) c.Int
|
||||||
|
|
||||||
|
//go:linkname Ip6Name C.uv_ip6_name
|
||||||
|
func Ip6Name(src *net.SockaddrIn6, dst *c.Char, size uintptr) c.Int
|
||||||
|
|
||||||
|
//go:linkname IpName C.uv_ip_name
|
||||||
|
func IpName(src *net.SockAddr, dst *c.Char, size uintptr) c.Int
|
||||||
|
|
||||||
|
//go:linkname InetNtop C.uv_inet_ntop
|
||||||
|
func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size uintptr) c.Int
|
||||||
|
|
||||||
|
//go:linkname InetPton C.uv_inet_pton
|
||||||
|
func InetPton(af c.Int, src *c.Char, dst c.Pointer) c.Int
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Getaddrinfo related function and method */
|
||||||
|
|
||||||
|
//go:linkname Getaddrinfo C.uv_getaddrinfo
|
||||||
|
func Getaddrinfo(loop *Loop, req *GetAddrInfo, getaddrinfoCb GetaddrinfoCb, node *c.Char, service *c.Char, hints *net.AddrInfo) c.Int
|
||||||
|
|
||||||
|
//go:linkname Freeaddrinfo C.uv_freeaddrinfo
|
||||||
|
func Freeaddrinfo(addrInfo *net.AddrInfo)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Getnameinfo related function and method */
|
||||||
|
|
||||||
|
//go:linkname Getnameinfo C.uv_getnameinfo
|
||||||
|
func Getnameinfo(loop *Loop, req *GetNameInfo, getnameinfoCb GetnameinfoCb, addr *net.SockAddr, flags c.Int) c.Int
|
||||||
42
runtime/internal/clite/libuv/signal.go
Normal file
42
runtime/internal/clite/libuv/signal.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Signal struct {
|
||||||
|
Unused [152]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type SignalCb func(handle *Signal, sigNum c.Int)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Signal related functions and method. */
|
||||||
|
|
||||||
|
//go:linkname SignalInit C.uv_signal_init
|
||||||
|
func SignalInit(loop *Loop, handle *Signal) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Signal).Start C.uv_signal_start
|
||||||
|
func (handle *Signal) Start(cb SignalCb, signum c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Signal).StartOneshot C.uv_signal_start_oneshot
|
||||||
|
func (handle *Signal) StartOneshot(cb SignalCb, signum c.Int) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Signal).Stop C.uv_signal_stop
|
||||||
|
func (handle *Signal) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
78
runtime/internal/clite/libuv/thread.go
Normal file
78
runtime/internal/clite/libuv/thread.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Thread struct {
|
||||||
|
Unused [8]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThreadOptions struct {
|
||||||
|
flags c.Uint
|
||||||
|
stackSize uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type Work struct {
|
||||||
|
Unused [128]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Function type */
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type ThreadCb func(arg c.Pointer)
|
||||||
|
|
||||||
|
//llgo:type C
|
||||||
|
type WorkCb func(req *Work)
|
||||||
|
|
||||||
|
//llgo:type C
|
||||||
|
type AfterWorkCb func(req *Work, status c.Int)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Thread related functions and method. */
|
||||||
|
|
||||||
|
//go:linkname ThreadEqual C.uv_thread_equal
|
||||||
|
func ThreadEqual(t1 *Thread, t2 *Thread) c.Int
|
||||||
|
|
||||||
|
//go:linkname ThreadGetCPU C.uv_thread_getcpu
|
||||||
|
func ThreadGetCPU() c.Int
|
||||||
|
|
||||||
|
//go:linkname ThreadSelf C.uv_thread_self
|
||||||
|
func ThreadSelf() Thread
|
||||||
|
|
||||||
|
// llgo:link (*Thread).Create C.uv_thread_create
|
||||||
|
func (t *Thread) Create(entry ThreadCb, arg c.Pointer) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Thread).CreateEx C.uv_thread_create_ex
|
||||||
|
func (t *Thread) CreateEx(entry ThreadCb, params *ThreadOptions, arg c.Pointer) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Thread).Join C.uv_thread_join
|
||||||
|
func (t *Thread) Join() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Thread).SetAffinity C.uv_thread_set_affinity
|
||||||
|
func (t *Thread) SetAffinity(cpuMask *c.Char, oldMask *c.Char, maskSize uintptr) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Thread).GetAffinity C.uv_thread_get_affinity
|
||||||
|
func (t *Thread) GetAffinity(cpuMask *c.Char, maskSize uintptr) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Work related functions and method. */
|
||||||
|
|
||||||
|
//go:linkname QueueWork C.uv_queue_work
|
||||||
|
func QueueWork(loop *Loop, req *Work, workCb WorkCb, afterWorkCb AfterWorkCb) c.Int
|
||||||
56
runtime/internal/clite/libuv/timer.go
Normal file
56
runtime/internal/clite/libuv/timer.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package libuv
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
// TODO(spongehah): Timer
|
||||||
|
type Timer struct {
|
||||||
|
Unused [152]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
// llgo:type C
|
||||||
|
type TimerCb func(timer *Timer)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Timer related function and method */
|
||||||
|
|
||||||
|
//go:linkname InitTimer C.uv_timer_init
|
||||||
|
func InitTimer(loop *Loop, timer *Timer) c.Int
|
||||||
|
|
||||||
|
// llgo:link (*Timer).Start C.uv_timer_start
|
||||||
|
func (timer *Timer) Start(cb TimerCb, timeoutMs uint64, repeat uint64) c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Timer).Stop C.uv_timer_stop
|
||||||
|
func (timer *Timer) Stop() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Timer).Again C.uv_timer_again
|
||||||
|
func (timer *Timer) Again() c.Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Timer).SetRepeat C.uv_timer_set_repeat
|
||||||
|
func (timer *Timer) SetRepeat(repeat uint64) {}
|
||||||
|
|
||||||
|
// llgo:link (*Timer).GetRepeat C.uv_timer_get_repeat
|
||||||
|
func (timer *Timer) GetRepeat() uint64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link (*Timer).GetDueIn C.uv_timer_get_due_in
|
||||||
|
func (timer *Timer) GetDueIn() uint64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
223
runtime/internal/clite/net/net.go
Normal file
223
runtime/internal/clite/net/net.go
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = true
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AF_UNSPEC = 0 // unspecified
|
||||||
|
AF_UNIX = 1 // local to host (pipes)
|
||||||
|
AF_LOCAL = AF_UNIX // backward compatibility
|
||||||
|
AF_INET = 2 // internetwork: UDP, TCP, etc.
|
||||||
|
AF_IMPLINK = 3 // arpanet imp addresses
|
||||||
|
AF_PUP = 4 // pup protocols: e.g. BSP
|
||||||
|
AF_CHAOS = 5 // mit CHAOS protocols
|
||||||
|
AF_NS = 6 // XEROX NS protocols
|
||||||
|
AF_ISO = 7 // ISO protocols
|
||||||
|
AF_OSI = AF_ISO
|
||||||
|
AF_ECMA = 8 // European computer manufacturers
|
||||||
|
AF_DATAKIT = 9 // datakit protocols
|
||||||
|
AF_CCITT = 10 // CCITT protocols, X.25 etc
|
||||||
|
AF_SNA = 11 // IBM SNA
|
||||||
|
AF_DECnet = 12 // DECnet
|
||||||
|
AF_DLI = 13 // DEC Direct data link interface
|
||||||
|
AF_LAT = 14 // LAT
|
||||||
|
AF_HYLINK = 15 // NSC Hyperchannel
|
||||||
|
AF_APPLETALK = 16 // Apple Talk
|
||||||
|
AF_ROUTE = 17 // Internal Routing Protocol
|
||||||
|
AF_LINK = 18 // Link layer interface
|
||||||
|
pseudo_AF_XTP = 19 // eXpress Transfer Protocol (no AF)
|
||||||
|
AF_COIP = 20 // connection-oriented IP, aka ST II
|
||||||
|
AF_CNT = 21 // Computer Network Technology
|
||||||
|
pseudo_AF_RTIP = 22 // Help Identify RTIP packets
|
||||||
|
AF_IPX = 23 // Novell Internet Protocol
|
||||||
|
AF_SIP = 24 // Simple Internet Protocol
|
||||||
|
pseudo_AF_PIP = 25 // Help Identify PIP packets
|
||||||
|
AF_NDRV = 27 // Network Driver 'raw' access
|
||||||
|
AF_ISDN = 28 // Integrated Services Digital Network
|
||||||
|
AF_E164 = AF_ISDN // CCITT E.164 recommendation
|
||||||
|
pseudo_AF_KEY = 29 // Internal key-management function
|
||||||
|
AF_INET6 = 30 // IPv6
|
||||||
|
AF_NATM = 31 // native ATM access
|
||||||
|
AF_SYSTEM = 32 // Kernel event messages
|
||||||
|
AF_NETBIOS = 33 // NetBIOS
|
||||||
|
AF_PPP = 34 // PPP communication protocol
|
||||||
|
pseudo_AF_HDRCMPLT = 35 // Used by BPF to not rewrite headers in interface output routine
|
||||||
|
AF_RESERVED_36 = 36 // Reserved for internal usage
|
||||||
|
AF_IEEE80211 = 37 // IEEE 802.11 protocol
|
||||||
|
AF_UTUN = 38
|
||||||
|
AF_VSOCK = 40 // VM Sockets
|
||||||
|
AF_MAX = 41
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SOCK_STREAM = 1 // stream socket
|
||||||
|
SOCK_DGRAM = 2 // datagram socket
|
||||||
|
SOCK_RAW = 3 // raw-protocol interface
|
||||||
|
SOCK_RDM = 4 // reliably-delivered message
|
||||||
|
SOCK_SEQPACKET = 5 // sequenced packet stream
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EAI_ADDRFAMILY = iota + 1 /* address family for hostname not supported */
|
||||||
|
EAI_AGAIN /* temporary failure in name resolution */
|
||||||
|
EAI_BADFLAGS /* invalid value for ai_flags */
|
||||||
|
EAI_FAIL /* non-recoverable failure in name resolution */
|
||||||
|
EAI_FAMILY /* ai_family not supported */
|
||||||
|
EAI_MEMORY /* memory allocation failure */
|
||||||
|
EAI_NODATA /* no address associated with hostname */
|
||||||
|
EAI_NONAME /* hostname nor servname provided, or not known */
|
||||||
|
EAI_SERVICE /* servname not supported for ai_socktype */
|
||||||
|
EAI_SOCKTYPE /* ai_socktype not supported */
|
||||||
|
EAI_SYSTEM /* system error returned in errno */
|
||||||
|
EAI_BADHINTS /* invalid value for hints */
|
||||||
|
EAI_PROTOCOL /* resolved protocol is unknown */
|
||||||
|
EAI_OVERFLOW /* argument buffer overflow */
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ALIGNSIZE = unsafe.Sizeof(c.LongLong(0))
|
||||||
|
MAXSIZE = 128
|
||||||
|
PAD1_SIZE = ALIGNSIZE - unsafe.Sizeof(byte(0)) - unsafe.Sizeof(byte(0))
|
||||||
|
PAD2_SIZE = MAXSIZE - unsafe.Sizeof(byte(0)) - unsafe.Sizeof(byte(0)) - PAD1_SIZE - ALIGNSIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
// (TODO) merge to inet
|
||||||
|
const INET_ADDRSTRLEN = 16
|
||||||
|
|
||||||
|
type SockaddrIn struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Addr InAddr
|
||||||
|
Zero [8]c.Char
|
||||||
|
}
|
||||||
|
|
||||||
|
type SockaddrIn6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo c.Uint
|
||||||
|
Addr In6Addr
|
||||||
|
ScopeId c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type SockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
pad1 [PAD1_SIZE]c.Char
|
||||||
|
align c.LongLong
|
||||||
|
pad2 [PAD2_SIZE]c.Char
|
||||||
|
}
|
||||||
|
|
||||||
|
type InAddr struct {
|
||||||
|
Addr c.Uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type In6Addr struct {
|
||||||
|
U6Addr [16]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type SockAddr struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Data [14]c.Char
|
||||||
|
}
|
||||||
|
|
||||||
|
type Hostent struct {
|
||||||
|
Name *c.Char // official name of host
|
||||||
|
Aliases **c.Char // null-terminated array of alternate names for the host
|
||||||
|
AddrType c.Int // host address type
|
||||||
|
Length c.Int // length of address
|
||||||
|
AddrList **c.Char // null-terminated array of addresses for the host
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Socket C.socket
|
||||||
|
func Socket(domain c.Int, typ c.Int, protocol c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Bind C.bind
|
||||||
|
func Bind(sockfd c.Int, addr *SockaddrIn, addrlen c.Uint) c.Int
|
||||||
|
|
||||||
|
//go:linkname Connect C.connect
|
||||||
|
func Connect(sockfd c.Int, addr *SockAddr, addrlen c.Uint) c.Int
|
||||||
|
|
||||||
|
//go:linkname Listen C.listen
|
||||||
|
func Listen(sockfd c.Int, backlog c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Accept C.accept
|
||||||
|
func Accept(sockfd c.Int, addr *SockaddrIn, addrlen *c.Uint) c.Int
|
||||||
|
|
||||||
|
//go:linkname GetHostByName C.gethostbyname
|
||||||
|
func GetHostByName(name *c.Char) *Hostent
|
||||||
|
|
||||||
|
// (TODO) merge to inet
|
||||||
|
//
|
||||||
|
//go:linkname InetNtop C.inet_ntop
|
||||||
|
func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size c.Uint) *c.Char
|
||||||
|
|
||||||
|
//go:linkname InetAddr C.inet_addr
|
||||||
|
func InetAddr(s *c.Char) c.Uint
|
||||||
|
|
||||||
|
//go:linkname Send C.send
|
||||||
|
func Send(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
||||||
|
|
||||||
|
//go:linkname Recv C.recv
|
||||||
|
func Recv(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
||||||
|
|
||||||
|
//go:linkname SetSockOpt C.setsockopt
|
||||||
|
func SetSockOpt(socket c.Int, level c.Int, optionName c.Int, optionValue c.Pointer, sockLen c.Uint) c.Int
|
||||||
|
|
||||||
|
//go:linkname Ntohs C.ntohs
|
||||||
|
func Ntohs(x uint16) uint16
|
||||||
|
|
||||||
|
//go:linkname Htons C.htons
|
||||||
|
func Htons(x uint16) uint16
|
||||||
|
|
||||||
|
//go:linkname Ntohl C.ntohl
|
||||||
|
func Ntohl(x c.Uint) c.Uint
|
||||||
|
|
||||||
|
//go:linkname Htonl C.htonl
|
||||||
|
func Htonl(x c.Uint) c.Uint
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type AddrInfo struct {
|
||||||
|
Flags c.Int
|
||||||
|
Family c.Int
|
||||||
|
SockType c.Int
|
||||||
|
Protocol c.Int
|
||||||
|
AddrLen c.Uint
|
||||||
|
CanOnName *c.Char
|
||||||
|
Addr *SockAddr
|
||||||
|
Next *AddrInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Getaddrinfo C.getaddrinfo
|
||||||
|
func Getaddrinfo(host *c.Char, port *c.Char, addrInfo *AddrInfo, result **AddrInfo) c.Int
|
||||||
|
|
||||||
|
//go:linkname Freeaddrinfo C.freeaddrinfo
|
||||||
|
func Freeaddrinfo(addrInfo *AddrInfo) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -94,6 +94,9 @@ func Readlink(path *c.Char, buf c.Pointer, bufsize uintptr) int
|
|||||||
//go:linkname Unlink C.unlink
|
//go:linkname Unlink C.unlink
|
||||||
func Unlink(path *c.Char) c.Int
|
func Unlink(path *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Unlinkat C.unlinkat
|
||||||
|
func Unlinkat(dirfd c.Int, path *c.Char, flags c.Int) c.Int
|
||||||
|
|
||||||
//go:linkname Remove C.remove
|
//go:linkname Remove C.remove
|
||||||
func Remove(path *c.Char) c.Int
|
func Remove(path *c.Char) c.Int
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const (
|
|||||||
LLGoPackage = "noinit"
|
LLGoPackage = "noinit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Errno = uintptr
|
type Errno uintptr
|
||||||
|
|
||||||
// A Signal is a number describing a process signal.
|
// A Signal is a number describing a process signal.
|
||||||
// It implements the os.Signal interface.
|
// It implements the os.Signal interface.
|
||||||
@@ -30,3 +30,7 @@ type Signal = int
|
|||||||
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||||
return int64(ts.Sec), int64(ts.Nsec)
|
return int64(ts.Sec), int64(ts.Nsec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (iov *Iovec) SetLen(length int) {
|
||||||
|
iov.Len = uint64(length)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package hmac
|
package hmac
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
@@ -11,6 +10,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _hmac struct{}
|
||||||
|
|
||||||
type eface struct {
|
type eface struct {
|
||||||
_type unsafe.Pointer
|
_type unsafe.Pointer
|
||||||
funcPtr *unsafe.Pointer
|
funcPtr *unsafe.Pointer
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package md5
|
package md5
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"hash"
|
"hash"
|
||||||
@@ -26,6 +25,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _md5 struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
crypto.RegisterHash(crypto.MD5, New)
|
crypto.RegisterHash(crypto.MD5, New)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package rand
|
package rand
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@@ -25,6 +24,9 @@ import (
|
|||||||
"github.com/qiniu/x/errors"
|
"github.com/qiniu/x/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _rand struct{}
|
||||||
|
|
||||||
type rndReader struct{}
|
type rndReader struct{}
|
||||||
|
|
||||||
func (rndReader) Read(p []byte) (n int, err error) {
|
func (rndReader) Read(p []byte) (n int, err error) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package sha1
|
package sha1
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"hash"
|
"hash"
|
||||||
@@ -26,6 +25,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _sha1 struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
crypto.RegisterHash(crypto.SHA1, New)
|
crypto.RegisterHash(crypto.SHA1, New)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package sha256
|
package sha256
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"hash"
|
"hash"
|
||||||
@@ -26,6 +25,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _sha256 struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
crypto.RegisterHash(crypto.SHA224, New224)
|
crypto.RegisterHash(crypto.SHA224, New224)
|
||||||
crypto.RegisterHash(crypto.SHA256, New)
|
crypto.RegisterHash(crypto.SHA256, New)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package sha512
|
package sha512
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"hash"
|
"hash"
|
||||||
@@ -26,6 +25,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _sha512 struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
crypto.RegisterHash(crypto.SHA384, New384)
|
crypto.RegisterHash(crypto.SHA384, New384)
|
||||||
crypto.RegisterHash(crypto.SHA512, New)
|
crypto.RegisterHash(crypto.SHA512, New)
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package fmt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Errorf formats according to a format specifier and returns the string as a
|
|
||||||
// value that satisfies error.
|
|
||||||
//
|
|
||||||
// If the format specifier includes a %w verb with an error operand,
|
|
||||||
// the returned error will implement an Unwrap method returning the operand.
|
|
||||||
// If there is more than one %w verb, the returned error will implement an
|
|
||||||
// Unwrap method returning a []error containing all the %w operands in the
|
|
||||||
// order they appear in the arguments.
|
|
||||||
// It is invalid to supply the %w verb with an operand that does not implement
|
|
||||||
// the error interface. The %w verb is otherwise a synonym for %v.
|
|
||||||
func Errorf(format string, a ...any) error {
|
|
||||||
p := newPrinter()
|
|
||||||
p.wrapErrs = true
|
|
||||||
p.doPrintf(format, a)
|
|
||||||
s := string(p.buf)
|
|
||||||
var err error
|
|
||||||
switch len(p.wrappedErrs) {
|
|
||||||
case 0:
|
|
||||||
err = errors.New(s)
|
|
||||||
case 1:
|
|
||||||
w := &wrapError{msg: s}
|
|
||||||
w.err, _ = a[p.wrappedErrs[0]].(error)
|
|
||||||
err = w
|
|
||||||
default:
|
|
||||||
if p.reordered {
|
|
||||||
sort.Ints(p.wrappedErrs)
|
|
||||||
}
|
|
||||||
var errs []error
|
|
||||||
for i, argNum := range p.wrappedErrs {
|
|
||||||
if i > 0 && p.wrappedErrs[i-1] == argNum {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e, ok := a[argNum].(error); ok {
|
|
||||||
errs = append(errs, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = &wrapErrors{s, errs}
|
|
||||||
}
|
|
||||||
p.free()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type wrapError struct {
|
|
||||||
msg string
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *wrapError) Error() string {
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *wrapError) Unwrap() error {
|
|
||||||
return e.err
|
|
||||||
}
|
|
||||||
|
|
||||||
type wrapErrors struct {
|
|
||||||
msg string
|
|
||||||
errs []error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *wrapErrors) Error() string {
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *wrapErrors) Unwrap() []error {
|
|
||||||
return e.errs
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package fmt
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// // llgo:skipall
|
|
||||||
type _fmt struct{}
|
|
||||||
@@ -1,594 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package fmt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ldigits = "0123456789abcdefx"
|
|
||||||
udigits = "0123456789ABCDEFX"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
signed = true
|
|
||||||
unsigned = false
|
|
||||||
)
|
|
||||||
|
|
||||||
// flags placed in a separate struct for easy clearing.
|
|
||||||
type fmtFlags struct {
|
|
||||||
widPresent bool
|
|
||||||
precPresent bool
|
|
||||||
minus bool
|
|
||||||
plus bool
|
|
||||||
sharp bool
|
|
||||||
space bool
|
|
||||||
zero bool
|
|
||||||
|
|
||||||
// For the formats %+v %#v, we set the plusV/sharpV flags
|
|
||||||
// and clear the plus/sharp flags since %+v and %#v are in effect
|
|
||||||
// different, flagless formats set at the top level.
|
|
||||||
plusV bool
|
|
||||||
sharpV bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// A fmt is the raw formatter used by Printf etc.
|
|
||||||
// It prints into a buffer that must be set up separately.
|
|
||||||
type fmt struct {
|
|
||||||
buf *buffer
|
|
||||||
|
|
||||||
fmtFlags
|
|
||||||
|
|
||||||
wid int // width
|
|
||||||
prec int // precision
|
|
||||||
|
|
||||||
// intbuf is large enough to store %b of an int64 with a sign and
|
|
||||||
// avoids padding at the end of the struct on 32 bit architectures.
|
|
||||||
intbuf [68]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fmt) clearflags() {
|
|
||||||
f.fmtFlags = fmtFlags{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fmt) init(buf *buffer) {
|
|
||||||
f.buf = buf
|
|
||||||
f.clearflags()
|
|
||||||
}
|
|
||||||
|
|
||||||
// writePadding generates n bytes of padding.
|
|
||||||
func (f *fmt) writePadding(n int) {
|
|
||||||
if n <= 0 { // No padding bytes needed.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
buf := *f.buf
|
|
||||||
oldLen := len(buf)
|
|
||||||
newLen := oldLen + n
|
|
||||||
// Make enough room for padding.
|
|
||||||
if newLen > cap(buf) {
|
|
||||||
buf = make(buffer, cap(buf)*2+n)
|
|
||||||
copy(buf, *f.buf)
|
|
||||||
}
|
|
||||||
// Decide which byte the padding should be filled with.
|
|
||||||
padByte := byte(' ')
|
|
||||||
if f.zero {
|
|
||||||
padByte = byte('0')
|
|
||||||
}
|
|
||||||
// Fill padding with padByte.
|
|
||||||
padding := buf[oldLen:newLen]
|
|
||||||
for i := range padding {
|
|
||||||
padding[i] = padByte
|
|
||||||
}
|
|
||||||
*f.buf = buf[:newLen]
|
|
||||||
}
|
|
||||||
|
|
||||||
// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
|
|
||||||
func (f *fmt) pad(b []byte) {
|
|
||||||
if !f.widPresent || f.wid == 0 {
|
|
||||||
f.buf.write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
width := f.wid - utf8.RuneCount(b)
|
|
||||||
if !f.minus {
|
|
||||||
// left padding
|
|
||||||
f.writePadding(width)
|
|
||||||
f.buf.write(b)
|
|
||||||
} else {
|
|
||||||
// right padding
|
|
||||||
f.buf.write(b)
|
|
||||||
f.writePadding(width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
|
|
||||||
func (f *fmt) padString(s string) {
|
|
||||||
if !f.widPresent || f.wid == 0 {
|
|
||||||
f.buf.writeString(s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
width := f.wid - utf8.RuneCountInString(s)
|
|
||||||
if !f.minus {
|
|
||||||
// left padding
|
|
||||||
f.writePadding(width)
|
|
||||||
f.buf.writeString(s)
|
|
||||||
} else {
|
|
||||||
// right padding
|
|
||||||
f.buf.writeString(s)
|
|
||||||
f.writePadding(width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtBoolean formats a boolean.
|
|
||||||
func (f *fmt) fmtBoolean(v bool) {
|
|
||||||
if v {
|
|
||||||
f.padString("true")
|
|
||||||
} else {
|
|
||||||
f.padString("false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtUnicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
|
|
||||||
func (f *fmt) fmtUnicode(u uint64) {
|
|
||||||
buf := f.intbuf[0:]
|
|
||||||
|
|
||||||
// With default precision set the maximum needed buf length is 18
|
|
||||||
// for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
|
|
||||||
// into the already allocated intbuf with a capacity of 68 bytes.
|
|
||||||
prec := 4
|
|
||||||
if f.precPresent && f.prec > 4 {
|
|
||||||
prec = f.prec
|
|
||||||
// Compute space needed for "U+" , number, " '", character, "'".
|
|
||||||
width := 2 + prec + 2 + utf8.UTFMax + 1
|
|
||||||
if width > len(buf) {
|
|
||||||
buf = make([]byte, width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
|
|
||||||
i := len(buf)
|
|
||||||
|
|
||||||
// For %#U we want to add a space and a quoted character at the end of the buffer.
|
|
||||||
if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
|
|
||||||
i--
|
|
||||||
buf[i] = '\''
|
|
||||||
i -= utf8.RuneLen(rune(u))
|
|
||||||
utf8.EncodeRune(buf[i:], rune(u))
|
|
||||||
i--
|
|
||||||
buf[i] = '\''
|
|
||||||
i--
|
|
||||||
buf[i] = ' '
|
|
||||||
}
|
|
||||||
// Format the Unicode code point u as a hexadecimal number.
|
|
||||||
for u >= 16 {
|
|
||||||
i--
|
|
||||||
buf[i] = udigits[u&0xF]
|
|
||||||
prec--
|
|
||||||
u >>= 4
|
|
||||||
}
|
|
||||||
i--
|
|
||||||
buf[i] = udigits[u]
|
|
||||||
prec--
|
|
||||||
// Add zeros in front of the number until requested precision is reached.
|
|
||||||
for prec > 0 {
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
prec--
|
|
||||||
}
|
|
||||||
// Add a leading "U+".
|
|
||||||
i--
|
|
||||||
buf[i] = '+'
|
|
||||||
i--
|
|
||||||
buf[i] = 'U'
|
|
||||||
|
|
||||||
oldZero := f.zero
|
|
||||||
f.zero = false
|
|
||||||
f.pad(buf[i:])
|
|
||||||
f.zero = oldZero
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtInteger formats signed and unsigned integers.
|
|
||||||
func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
|
|
||||||
negative := isSigned && int64(u) < 0
|
|
||||||
if negative {
|
|
||||||
u = -u
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := f.intbuf[0:]
|
|
||||||
// The already allocated f.intbuf with a capacity of 68 bytes
|
|
||||||
// is large enough for integer formatting when no precision or width is set.
|
|
||||||
if f.widPresent || f.precPresent {
|
|
||||||
// Account 3 extra bytes for possible addition of a sign and "0x".
|
|
||||||
width := 3 + f.wid + f.prec // wid and prec are always positive.
|
|
||||||
if width > len(buf) {
|
|
||||||
// We're going to need a bigger boat.
|
|
||||||
buf = make([]byte, width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Two ways to ask for extra leading zero digits: %.3d or %03d.
|
|
||||||
// If both are specified the f.zero flag is ignored and
|
|
||||||
// padding with spaces is used instead.
|
|
||||||
prec := 0
|
|
||||||
if f.precPresent {
|
|
||||||
prec = f.prec
|
|
||||||
// Precision of 0 and value of 0 means "print nothing" but padding.
|
|
||||||
if prec == 0 && u == 0 {
|
|
||||||
oldZero := f.zero
|
|
||||||
f.zero = false
|
|
||||||
f.writePadding(f.wid)
|
|
||||||
f.zero = oldZero
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if f.zero && f.widPresent {
|
|
||||||
prec = f.wid
|
|
||||||
if negative || f.plus || f.space {
|
|
||||||
prec-- // leave room for sign
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Because printing is easier right-to-left: format u into buf, ending at buf[i].
|
|
||||||
// We could make things marginally faster by splitting the 32-bit case out
|
|
||||||
// into a separate block but it's not worth the duplication, so u has 64 bits.
|
|
||||||
i := len(buf)
|
|
||||||
// Use constants for the division and modulo for more efficient code.
|
|
||||||
// Switch cases ordered by popularity.
|
|
||||||
switch base {
|
|
||||||
case 10:
|
|
||||||
for u >= 10 {
|
|
||||||
i--
|
|
||||||
next := u / 10
|
|
||||||
buf[i] = byte('0' + u - next*10)
|
|
||||||
u = next
|
|
||||||
}
|
|
||||||
case 16:
|
|
||||||
for u >= 16 {
|
|
||||||
i--
|
|
||||||
buf[i] = digits[u&0xF]
|
|
||||||
u >>= 4
|
|
||||||
}
|
|
||||||
case 8:
|
|
||||||
for u >= 8 {
|
|
||||||
i--
|
|
||||||
buf[i] = byte('0' + u&7)
|
|
||||||
u >>= 3
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
for u >= 2 {
|
|
||||||
i--
|
|
||||||
buf[i] = byte('0' + u&1)
|
|
||||||
u >>= 1
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("fmt: unknown base; can't happen")
|
|
||||||
}
|
|
||||||
i--
|
|
||||||
buf[i] = digits[u]
|
|
||||||
for i > 0 && prec > len(buf)-i {
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Various prefixes: 0x, -, etc.
|
|
||||||
if f.sharp {
|
|
||||||
switch base {
|
|
||||||
case 2:
|
|
||||||
// Add a leading 0b.
|
|
||||||
i--
|
|
||||||
buf[i] = 'b'
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
case 8:
|
|
||||||
if buf[i] != '0' {
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
}
|
|
||||||
case 16:
|
|
||||||
// Add a leading 0x or 0X.
|
|
||||||
i--
|
|
||||||
buf[i] = digits[16]
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if verb == 'O' {
|
|
||||||
i--
|
|
||||||
buf[i] = 'o'
|
|
||||||
i--
|
|
||||||
buf[i] = '0'
|
|
||||||
}
|
|
||||||
|
|
||||||
if negative {
|
|
||||||
i--
|
|
||||||
buf[i] = '-'
|
|
||||||
} else if f.plus {
|
|
||||||
i--
|
|
||||||
buf[i] = '+'
|
|
||||||
} else if f.space {
|
|
||||||
i--
|
|
||||||
buf[i] = ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
// Left padding with zeros has already been handled like precision earlier
|
|
||||||
// or the f.zero flag is ignored due to an explicitly set precision.
|
|
||||||
oldZero := f.zero
|
|
||||||
f.zero = false
|
|
||||||
f.pad(buf[i:])
|
|
||||||
f.zero = oldZero
|
|
||||||
}
|
|
||||||
|
|
||||||
// truncateString truncates the string s to the specified precision, if present.
|
|
||||||
func (f *fmt) truncateString(s string) string {
|
|
||||||
if f.precPresent {
|
|
||||||
n := f.prec
|
|
||||||
for i := range s {
|
|
||||||
n--
|
|
||||||
if n < 0 {
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// truncate truncates the byte slice b as a string of the specified precision, if present.
|
|
||||||
func (f *fmt) truncate(b []byte) []byte {
|
|
||||||
if f.precPresent {
|
|
||||||
n := f.prec
|
|
||||||
for i := 0; i < len(b); {
|
|
||||||
n--
|
|
||||||
if n < 0 {
|
|
||||||
return b[:i]
|
|
||||||
}
|
|
||||||
wid := 1
|
|
||||||
if b[i] >= utf8.RuneSelf {
|
|
||||||
_, wid = utf8.DecodeRune(b[i:])
|
|
||||||
}
|
|
||||||
i += wid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtS formats a string.
|
|
||||||
func (f *fmt) fmtS(s string) {
|
|
||||||
s = f.truncateString(s)
|
|
||||||
f.padString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtBs formats the byte slice b as if it was formatted as string with fmtS.
|
|
||||||
func (f *fmt) fmtBs(b []byte) {
|
|
||||||
b = f.truncate(b)
|
|
||||||
f.pad(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtSbx formats a string or byte slice as a hexadecimal encoding of its bytes.
|
|
||||||
func (f *fmt) fmtSbx(s string, b []byte, digits string) {
|
|
||||||
length := len(b)
|
|
||||||
if b == nil {
|
|
||||||
// No byte slice present. Assume string s should be encoded.
|
|
||||||
length = len(s)
|
|
||||||
}
|
|
||||||
// Set length to not process more bytes than the precision demands.
|
|
||||||
if f.precPresent && f.prec < length {
|
|
||||||
length = f.prec
|
|
||||||
}
|
|
||||||
// Compute width of the encoding taking into account the f.sharp and f.space flag.
|
|
||||||
width := 2 * length
|
|
||||||
if width > 0 {
|
|
||||||
if f.space {
|
|
||||||
// Each element encoded by two hexadecimals will get a leading 0x or 0X.
|
|
||||||
if f.sharp {
|
|
||||||
width *= 2
|
|
||||||
}
|
|
||||||
// Elements will be separated by a space.
|
|
||||||
width += length - 1
|
|
||||||
} else if f.sharp {
|
|
||||||
// Only a leading 0x or 0X will be added for the whole string.
|
|
||||||
width += 2
|
|
||||||
}
|
|
||||||
} else { // The byte slice or string that should be encoded is empty.
|
|
||||||
if f.widPresent {
|
|
||||||
f.writePadding(f.wid)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Handle padding to the left.
|
|
||||||
if f.widPresent && f.wid > width && !f.minus {
|
|
||||||
f.writePadding(f.wid - width)
|
|
||||||
}
|
|
||||||
// Write the encoding directly into the output buffer.
|
|
||||||
buf := *f.buf
|
|
||||||
if f.sharp {
|
|
||||||
// Add leading 0x or 0X.
|
|
||||||
buf = append(buf, '0', digits[16])
|
|
||||||
}
|
|
||||||
var c byte
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
if f.space && i > 0 {
|
|
||||||
// Separate elements with a space.
|
|
||||||
buf = append(buf, ' ')
|
|
||||||
if f.sharp {
|
|
||||||
// Add leading 0x or 0X for each element.
|
|
||||||
buf = append(buf, '0', digits[16])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if b != nil {
|
|
||||||
c = b[i] // Take a byte from the input byte slice.
|
|
||||||
} else {
|
|
||||||
c = s[i] // Take a byte from the input string.
|
|
||||||
}
|
|
||||||
// Encode each byte as two hexadecimal digits.
|
|
||||||
buf = append(buf, digits[c>>4], digits[c&0xF])
|
|
||||||
}
|
|
||||||
*f.buf = buf
|
|
||||||
// Handle padding to the right.
|
|
||||||
if f.widPresent && f.wid > width && f.minus {
|
|
||||||
f.writePadding(f.wid - width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtSx formats a string as a hexadecimal encoding of its bytes.
|
|
||||||
func (f *fmt) fmtSx(s, digits string) {
|
|
||||||
f.fmtSbx(s, nil, digits)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtBx formats a byte slice as a hexadecimal encoding of its bytes.
|
|
||||||
func (f *fmt) fmtBx(b []byte, digits string) {
|
|
||||||
f.fmtSbx("", b, digits)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtQ formats a string as a double-quoted, escaped Go string constant.
|
|
||||||
// If f.sharp is set a raw (backquoted) string may be returned instead
|
|
||||||
// if the string does not contain any control characters other than tab.
|
|
||||||
func (f *fmt) fmtQ(s string) {
|
|
||||||
s = f.truncateString(s)
|
|
||||||
if f.sharp && strconv.CanBackquote(s) {
|
|
||||||
f.padString("`" + s + "`")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
buf := f.intbuf[:0]
|
|
||||||
if f.plus {
|
|
||||||
f.pad(strconv.AppendQuoteToASCII(buf, s))
|
|
||||||
} else {
|
|
||||||
f.pad(strconv.AppendQuote(buf, s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtC formats an integer as a Unicode character.
|
|
||||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
|
||||||
func (f *fmt) fmtC(c uint64) {
|
|
||||||
// Explicitly check whether c exceeds utf8.MaxRune since the conversion
|
|
||||||
// of a uint64 to a rune may lose precision that indicates an overflow.
|
|
||||||
r := rune(c)
|
|
||||||
if c > utf8.MaxRune {
|
|
||||||
r = utf8.RuneError
|
|
||||||
}
|
|
||||||
buf := f.intbuf[:0]
|
|
||||||
f.pad(utf8.AppendRune(buf, r))
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtQc formats an integer as a single-quoted, escaped Go character constant.
|
|
||||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
|
||||||
func (f *fmt) fmtQc(c uint64) {
|
|
||||||
r := rune(c)
|
|
||||||
if c > utf8.MaxRune {
|
|
||||||
r = utf8.RuneError
|
|
||||||
}
|
|
||||||
buf := f.intbuf[:0]
|
|
||||||
if f.plus {
|
|
||||||
f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
|
|
||||||
} else {
|
|
||||||
f.pad(strconv.AppendQuoteRune(buf, r))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmtFloat formats a float64. It assumes that verb is a valid format specifier
|
|
||||||
// for strconv.AppendFloat and therefore fits into a byte.
|
|
||||||
func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
|
|
||||||
// Explicit precision in format specifier overrules default precision.
|
|
||||||
if f.precPresent {
|
|
||||||
prec = f.prec
|
|
||||||
}
|
|
||||||
// Format number, reserving space for leading + sign if needed.
|
|
||||||
num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
|
|
||||||
if num[1] == '-' || num[1] == '+' {
|
|
||||||
num = num[1:]
|
|
||||||
} else {
|
|
||||||
num[0] = '+'
|
|
||||||
}
|
|
||||||
// f.space means to add a leading space instead of a "+" sign unless
|
|
||||||
// the sign is explicitly asked for by f.plus.
|
|
||||||
if f.space && num[0] == '+' && !f.plus {
|
|
||||||
num[0] = ' '
|
|
||||||
}
|
|
||||||
// Special handling for infinities and NaN,
|
|
||||||
// which don't look like a number so shouldn't be padded with zeros.
|
|
||||||
if num[1] == 'I' || num[1] == 'N' {
|
|
||||||
oldZero := f.zero
|
|
||||||
f.zero = false
|
|
||||||
// Remove sign before NaN if not asked for.
|
|
||||||
if num[1] == 'N' && !f.space && !f.plus {
|
|
||||||
num = num[1:]
|
|
||||||
}
|
|
||||||
f.pad(num)
|
|
||||||
f.zero = oldZero
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// The sharp flag forces printing a decimal point for non-binary formats
|
|
||||||
// and retains trailing zeros, which we may need to restore.
|
|
||||||
if f.sharp && verb != 'b' {
|
|
||||||
digits := 0
|
|
||||||
switch verb {
|
|
||||||
case 'v', 'g', 'G', 'x':
|
|
||||||
digits = prec
|
|
||||||
// If no precision is set explicitly use a precision of 6.
|
|
||||||
if digits == -1 {
|
|
||||||
digits = 6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer pre-allocated with enough room for
|
|
||||||
// exponent notations of the form "e+123" or "p-1023".
|
|
||||||
var tailBuf [6]byte
|
|
||||||
tail := tailBuf[:0]
|
|
||||||
|
|
||||||
hasDecimalPoint := false
|
|
||||||
sawNonzeroDigit := false
|
|
||||||
// Starting from i = 1 to skip sign at num[0].
|
|
||||||
for i := 1; i < len(num); i++ {
|
|
||||||
switch num[i] {
|
|
||||||
case '.':
|
|
||||||
hasDecimalPoint = true
|
|
||||||
case 'p', 'P':
|
|
||||||
tail = append(tail, num[i:]...)
|
|
||||||
num = num[:i]
|
|
||||||
case 'e', 'E':
|
|
||||||
if verb != 'x' && verb != 'X' {
|
|
||||||
tail = append(tail, num[i:]...)
|
|
||||||
num = num[:i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
if num[i] != '0' {
|
|
||||||
sawNonzeroDigit = true
|
|
||||||
}
|
|
||||||
// Count significant digits after the first non-zero digit.
|
|
||||||
if sawNonzeroDigit {
|
|
||||||
digits--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !hasDecimalPoint {
|
|
||||||
// Leading digit 0 should contribute once to digits.
|
|
||||||
if len(num) == 2 && num[1] == '0' {
|
|
||||||
digits--
|
|
||||||
}
|
|
||||||
num = append(num, '.')
|
|
||||||
}
|
|
||||||
for digits > 0 {
|
|
||||||
num = append(num, '0')
|
|
||||||
digits--
|
|
||||||
}
|
|
||||||
num = append(num, tail...)
|
|
||||||
}
|
|
||||||
// We want a sign if asked for and if the sign is not positive.
|
|
||||||
if f.plus || num[0] != '+' {
|
|
||||||
// If we're zero padding to the left we want the sign before the leading zeros.
|
|
||||||
// Achieve this by writing the sign out and then padding the unsigned number.
|
|
||||||
if f.zero && f.widPresent && f.wid > len(num) {
|
|
||||||
f.buf.writeByte(num[0])
|
|
||||||
f.writePadding(f.wid - len(num))
|
|
||||||
f.buf.write(num[1:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f.pad(num)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// No sign to show and the number is positive; just print the unsigned number.
|
|
||||||
f.pad(num[1:])
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package crc32
|
package crc32
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"hash"
|
"hash"
|
||||||
|
|
||||||
@@ -24,6 +23,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/zlib"
|
"github.com/goplus/llgo/runtime/internal/clite/zlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _crc32 struct{}
|
||||||
|
|
||||||
// The size of a CRC-32 checksum in bytes.
|
// The size of a CRC-32 checksum in bytes.
|
||||||
const Size = 4
|
const Size = 4
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,28 @@
|
|||||||
|
|
||||||
package abi
|
package abi
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llgo/runtime/abi"
|
"github.com/goplus/llgo/runtime/abi"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _abi struct{}
|
||||||
|
|
||||||
type InterfaceType = abi.InterfaceType
|
type InterfaceType = abi.InterfaceType
|
||||||
|
|
||||||
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
||||||
x := uintptr(p)
|
x := uintptr(p)
|
||||||
return unsafe.Pointer(x ^ 0)
|
return unsafe.Pointer(x ^ 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FuncPCABI0(f interface{}) uintptr {
|
||||||
|
words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f))
|
||||||
|
return *(*uintptr)(unsafe.Pointer(words[1]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuncPCABIInternal(f interface{}) uintptr {
|
||||||
|
words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f))
|
||||||
|
return *(*uintptr)(unsafe.Pointer(words[1]))
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package bytealg
|
package bytealg
|
||||||
|
|
||||||
// llgo:skip init CompareString
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -24,6 +23,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/runtime"
|
"github.com/goplus/llgo/runtime/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skip init CompareString
|
||||||
|
type _bytealg struct{}
|
||||||
|
|
||||||
func IndexByte(b []byte, ch byte) int {
|
func IndexByte(b []byte, ch byte) int {
|
||||||
ptr := unsafe.Pointer(unsafe.SliceData(b))
|
ptr := unsafe.Pointer(unsafe.SliceData(b))
|
||||||
ret := c.Memchr(ptr, c.Int(ch), uintptr(len(b)))
|
ret := c.Memchr(ptr, c.Int(ch), uintptr(len(b)))
|
||||||
|
|||||||
1
runtime/internal/lib/internal/cpu/cpu.go
Normal file
1
runtime/internal/lib/internal/cpu/cpu.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package cpu
|
||||||
40
runtime/internal/lib/internal/cpu/cpu_x86.go
Normal file
40
runtime/internal/lib/internal/cpu/cpu_x86.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//go:build 386 || amd64
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
static void getcpuid(unsigned int eax, unsigned int ecx,
|
||||||
|
unsigned int *a, unsigned int *b,
|
||||||
|
unsigned int *c, unsigned int *d) {
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"pushq %%rbp\n\t"
|
||||||
|
"movq %%rsp, %%rbp\n\t"
|
||||||
|
"andq $-16, %%rsp\n\t" // 16-byte align stack
|
||||||
|
"cpuid\n\t"
|
||||||
|
"movq %%rbp, %%rsp\n\t"
|
||||||
|
"popq %%rbp\n\t"
|
||||||
|
: "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
|
||||||
|
: "a"(eax), "c"(ecx)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error This code requires GCC or Clang
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) {
|
||||||
|
C.getcpuid(
|
||||||
|
C.uint(eaxArg),
|
||||||
|
C.uint(ecxArg),
|
||||||
|
(*C.uint)(&eax),
|
||||||
|
(*C.uint)(&ebx),
|
||||||
|
(*C.uint)(&ecx),
|
||||||
|
(*C.uint)(&edx),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -8,12 +8,14 @@
|
|||||||
// that are valid map keys.
|
// that are valid map keys.
|
||||||
package fmtsort
|
package fmtsort
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _fmtsort struct{}
|
||||||
|
|
||||||
// Note: Throughout this package we avoid calling reflect.Value.Interface as
|
// Note: Throughout this package we avoid calling reflect.Value.Interface as
|
||||||
// it is not always legal to do so and it's easier to avoid the issue than to face it.
|
// it is not always legal to do so and it's easier to avoid the issue than to face it.
|
||||||
|
|
||||||
|
|||||||
13
runtime/internal/lib/internal/godebug/godebug.go
Normal file
13
runtime/internal/lib/internal/godebug/godebug.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package godebug
|
||||||
|
|
||||||
|
func setUpdate(update func(string, string)) {
|
||||||
|
println("todo: godebug.setUpdate")
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerMetric(name string, read func() uint64) {
|
||||||
|
println("todo: godebug.registerMetric")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNewIncNonDefault(newIncNonDefault func(string) func()) {
|
||||||
|
println("todo: godebug.setNewIncNonDefault")
|
||||||
|
}
|
||||||
@@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
// Simple conversions to avoid depending on strconv.
|
// Simple conversions to avoid depending on strconv.
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
package itoa
|
package itoa
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _itoa struct{}
|
||||||
|
|
||||||
// Itoa converts val to a decimal string.
|
// Itoa converts val to a decimal string.
|
||||||
func Itoa(val int) string {
|
func Itoa(val int) string {
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
// These types are defined here to permit the syscall package to reference them.
|
// These types are defined here to permit the syscall package to reference them.
|
||||||
package oserror
|
package oserror
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _oserror struct{}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalid = errors.New("invalid argument")
|
ErrInvalid = errors.New("invalid argument")
|
||||||
ErrPermission = errors.New("permission denied")
|
ErrPermission = errors.New("permission denied")
|
||||||
|
|||||||
45
runtime/internal/lib/internal/poll/poll.go
Normal file
45
runtime/internal/lib/internal/poll/poll.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package poll
|
||||||
|
|
||||||
|
func runtime_Semacquire(sema *uint32) {
|
||||||
|
panic("todo: poll.runtime_Semacquire")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_Semrelease(sema *uint32) {
|
||||||
|
panic("todo: poll.runtime_Semrelease")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollServerInit() {
|
||||||
|
panic("todo: poll.runtime_pollServerInit")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollOpen(fd uintptr) (uintptr, int) {
|
||||||
|
panic("todo: poll.runtime_pollOpen")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollClose(ctx uintptr) {
|
||||||
|
panic("todo: poll.runtime_pollClose")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollWait(ctx uintptr, mode int) int {
|
||||||
|
panic("todo: poll.runtime_pollWait")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollWaitCanceled(ctx uintptr, mode int) {
|
||||||
|
panic("todo: poll.runtime_pollWaitCanceled")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollReset(ctx uintptr, mode int) int {
|
||||||
|
panic("todo: poll.runtime_pollReset")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollSetDeadline(ctx uintptr, d int64, mode int) {
|
||||||
|
panic("todo: poll.runtime_pollSetDeadline")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_pollUnblock(ctx uintptr) {
|
||||||
|
panic("todo: poll.runtime_pollUnblock")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_isPollServerDescriptor(fd uintptr) bool {
|
||||||
|
panic("todo: poll.runtime_isPollServerDescriptor")
|
||||||
|
}
|
||||||
@@ -6,9 +6,11 @@
|
|||||||
|
|
||||||
package execenv
|
package execenv
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _execenv struct{}
|
||||||
|
|
||||||
// Default will return the default environment
|
// Default will return the default environment
|
||||||
// variables based on the process attributes
|
// variables based on the process attributes
|
||||||
// provided.
|
// provided.
|
||||||
|
|||||||
@@ -6,13 +6,15 @@
|
|||||||
|
|
||||||
package execenv
|
package execenv
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"internal/syscall/windows"
|
"internal/syscall/windows"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _execenv struct{}
|
||||||
|
|
||||||
// Default will return the default environment
|
// Default will return the default environment
|
||||||
// variables based on the process attributes
|
// variables based on the process attributes
|
||||||
// provided.
|
// provided.
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
struct fcntl_ret
|
||||||
|
{
|
||||||
|
int32_t r1; // Return value
|
||||||
|
int32_t err; // Error code
|
||||||
|
};
|
||||||
|
|
||||||
|
// llgo_fcntl implements the fcntl system call wrapper for Go
|
||||||
|
// fd: file descriptor
|
||||||
|
// cmd: fcntl command
|
||||||
|
// arg: command argument
|
||||||
|
struct fcntl_ret llgo_fcntl2(int32_t fd, int32_t cmd, int32_t arg)
|
||||||
|
{
|
||||||
|
struct fcntl_ret ret = {0};
|
||||||
|
int result = fcntl(fd, cmd, arg);
|
||||||
|
|
||||||
|
if (result == -1)
|
||||||
|
{
|
||||||
|
ret.err = errno;
|
||||||
|
ret.r1 = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret.err = 0;
|
||||||
|
ret.r1 = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -2,14 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build js && wasm
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
func IsNonblock(fd int) (nonblocking bool, err error) {
|
const (
|
||||||
return false, nil
|
AT_EACCESS = 0x10
|
||||||
}
|
AT_FDCWD = -0x2
|
||||||
|
AT_REMOVEDIR = 0x80
|
||||||
|
AT_SYMLINK_NOFOLLOW = 0x0020
|
||||||
|
|
||||||
func HasNonblockFlag(flag int) bool {
|
UTIME_OMIT = -0x2
|
||||||
return false
|
)
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
const unlinkatTrap uintptr = syscall.SYS_UNLINKAT
|
||||||
|
const openatTrap uintptr = syscall.SYS_OPENAT
|
||||||
|
|
||||||
|
const (
|
||||||
|
AT_EACCESS = 0x200
|
||||||
|
AT_FDCWD = -0x64
|
||||||
|
AT_REMOVEDIR = 0x200
|
||||||
|
AT_SYMLINK_NOFOLLOW = 0x100
|
||||||
|
|
||||||
|
UTIME_OMIT = 0x3ffffffe
|
||||||
|
)
|
||||||
18
runtime/internal/lib/internal/syscall/unix/constants.go
Normal file
18
runtime/internal/lib/internal/syscall/unix/constants.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
R_OK = 0x4
|
||||||
|
W_OK = 0x2
|
||||||
|
X_OK = 0x1
|
||||||
|
|
||||||
|
// NoFollowErrno is the error returned from open/openat called with
|
||||||
|
// O_NOFOLLOW flag, when the trailing component (basename) of the path
|
||||||
|
// is a symbolic link.
|
||||||
|
NoFollowErrno = noFollowErrno
|
||||||
|
)
|
||||||
23
runtime/internal/lib/internal/syscall/unix/fcntl_unix.go
Normal file
23
runtime/internal/lib/internal/syscall/unix/fcntl_unix.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// llgo:skip fcntl
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link"
|
||||||
|
LLGoFiles = "_unix/fcntl_unix.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname fcntl C.llgo_fcntl2
|
||||||
|
func fcntl(fd int32, cmd int32, arg int32) (int32, int32)
|
||||||
|
|
||||||
|
func Fcntl(fd int, cmd int, arg int) (int, error) {
|
||||||
|
val, errno := fcntl(int32(fd), int32(cmd), int32(arg))
|
||||||
|
if val == -1 {
|
||||||
|
return int(val), syscall.Errno(errno)
|
||||||
|
}
|
||||||
|
return int(val), nil
|
||||||
|
}
|
||||||
14
runtime/internal/lib/internal/syscall/unix/nofollow_bsd.go
Normal file
14
runtime/internal/lib/internal/syscall/unix/nofollow_bsd.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build dragonfly || freebsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// References:
|
||||||
|
// - https://man.freebsd.org/cgi/man.cgi?open(2)
|
||||||
|
// - https://man.dragonflybsd.org/?command=open§ion=2
|
||||||
|
const noFollowErrno = syscall.EMLINK
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// Reference: https://man.netbsd.org/open.2
|
||||||
|
const noFollowErrno = syscall.EFTYPE
|
||||||
22
runtime/internal/lib/internal/syscall/unix/nofollow_posix.go
Normal file
22
runtime/internal/lib/internal/syscall/unix/nofollow_posix.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build unix && !dragonfly && !freebsd && !netbsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// POSIX.1-2008 says it's ELOOP. Most platforms follow:
|
||||||
|
//
|
||||||
|
// - aix: O_NOFOLLOW not documented (https://www.ibm.com/docs/ssw_aix_73/o_bostechref/open.html), assuming ELOOP
|
||||||
|
// - android: see linux
|
||||||
|
// - darwin: https://github.com/apple/darwin-xnu/blob/main/bsd/man/man2/open.2
|
||||||
|
// - hurd: who knows if it works at all (https://www.gnu.org/software/hurd/open_issues/open_symlink.html)
|
||||||
|
// - illumos: https://illumos.org/man/2/open
|
||||||
|
// - ios: see darwin
|
||||||
|
// - linux: https://man7.org/linux/man-pages/man2/openat.2.html
|
||||||
|
// - openbsd: https://man.openbsd.org/open.2
|
||||||
|
// - solaris: https://docs.oracle.com/cd/E23824_01/html/821-1463/open-2.html
|
||||||
|
const noFollowErrno = syscall.ELOOP
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build unix
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import "github.com/goplus/llgo/runtime/internal/clite/syscall"
|
|
||||||
|
|
||||||
/* TODO(xsw):
|
|
||||||
func IsNonblock(fd int) (nonblocking bool, err error) {
|
|
||||||
flag, e1 := Fcntl(fd, syscall.F_GETFL, 0)
|
|
||||||
if e1 != nil {
|
|
||||||
return false, e1
|
|
||||||
}
|
|
||||||
return flag&syscall.O_NONBLOCK != 0, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func HasNonblockFlag(flag int) bool {
|
|
||||||
return flag&syscall.O_NONBLOCK != 0
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright 2023 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build wasip1
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import "github.com/goplus/llgo/runtime/internal/clite/syscall"
|
|
||||||
|
|
||||||
/* TODO(xsw):
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
_ "unsafe" // for go:linkname
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsNonblock(fd int) (nonblocking bool, err error) {
|
|
||||||
flags, e1 := fd_fdstat_get_flags(fd)
|
|
||||||
if e1 != nil {
|
|
||||||
return false, e1
|
|
||||||
}
|
|
||||||
return flags&syscall.FDFLAG_NONBLOCK != 0, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func HasNonblockFlag(flag int) bool {
|
|
||||||
return flag&syscall.FDFLAG_NONBLOCK != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO(xsw):
|
|
||||||
// This helper is implemented in the syscall package. It means we don't have
|
|
||||||
// to redefine the fd_fdstat_get host import or the fdstat struct it
|
|
||||||
// populates.
|
|
||||||
//
|
|
||||||
//-go:linkname fd_fdstat_get_flags syscall.fd_fdstat_get_flags
|
|
||||||
func fd_fdstat_get_flags(fd int) (uint32, error)
|
|
||||||
*/
|
|
||||||
@@ -17,8 +17,10 @@
|
|||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"syscall"
|
||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// llgo:skipall
|
func HasNonblockFlag(flag int) bool {
|
||||||
type _unix struct{}
|
return flag&syscall.O_NONBLOCK != 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package big
|
package big
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
@@ -24,6 +23,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
"github.com/goplus/llgo/runtime/internal/clite/openssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _big struct{}
|
||||||
|
|
||||||
// A Word represents a single digit of a multi-precision unsigned integer.
|
// A Word represents a single digit of a multi-precision unsigned integer.
|
||||||
type Word openssl.BN_ULONG
|
type Word openssl.BN_ULONG
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
// llgo:skip sin cos
|
|
||||||
import (
|
import (
|
||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
|
|
||||||
c "github.com/goplus/llgo/runtime/internal/clite"
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skip sin cos
|
||||||
const (
|
const (
|
||||||
LLGoPackage = true
|
LLGoPackage = true
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
// crypto/rand package.
|
// crypto/rand package.
|
||||||
package rand
|
package rand
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -28,6 +27,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/time"
|
"github.com/goplus/llgo/runtime/internal/clite/time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _rand struct{}
|
||||||
|
|
||||||
// A Source represents a source of uniformly-distributed
|
// A Source represents a source of uniformly-distributed
|
||||||
// pseudo-random int64 values in the range [0, 1<<63).
|
// pseudo-random int64 values in the range [0, 1<<63).
|
||||||
//
|
//
|
||||||
|
|||||||
180
runtime/internal/lib/os/dir.go
Normal file
180
runtime/internal/lib/os/dir.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"sort"
|
||||||
|
origSyscall "syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/os"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/lib/internal/bytealg"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/lib/syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
type readdirMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
readdirName readdirMode = iota
|
||||||
|
readdirDirEntry
|
||||||
|
readdirFileInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
type DirEntry = fs.DirEntry
|
||||||
|
|
||||||
|
func (f *File) Readdirnames(n int) (names []string, err error) {
|
||||||
|
if f == nil {
|
||||||
|
return nil, ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := f.ReadDir(n)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
names = make([]string, len(entries))
|
||||||
|
for i, entry := range entries {
|
||||||
|
names[i] = entry.Name()
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func open(path string, flag int, perm uint32) (int, error) {
|
||||||
|
fd, err := syscall.Open(path, flag, perm)
|
||||||
|
return fd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func openDirNolog(name string) (*File, error) {
|
||||||
|
var (
|
||||||
|
r int
|
||||||
|
e error
|
||||||
|
)
|
||||||
|
ignoringEINTR(func() error {
|
||||||
|
r, e = open(name, O_RDONLY|origSyscall.O_CLOEXEC, 0)
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
if e != nil {
|
||||||
|
return nil, &PathError{Op: "open", Path: name, Err: e}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !supportsCloseOnExec {
|
||||||
|
origSyscall.CloseOnExec(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
f := newFile(r, name, kindNoPoll)
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func openDir(name string) (*File, error) {
|
||||||
|
return openDirNolog(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadDir(name string) ([]DirEntry, error) {
|
||||||
|
f, err := openDir(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
dirs, err := f.ReadDir(-1)
|
||||||
|
sort.Slice(dirs, func(i, j int) bool {
|
||||||
|
return bytealg.CompareString(dirs[i].Name(), dirs[j].Name()) < 0
|
||||||
|
})
|
||||||
|
return dirs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname c_fdopendir C.fdopendir
|
||||||
|
func c_fdopendir(fd c.Int) uintptr
|
||||||
|
|
||||||
|
func fdopendir(fd int) (dir uintptr, err error) {
|
||||||
|
return c_fdopendir(c.Int(fd)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname c_closedir C.closedir
|
||||||
|
func c_closedir(dir uintptr) c.Int
|
||||||
|
|
||||||
|
func closedir(dir uintptr) error {
|
||||||
|
if c_closedir(dir) != 0 {
|
||||||
|
return syscall.Errno(os.Errno())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname c_readdir C.readdir
|
||||||
|
func c_readdir(dir uintptr) ([]syscall.Dirent, error)
|
||||||
|
|
||||||
|
func readdir(dir uintptr) ([]syscall.Dirent, error) {
|
||||||
|
return c_readdir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) ReadDir(n int) (dirents []DirEntry, err error) {
|
||||||
|
if f == nil {
|
||||||
|
return nil, ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open directory using file descriptor
|
||||||
|
dir, err := fdopendir(int(f.fd))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer closedir(dir)
|
||||||
|
|
||||||
|
// Match Readdir and Readdirnames: don't return nil slices.
|
||||||
|
dirents = []DirEntry{}
|
||||||
|
|
||||||
|
// Read directory entries
|
||||||
|
for n < 0 || len(dirents) < n {
|
||||||
|
entries, err := readdir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return dirents, err
|
||||||
|
}
|
||||||
|
if len(entries) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
// Convert syscall.Dirent to fs.DirEntry
|
||||||
|
name := bytesToString((*[1024]byte)(unsafe.Pointer(&entry.Name[0]))[:])
|
||||||
|
if name == "." || name == ".." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
typ := fs.FileMode(0)
|
||||||
|
switch entry.Type {
|
||||||
|
case origSyscall.DT_REG:
|
||||||
|
typ = 0
|
||||||
|
case origSyscall.DT_DIR:
|
||||||
|
typ = fs.ModeDir
|
||||||
|
case origSyscall.DT_LNK:
|
||||||
|
typ = fs.ModeSymlink
|
||||||
|
case origSyscall.DT_SOCK:
|
||||||
|
typ = fs.ModeSocket
|
||||||
|
case origSyscall.DT_FIFO:
|
||||||
|
typ = fs.ModeNamedPipe
|
||||||
|
case origSyscall.DT_CHR:
|
||||||
|
typ = fs.ModeCharDevice
|
||||||
|
case origSyscall.DT_BLK:
|
||||||
|
typ = fs.ModeDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
dirents = append(dirents, &unixDirent{
|
||||||
|
parent: f.name,
|
||||||
|
name: name,
|
||||||
|
typ: typ,
|
||||||
|
})
|
||||||
|
|
||||||
|
if n > 0 && len(dirents) >= n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirents, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bytesToString converts byte slice to string without allocation.
|
||||||
|
func bytesToString(b []byte) string {
|
||||||
|
var i int
|
||||||
|
for i = 0; i < len(b) && b[i] != 0; i++ {
|
||||||
|
}
|
||||||
|
return string(b[0:i])
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package exec
|
package exec
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
@@ -33,6 +32,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/lib/internal/syscall/execenv"
|
"github.com/goplus/llgo/runtime/internal/lib/internal/syscall/execenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _exec struct{}
|
||||||
|
|
||||||
// Error is returned by LookPath when it fails to classify a file as an
|
// Error is returned by LookPath when it fails to classify a file as an
|
||||||
// executable.
|
// executable.
|
||||||
type Error struct {
|
type Error struct {
|
||||||
|
|||||||
@@ -59,8 +59,12 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
|
|||||||
// runtime.KeepAlive(attr)
|
// runtime.KeepAlive(attr)
|
||||||
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, &PathError{Op: "fork/exec", Path: name, Err: e}
|
// TODO(lijie): workaround with type assertion
|
||||||
|
if r, ok := e.(syscall.Errno); !ok || r != 0 {
|
||||||
|
return nil, &PathError{Op: "fork/exec", Path: name, Err: e}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
println("StartProcess", pid, h, e)
|
||||||
|
|
||||||
return newProcess(pid, h), nil
|
return newProcess(pid, h), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -27,6 +26,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/os"
|
"github.com/goplus/llgo/runtime/internal/clite/os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _os struct{}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = true
|
LLGoPackage = true
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -53,3 +53,7 @@ func MkdirAll(path string, perm FileMode) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RemoveAll(path string) error {
|
||||||
|
return removeAll(path)
|
||||||
|
}
|
||||||
|
|||||||
222
runtime/internal/lib/os/removeall_at.go
Normal file
222
runtime/internal/lib/os/removeall_at.go
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
origSyscall "syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/os"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/lib/internal/syscall/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func removeAll(path string) error {
|
||||||
|
if path == "" {
|
||||||
|
// fail silently to retain compatibility with previous behavior
|
||||||
|
// of RemoveAll. See issue 28830.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rmdir system call does not permit removing ".",
|
||||||
|
// so we don't permit it either.
|
||||||
|
if endsWithDot(path) {
|
||||||
|
return &PathError{Op: "RemoveAll", Path: path, Err: origSyscall.EINVAL}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple case: if Remove works, we're done.
|
||||||
|
err := Remove(path)
|
||||||
|
if err == nil || IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAll recurses by deleting the path base from
|
||||||
|
// its parent directory
|
||||||
|
parentDir, base := splitPath(path)
|
||||||
|
|
||||||
|
parent, err := Open(parentDir)
|
||||||
|
if IsNotExist(err) {
|
||||||
|
// If parent does not exist, base cannot exist. Fail silently
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer parent.Close()
|
||||||
|
|
||||||
|
if err := removeAllFrom(parent, base); err != nil {
|
||||||
|
if pathErr, ok := err.(*PathError); ok {
|
||||||
|
pathErr.Path = parentDir + string(PathSeparator) + pathErr.Path
|
||||||
|
err = pathErr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAllFrom(parent *File, base string) error {
|
||||||
|
p, err := syscall.BytePtrFromString(base)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
parentFd := int(parent.Fd())
|
||||||
|
// Simple case: if Unlink (aka remove) works, we're done.
|
||||||
|
err = ignoringEINTR(func() error {
|
||||||
|
if os.Unlinkat(c.Int(parentFd), (*c.Char)(unsafe.Pointer(p)), 0) < 0 {
|
||||||
|
return origSyscall.Errno(os.Errno())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err == nil || IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EISDIR means that we have a directory, and we need to
|
||||||
|
// remove its contents.
|
||||||
|
// EPERM or EACCES means that we don't have write permission on
|
||||||
|
// the parent directory, but this entry might still be a directory
|
||||||
|
// whose contents need to be removed.
|
||||||
|
// Otherwise just return the error.
|
||||||
|
if err != origSyscall.EISDIR && err != origSyscall.EPERM && err != origSyscall.EACCES {
|
||||||
|
return &PathError{Op: "unlinkat", Path: base, Err: err}
|
||||||
|
}
|
||||||
|
uErr := err
|
||||||
|
|
||||||
|
// Remove the directory's entries.
|
||||||
|
var recurseErr error
|
||||||
|
for {
|
||||||
|
const reqSize = 1024
|
||||||
|
var respSize int
|
||||||
|
|
||||||
|
// Open the directory to recurse into
|
||||||
|
file, err := openDirAt(parentFd, base)
|
||||||
|
if err != nil {
|
||||||
|
if IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err == origSyscall.ENOTDIR || err == unix.NoFollowErrno {
|
||||||
|
// Not a directory; return the error from the unix.Unlinkat.
|
||||||
|
return &PathError{Op: "unlinkat", Path: base, Err: uErr}
|
||||||
|
}
|
||||||
|
recurseErr = &PathError{Op: "openfdat", Path: base, Err: err}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
numErr := 0
|
||||||
|
|
||||||
|
names, readErr := file.Readdirnames(reqSize)
|
||||||
|
// Errors other than EOF should stop us from continuing.
|
||||||
|
if readErr != nil && readErr != io.EOF {
|
||||||
|
file.Close()
|
||||||
|
if IsNotExist(readErr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &PathError{Op: "readdirnames", Path: base, Err: readErr}
|
||||||
|
}
|
||||||
|
|
||||||
|
respSize = len(names)
|
||||||
|
for _, name := range names {
|
||||||
|
err := removeAllFrom(file, name)
|
||||||
|
if err != nil {
|
||||||
|
if pathErr, ok := err.(*PathError); ok {
|
||||||
|
pathErr.Path = base + string(PathSeparator) + pathErr.Path
|
||||||
|
}
|
||||||
|
numErr++
|
||||||
|
if recurseErr == nil {
|
||||||
|
recurseErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can delete any entry, break to start new iteration.
|
||||||
|
// Otherwise, we discard current names, get next entries and try deleting them.
|
||||||
|
if numErr != reqSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removing files from the directory may have caused
|
||||||
|
// the OS to reshuffle it. Simply calling Readdirnames
|
||||||
|
// again may skip some entries. The only reliable way
|
||||||
|
// to avoid this is to close and re-open the
|
||||||
|
// directory. See issue 20841.
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
// Finish when the end of the directory is reached
|
||||||
|
if respSize < reqSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the directory itself.
|
||||||
|
unlinkError := ignoringEINTR(func() error {
|
||||||
|
if os.Unlinkat(c.Int(parentFd), (*c.Char)(unsafe.Pointer(p)), unix.AT_REMOVEDIR) < 0 {
|
||||||
|
return origSyscall.Errno(os.Errno())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if unlinkError == nil || IsNotExist(unlinkError) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if recurseErr != nil {
|
||||||
|
return recurseErr
|
||||||
|
}
|
||||||
|
return &PathError{Op: "unlinkat", Path: base, Err: unlinkError}
|
||||||
|
}
|
||||||
|
|
||||||
|
// openDirAt opens a directory name relative to the directory referred to by
|
||||||
|
// the file descriptor dirfd. If name is anything but a directory (this
|
||||||
|
// includes a symlink to one), it should return an error. Other than that this
|
||||||
|
// should act like openFileNolog.
|
||||||
|
//
|
||||||
|
// This acts like openFileNolog rather than OpenFile because
|
||||||
|
// we are going to (try to) remove the file.
|
||||||
|
// The contents of this file are not relevant for test caching.
|
||||||
|
func openDirAt(dirfd int, name string) (*File, error) {
|
||||||
|
p, err := syscall.BytePtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var r int
|
||||||
|
for {
|
||||||
|
var e error
|
||||||
|
r = int(os.Openat(c.Int(dirfd), (*c.Char)(unsafe.Pointer(p)), origSyscall.O_RDONLY|origSyscall.O_CLOEXEC|origSyscall.O_DIRECTORY|origSyscall.O_NOFOLLOW, 0))
|
||||||
|
if r >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
e = origSyscall.Errno(r)
|
||||||
|
|
||||||
|
// See comment in openFileNolog.
|
||||||
|
if e == origSyscall.EINTR {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
if !supportsCloseOnExec {
|
||||||
|
origSyscall.CloseOnExec(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use kindNoPoll because we know that this is a directory.
|
||||||
|
return newFile(r, name, kindNoPoll), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// endsWithDot reports whether the final component of path is ".".
|
||||||
|
func endsWithDot(path string) bool {
|
||||||
|
if path == "." {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
142
runtime/internal/lib/os/removeall_noat.go
Normal file
142
runtime/internal/lib/os/removeall_noat.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !unix
|
||||||
|
|
||||||
|
package os
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func removeAll(path string) error {
|
||||||
|
if path == "" {
|
||||||
|
// fail silently to retain compatibility with previous behavior
|
||||||
|
// of RemoveAll. See issue 28830.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rmdir system call permits removing "." on Plan 9,
|
||||||
|
// so we don't permit it to remain consistent with the
|
||||||
|
// "at" implementation of RemoveAll.
|
||||||
|
if endsWithDot(path) {
|
||||||
|
return &PathError{Op: "RemoveAll", Path: path, Err: syscall.EINVAL}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple case: if Remove works, we're done.
|
||||||
|
err := Remove(path)
|
||||||
|
if err == nil || IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, is this a directory we need to recurse into?
|
||||||
|
dir, serr := Lstat(path)
|
||||||
|
if serr != nil {
|
||||||
|
if serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return serr
|
||||||
|
}
|
||||||
|
if !dir.IsDir() {
|
||||||
|
// Not a directory; return the error from Remove.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove contents & return first error.
|
||||||
|
err = nil
|
||||||
|
for {
|
||||||
|
fd, err := Open(path)
|
||||||
|
if err != nil {
|
||||||
|
if IsNotExist(err) {
|
||||||
|
// Already deleted by someone else.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqSize = 1024
|
||||||
|
var names []string
|
||||||
|
var readErr error
|
||||||
|
|
||||||
|
for {
|
||||||
|
numErr := 0
|
||||||
|
names, readErr = fd.Readdirnames(reqSize)
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
err1 := RemoveAll(path + string(PathSeparator) + name)
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
if err1 != nil {
|
||||||
|
numErr++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can delete any entry, break to start new iteration.
|
||||||
|
// Otherwise, we discard current names, get next entries and try deleting them.
|
||||||
|
if numErr != reqSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removing files from the directory may have caused
|
||||||
|
// the OS to reshuffle it. Simply calling Readdirnames
|
||||||
|
// again may skip some entries. The only reliable way
|
||||||
|
// to avoid this is to close and re-open the
|
||||||
|
// directory. See issue 20841.
|
||||||
|
fd.Close()
|
||||||
|
|
||||||
|
if readErr == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// If Readdirnames returned an error, use it.
|
||||||
|
if err == nil {
|
||||||
|
err = readErr
|
||||||
|
}
|
||||||
|
if len(names) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to re-open unnecessarily, so if we
|
||||||
|
// got fewer than request names from Readdirnames, try
|
||||||
|
// simply removing the directory now. If that
|
||||||
|
// succeeds, we are done.
|
||||||
|
if len(names) < reqSize {
|
||||||
|
err1 := Remove(path)
|
||||||
|
if err1 == nil || IsNotExist(err1) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// We got some error removing the
|
||||||
|
// directory contents, and since we
|
||||||
|
// read fewer names than we requested
|
||||||
|
// there probably aren't more files to
|
||||||
|
// remove. Don't loop around to read
|
||||||
|
// the directory again. We'll probably
|
||||||
|
// just get the same error.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove directory.
|
||||||
|
err1 := Remove(path)
|
||||||
|
if err1 == nil || IsNotExist(err1) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" && IsPermission(err1) {
|
||||||
|
if fs, err := Stat(path); err == nil {
|
||||||
|
if err = Chmod(path, FileMode(0200|int(fs.Mode()))); err == nil {
|
||||||
|
err1 = Remove(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
25
runtime/internal/lib/os/signal/signal.go
Normal file
25
runtime/internal/lib/os/signal/signal.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package signal
|
||||||
|
|
||||||
|
func signal_disable(uint32) {
|
||||||
|
panic("signal_disable not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signal_enable(uint32) {
|
||||||
|
panic("signal_enable not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signal_ignore(uint32) {
|
||||||
|
panic("signal_ignore not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signal_ignored(uint32) bool {
|
||||||
|
panic("signal_ignored not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signal_recv() uint32 {
|
||||||
|
panic("signal_recv not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signalWaitUntilIdle() {
|
||||||
|
panic("signalWaitUntilIdle not implemented")
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ package os
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/goplus/llgo/runtime/internal/lib/syscall"
|
"github.com/goplus/llgo/runtime/internal/clite/syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
|
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
|
||||||
|
|||||||
5
runtime/internal/lib/runtime/debug/debug.go
Normal file
5
runtime/internal/lib/runtime/debug/debug.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package debug
|
||||||
|
|
||||||
|
func SetTraceback(level string) {
|
||||||
|
panic("todo: runtime/debug.SetTraceback")
|
||||||
|
}
|
||||||
@@ -7,3 +7,7 @@ package runtime
|
|||||||
func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
|
func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
|
||||||
panic("todo: runtime.Caller")
|
panic("todo: runtime.Caller")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Callers(skip int, pc []uintptr) int {
|
||||||
|
panic("todo: runtime.Callers")
|
||||||
|
}
|
||||||
|
|||||||
6
runtime/internal/lib/runtime/internal/syscall/syscall.go
Normal file
6
runtime/internal/lib/runtime/internal/syscall/syscall.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package syscall
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _syscall6 struct{}
|
||||||
24
runtime/internal/lib/runtime/pprof/pprof.go
Normal file
24
runtime/internal/lib/runtime/pprof/pprof.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package pprof
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type Profile struct{}
|
||||||
|
|
||||||
|
func (p *Profile) WriteTo(w io.Writer, verbose bool) (int, error) {
|
||||||
|
panic("WriteTo not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartCPUProfile(w io.Writer) error {
|
||||||
|
panic("StartCPUProfile not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopCPUProfile() {
|
||||||
|
panic("StopCPUProfile not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lookup(name string) *Profile {
|
||||||
|
panic("Lookup not implemented")
|
||||||
|
}
|
||||||
@@ -16,8 +16,22 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int llgo_maxprocs() {
|
||||||
|
#ifdef _SC_NPROCESSORS_ONLN
|
||||||
|
return (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
import (
|
import (
|
||||||
_ "unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/pthread"
|
||||||
)
|
)
|
||||||
|
|
||||||
// llgo:skipall
|
// llgo:skipall
|
||||||
@@ -27,12 +41,23 @@ type _runtime struct{}
|
|||||||
// GOROOT environment variable, if set at process start,
|
// GOROOT environment variable, if set at process start,
|
||||||
// or else the root used during the Go build.
|
// or else the root used during the Go build.
|
||||||
func GOROOT() string {
|
func GOROOT() string {
|
||||||
/*
|
return ""
|
||||||
s := gogetenv("GOROOT")
|
}
|
||||||
if s != "" {
|
|
||||||
return s
|
//go:linkname c_maxprocs C.llgo_maxprocs
|
||||||
}
|
func c_maxprocs() int32
|
||||||
return defaultGOROOT
|
|
||||||
*/
|
func GOMAXPROCS(n int) int {
|
||||||
panic("todo: GOROOT")
|
return int(c_maxprocs())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Goexit() {
|
||||||
|
pthread.Exit(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeepAlive(x any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(fd uintptr, p unsafe.Pointer, n int32) int32 {
|
||||||
|
return int32(C.write(C.int(fd), p, C.size_t(n)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
// Layout of in-memory per-function information prepared by linker
|
// Layout of in-memory per-function information prepared by linker
|
||||||
// See https://golang.org/s/go12symtab.
|
// See https://golang.org/s/go12symtab.
|
||||||
// Keep in sync with linker (../cmd/link/internal/ld/pcln.go:/pclntab)
|
// Keep in sync with linker (../cmd/link/internal/ld/pcln.go:/pclntab)
|
||||||
@@ -11,3 +15,33 @@ package runtime
|
|||||||
type _func struct {
|
type _func struct {
|
||||||
unused [8]byte
|
unused [8]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Stack(buf []byte, all bool) int {
|
||||||
|
panic("todo: runtime.Stack")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartTrace() error {
|
||||||
|
panic("todo: runtime.StartTrace")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadTrace() []byte {
|
||||||
|
panic("todo: runtime.ReadTrace")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopTrace() {
|
||||||
|
panic("todo: runtime.StopTrace")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadMemStats(m *runtime.MemStats) {
|
||||||
|
panic("todo: runtime.ReadMemStats")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetMutexProfileFraction(rate int) int {
|
||||||
|
panic("todo: runtime.SetMutexProfileFraction")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBlockProfileRate(rate int) {
|
||||||
|
panic("todo: runtime.SetBlockProfileRate")
|
||||||
|
}
|
||||||
|
|
||||||
|
var MemProfileRate int = 512 * 1024
|
||||||
|
|||||||
9
runtime/internal/lib/runtime/runtime_gc.go
Normal file
9
runtime/internal/lib/runtime/runtime_gc.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//go:build !nogc
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/runtime/internal/clite/bdwgc"
|
||||||
|
|
||||||
|
func GC() {
|
||||||
|
bdwgc.Gcollect()
|
||||||
|
}
|
||||||
7
runtime/internal/lib/runtime/runtime_nogc.go
Normal file
7
runtime/internal/lib/runtime/runtime_nogc.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build nogc
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
func GC() {
|
||||||
|
|
||||||
|
}
|
||||||
5
runtime/internal/lib/runtime/trace/trace.go
Normal file
5
runtime/internal/lib/runtime/trace/trace.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package trace
|
||||||
|
|
||||||
|
func userTaskEnd(id uint64) {
|
||||||
|
panic("todo: runtime/trace.userTaskEnd")
|
||||||
|
}
|
||||||
103
runtime/internal/lib/sync/atomic/type.go
Normal file
103
runtime/internal/lib/sync/atomic/type.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package atomic
|
||||||
|
|
||||||
|
// An Int64 is an atomic int64. The zero value is zero.
|
||||||
|
type Int64 struct {
|
||||||
|
_ noCopy
|
||||||
|
_ align64
|
||||||
|
v int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads and returns the value stored in x.
|
||||||
|
func (x *Int64) Load() int64 { return LoadInt64(&x.v) }
|
||||||
|
|
||||||
|
// Store atomically stores val into x.
|
||||||
|
func (x *Int64) Store(val int64) { StoreInt64(&x.v, val) }
|
||||||
|
|
||||||
|
// Swap atomically stores new into x and returns the previous value.
|
||||||
|
func (x *Int64) Swap(new int64) (old int64) { return SwapInt64(&x.v, new) }
|
||||||
|
|
||||||
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
||||||
|
func (x *Int64) CompareAndSwap(old, new int64) (swapped bool) {
|
||||||
|
return CompareAndSwapInt64(&x.v, old, new)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add atomically adds delta to x and returns the new value.
|
||||||
|
func (x *Int64) Add(delta int64) (new int64) { return AddInt64(&x.v, delta) }
|
||||||
|
|
||||||
|
// And atomically performs a bitwise AND operation on x using the bitmask
|
||||||
|
// provided as mask and returns the old value.
|
||||||
|
func (x *Int64) And(mask int64) (old int64) { return AndInt64(&x.v, mask) }
|
||||||
|
|
||||||
|
// Or atomically performs a bitwise OR operation on x using the bitmask
|
||||||
|
// provided as mask and returns the old value.
|
||||||
|
func (x *Int64) Or(mask int64) (old int64) { return OrInt64(&x.v, mask) }
|
||||||
|
|
||||||
|
// A Uint64 is an atomic uint64. The zero value is zero.
|
||||||
|
type Uint64 struct {
|
||||||
|
_ noCopy
|
||||||
|
_ align64
|
||||||
|
v uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads and returns the value stored in x.
|
||||||
|
func (x *Uint64) Load() uint64 { return LoadUint64(&x.v) }
|
||||||
|
|
||||||
|
// Store atomically stores val into x.
|
||||||
|
func (x *Uint64) Store(val uint64) { StoreUint64(&x.v, val) }
|
||||||
|
|
||||||
|
// Swap atomically stores new into x and returns the previous value.
|
||||||
|
func (x *Uint64) Swap(new uint64) (old uint64) { return SwapUint64(&x.v, new) }
|
||||||
|
|
||||||
|
// CompareAndSwap executes the compare-and-swap operation for x.
|
||||||
|
func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool) {
|
||||||
|
return CompareAndSwapUint64(&x.v, old, new)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add atomically adds delta to x and returns the new value.
|
||||||
|
func (x *Uint64) Add(delta uint64) (new uint64) { return AddUint64(&x.v, delta) }
|
||||||
|
|
||||||
|
// And atomically performs a bitwise AND operation on x using the bitmask
|
||||||
|
// provided as mask and returns the old value.
|
||||||
|
func (x *Uint64) And(mask uint64) (old uint64) { return AndUint64(&x.v, mask) }
|
||||||
|
|
||||||
|
// Or atomically performs a bitwise OR operation on x using the bitmask
|
||||||
|
// provided as mask and returns the old value.
|
||||||
|
func (x *Uint64) Or(mask uint64) (old uint64) { return OrUint64(&x.v, mask) }
|
||||||
|
|
||||||
|
// noCopy may be added to structs which must not be copied
|
||||||
|
// after the first use.
|
||||||
|
//
|
||||||
|
// See https://golang.org/issues/8005#issuecomment-190753527
|
||||||
|
// for details.
|
||||||
|
//
|
||||||
|
// Note that it must not be embedded, due to the Lock and Unlock methods.
|
||||||
|
type noCopy struct{}
|
||||||
|
|
||||||
|
// Lock is a no-op used by -copylocks checker from `go vet`.
|
||||||
|
func (*noCopy) Lock() {}
|
||||||
|
func (*noCopy) Unlock() {}
|
||||||
|
|
||||||
|
// align64 may be added to structs that must be 64-bit aligned.
|
||||||
|
// This struct is recognized by a special case in the compiler
|
||||||
|
// and will not work if copied to any other package.
|
||||||
|
type align64 struct{}
|
||||||
|
|
||||||
|
// llgo:link AndInt64 llgo.atomicAnd
|
||||||
|
func AndInt64(addr *int64, mask int64) (old int64) {
|
||||||
|
panic("implement by llgo instruction")
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link AndUint64 llgo.atomicAnd
|
||||||
|
func AndUint64(addr *uint64, mask uint64) (old uint64) {
|
||||||
|
panic("implement by llgo instruction")
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link OrInt64 llgo.atomicOr
|
||||||
|
func OrInt64(addr *int64, mask int64) (old int64) {
|
||||||
|
panic("implement by llgo instruction")
|
||||||
|
}
|
||||||
|
|
||||||
|
// llgo:link OrUint64 llgo.atomicOr
|
||||||
|
func OrUint64(addr *uint64, mask uint64) (old uint64) {
|
||||||
|
panic("implement by llgo instruction")
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package sync
|
package sync
|
||||||
|
|
||||||
// llgo:skipall
|
|
||||||
import (
|
import (
|
||||||
gosync "sync"
|
gosync "sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -25,6 +24,9 @@ import (
|
|||||||
"github.com/goplus/llgo/runtime/internal/clite/pthread/sync"
|
"github.com/goplus/llgo/runtime/internal/clite/pthread/sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
type _sync struct{}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Mutex sync.Mutex
|
type Mutex sync.Mutex
|
||||||
|
|||||||
@@ -17,16 +17,20 @@
|
|||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
origSyscall "syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
c "github.com/goplus/llgo/runtime/internal/clite"
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
"github.com/goplus/llgo/runtime/internal/clite/os"
|
"github.com/goplus/llgo/runtime/internal/clite/os"
|
||||||
"github.com/goplus/llgo/runtime/internal/clite/syscall"
|
"github.com/goplus/llgo/runtime/internal/clite/syscall"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/lib/internal/bytealg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// llgo:skipall
|
// llgo:skipall
|
||||||
type _syscall struct{}
|
type _syscall struct{}
|
||||||
|
|
||||||
|
type Iovec syscall.Iovec
|
||||||
|
|
||||||
type Timespec syscall.Timespec
|
type Timespec syscall.Timespec
|
||||||
type Timeval syscall.Timeval
|
type Timeval syscall.Timeval
|
||||||
|
|
||||||
@@ -192,3 +196,24 @@ func setrlimit(which int, lim *Rlimit) (err error) {
|
|||||||
}
|
}
|
||||||
return Errno(ret)
|
return Errno(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BytePtrFromString(s string) (*byte, error) {
|
||||||
|
a, err := ByteSliceFromString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &a[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ByteSliceFromString(s string) ([]byte, error) {
|
||||||
|
if bytealg.IndexByteString(s, 0) != -1 {
|
||||||
|
return nil, Errno(syscall.EINVAL)
|
||||||
|
}
|
||||||
|
a := make([]byte, len(s)+1)
|
||||||
|
copy(a, s)
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Accept(fd int) (nfd int, sa origSyscall.Sockaddr, err error) {
|
||||||
|
panic("todo: syscall.Accept")
|
||||||
|
}
|
||||||
|
|||||||
5
runtime/internal/lib/syscall/syscall_darwin.go
Normal file
5
runtime/internal/lib/syscall/syscall_darwin.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package syscall
|
||||||
|
|
||||||
|
func Sysctl(key string) (string, error) {
|
||||||
|
panic("todo: syscall.Sysctl")
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
origSyscall "syscall"
|
||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
|
|
||||||
c "github.com/goplus/llgo/runtime/internal/clite"
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
@@ -126,3 +127,11 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
|||||||
func faccessat(dirfd c.Int, path *c.Char, mode c.Int, flags c.Int) c.Int
|
func faccessat(dirfd c.Int, path *c.Char, mode c.Int, flags c.Int) c.Int
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func Accept4(fd int, flags int) (nfd int, sa origSyscall.Sockaddr, err error) {
|
||||||
|
panic("todo: syscall.Accept4")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uname(buf *origSyscall.Utsname) (err error) {
|
||||||
|
panic("todo: syscall.Uname")
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ var (
|
|||||||
|
|
||||||
type Errno uintptr
|
type Errno uintptr
|
||||||
|
|
||||||
|
type Dirent = syscall.Dirent
|
||||||
|
|
||||||
func (e Errno) Error() string {
|
func (e Errno) Error() string {
|
||||||
ret := c.Strerror(c.Int(e))
|
ret := c.Strerror(c.Int(e))
|
||||||
return unsafe.String((*byte)(unsafe.Pointer(ret)), c.Strlen(ret))
|
return unsafe.String((*byte)(unsafe.Pointer(ret)), c.Strlen(ret))
|
||||||
@@ -69,3 +71,11 @@ func (s Signal) String() string {
|
|||||||
*/
|
*/
|
||||||
panic("todo: syscall.Signal.String")
|
panic("todo: syscall.Signal.String")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
|
||||||
|
panic("todo: syscall.Mmap")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Munmap(b []byte) (err error) {
|
||||||
|
panic("todo: syscall.Munmap")
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,23 +4,27 @@
|
|||||||
|
|
||||||
package time
|
package time
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
"github.com/goplus/llgo/runtime/internal/clite/libuv"
|
||||||
|
)
|
||||||
|
|
||||||
// Sleep pauses the current goroutine for at least the duration d.
|
// Sleep pauses the current goroutine for at least the duration d.
|
||||||
// A negative or zero duration causes Sleep to return immediately.
|
// A negative or zero duration causes Sleep to return immediately.
|
||||||
func Sleep(d Duration) {
|
func Sleep(d Duration) {
|
||||||
panic("todo: time.Sleep")
|
c.Usleep(c.Uint(d.Nanoseconds()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface to timers implemented in package runtime.
|
// Interface to timers implemented in package runtime.
|
||||||
// Must be in sync with ../runtime/time.go:/^type timer
|
// Must be in sync with ../runtime/time.go:/^type timer
|
||||||
type runtimeTimer struct {
|
type runtimeTimer struct {
|
||||||
pp uintptr
|
libuv.Timer
|
||||||
when int64
|
when int64
|
||||||
period int64
|
f func(any, uintptr)
|
||||||
f func(any, uintptr) // NOTE: must not be closure
|
arg any
|
||||||
arg any
|
|
||||||
seq uintptr
|
|
||||||
nextwhen int64
|
|
||||||
status uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// when is a helper function for setting the 'when' field of a runtimeTimer.
|
// when is a helper function for setting the 'when' field of a runtimeTimer.
|
||||||
@@ -40,10 +44,6 @@ func when(d Duration) int64 {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func startTimer(*runtimeTimer) { panic("todo: time.startTimer") }
|
|
||||||
func stopTimer(*runtimeTimer) bool { panic("todo: time.stopTimer") }
|
|
||||||
func resetTimer(*runtimeTimer, int64) bool { panic("todo: time.resetTimer") }
|
|
||||||
|
|
||||||
/* TODO(xsw):
|
/* TODO(xsw):
|
||||||
func modTimer(t *runtimeTimer, when, period int64, f func(any, uintptr), arg any, seq uintptr) {
|
func modTimer(t *runtimeTimer, when, period int64, f func(any, uintptr), arg any, seq uintptr) {
|
||||||
panic("todo: time.modTimer")
|
panic("todo: time.modTimer")
|
||||||
@@ -82,9 +82,6 @@ type Timer struct {
|
|||||||
// If the caller needs to know whether f is completed, it must coordinate
|
// If the caller needs to know whether f is completed, it must coordinate
|
||||||
// with f explicitly.
|
// with f explicitly.
|
||||||
func (t *Timer) Stop() bool {
|
func (t *Timer) Stop() bool {
|
||||||
if t.r.f == nil {
|
|
||||||
panic("time: Stop called on uninitialized Timer")
|
|
||||||
}
|
|
||||||
return stopTimer(&t.r)
|
return stopTimer(&t.r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,9 +136,6 @@ func NewTimer(d Duration) *Timer {
|
|||||||
// one. If the caller needs to know whether the prior execution of
|
// one. If the caller needs to know whether the prior execution of
|
||||||
// f is completed, it must coordinate with f explicitly.
|
// f is completed, it must coordinate with f explicitly.
|
||||||
func (t *Timer) Reset(d Duration) bool {
|
func (t *Timer) Reset(d Duration) bool {
|
||||||
if t.r.f == nil {
|
|
||||||
panic("time: Reset called on uninitialized Timer")
|
|
||||||
}
|
|
||||||
w := when(d)
|
w := when(d)
|
||||||
return resetTimer(&t.r, w)
|
return resetTimer(&t.r, w)
|
||||||
}
|
}
|
||||||
@@ -182,3 +176,64 @@ func AfterFunc(d Duration, f func()) *Timer {
|
|||||||
func goFunc(arg any, seq uintptr) {
|
func goFunc(arg any, seq uintptr) {
|
||||||
go arg.(func())()
|
go arg.(func())()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
timerLoop *libuv.Loop
|
||||||
|
timerOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
timerOnce.Do(func() {
|
||||||
|
timerLoop = libuv.LoopNew()
|
||||||
|
})
|
||||||
|
go func() {
|
||||||
|
timerLoop.Run(libuv.RUN_DEFAULT)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// cross thread
|
||||||
|
func timerEvent(async *libuv.Async) {
|
||||||
|
a := (*asyncTimerEvent)(unsafe.Pointer(async))
|
||||||
|
a.cb()
|
||||||
|
a.Close(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type asyncTimerEvent struct {
|
||||||
|
libuv.Async
|
||||||
|
cb func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func timerCallback(t *libuv.Timer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTimer(r *runtimeTimer) {
|
||||||
|
asyncTimer := &asyncTimerEvent{
|
||||||
|
cb: func() {
|
||||||
|
libuv.InitTimer(timerLoop, &r.Timer)
|
||||||
|
r.Start(timerCallback, uint64(r.when), 0)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
timerLoop.Async(&asyncTimer.Async, timerEvent)
|
||||||
|
asyncTimer.Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopTimer(r *runtimeTimer) bool {
|
||||||
|
asyncTimer := &asyncTimerEvent{
|
||||||
|
cb: func() {
|
||||||
|
r.Stop()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
timerLoop.Async(&asyncTimer.Async, timerEvent)
|
||||||
|
return asyncTimer.Send() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func resetTimer(r *runtimeTimer, when int64) bool {
|
||||||
|
asyncTimer := &asyncTimerEvent{
|
||||||
|
cb: func() {
|
||||||
|
r.Stop()
|
||||||
|
r.Start(timerCallback, uint64(when), 0)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
timerLoop.Async(&asyncTimer.Async, timerEvent)
|
||||||
|
return asyncTimer.Send() == 0
|
||||||
|
}
|
||||||
|
|||||||
36
runtime/internal/lib/time/tick.go
Normal file
36
runtime/internal/lib/time/tick.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package time
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type Ticker struct {
|
||||||
|
C <-chan Time // The channel on which the ticks are delivered.
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTicker(d Duration) *Ticker {
|
||||||
|
if d <= 0 {
|
||||||
|
panic("non-positive interval for NewTicker")
|
||||||
|
}
|
||||||
|
c := make(chan Time, 1)
|
||||||
|
t := &Timer{C: c}
|
||||||
|
t.C = c
|
||||||
|
startTimer(&t.r)
|
||||||
|
return (*Ticker)(unsafe.Pointer(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Ticker) Stop() {
|
||||||
|
stopTimer(&(*Timer)(unsafe.Pointer(t)).r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Ticker) Reset(d Duration) {
|
||||||
|
if d <= 0 {
|
||||||
|
panic("non-positive interval for Ticker.Reset")
|
||||||
|
}
|
||||||
|
resetTimer(&(*Timer)(unsafe.Pointer(t)).r, when(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Tick(d Duration) <-chan Time {
|
||||||
|
if d <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return NewTicker(d).C
|
||||||
|
}
|
||||||
@@ -187,6 +187,10 @@ func (t Time) Compare(u Time) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t Time) UnixNano() int64 {
|
||||||
|
return (t.unixSec())*1e9 + int64(t.nsec())
|
||||||
|
}
|
||||||
|
|
||||||
// Equal reports whether t and u represent the same time instant.
|
// Equal reports whether t and u represent the same time instant.
|
||||||
// Two times can be equal even if they are in different locations.
|
// Two times can be equal even if they are in different locations.
|
||||||
// For example, 6:00 +0200 and 4:00 UTC are Equal.
|
// For example, 6:00 +0200 and 4:00 UTC are Equal.
|
||||||
|
|||||||
Reference in New Issue
Block a user