Added Starlark scripting language for SCRIPT blocks.
This commit is contained in:
parent
d09a039697
commit
af315647bd
333 changed files with 186530 additions and 6 deletions
7
go.mod
7
go.mod
|
|
@ -2,4 +2,9 @@ module c65gm
|
||||||
|
|
||||||
go 1.25.1
|
go 1.25.1
|
||||||
|
|
||||||
require github.com/armon/go-radix v1.0.0
|
require (
|
||||||
|
github.com/armon/go-radix v1.0.0
|
||||||
|
go.starlark.net v0.0.0-20251029211736-7849196f18cf
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||||
|
|
|
||||||
8
go.sum
8
go.sum
|
|
@ -1,2 +1,10 @@
|
||||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
go.starlark.net v0.0.0-20251029211736-7849196f18cf h1:iyRnW9PWEZDYnIKzNjW3K9Xa+/o19k/cLLwIkKGDEYg=
|
||||||
|
go.starlark.net v0.0.0-20251029211736-7849196f18cf/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,25 @@ func (c *Compiler) Registry() *CommandRegistry {
|
||||||
func (c *Compiler) Compile(lines []preproc.Line) ([]string, error) {
|
func (c *Compiler) Compile(lines []preproc.Line) ([]string, error) {
|
||||||
var codeOutput []string
|
var codeOutput []string
|
||||||
var lastKind = preproc.Source
|
var lastKind = preproc.Source
|
||||||
|
var scriptBuffer []string
|
||||||
|
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
// Detect kind transitions and emit markers
|
// Detect kind transitions and emit markers
|
||||||
if line.Kind != lastKind {
|
if line.Kind != lastKind {
|
||||||
// Close previous block
|
// Execute and close previous Script block
|
||||||
|
if lastKind == preproc.Script {
|
||||||
|
scriptOutput, err := executeScript(scriptBuffer, c.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("script execution failed: %w", err)
|
||||||
|
}
|
||||||
|
codeOutput = append(codeOutput, scriptOutput...)
|
||||||
|
scriptBuffer = nil
|
||||||
|
codeOutput = append(codeOutput, "; ENDSCRIPT")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close previous Assembler block
|
||||||
if lastKind == preproc.Assembler {
|
if lastKind == preproc.Assembler {
|
||||||
codeOutput = append(codeOutput, "; ENDASM")
|
codeOutput = append(codeOutput, "; ENDASM")
|
||||||
} else if lastKind == preproc.Script {
|
|
||||||
codeOutput = append(codeOutput, "; ENDSCRIPT")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open new block
|
// Open new block
|
||||||
|
|
@ -56,7 +66,7 @@ func (c *Compiler) Compile(lines []preproc.Line) ([]string, error) {
|
||||||
lastKind = line.Kind
|
lastKind = line.Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip non-source lines (assembler and script handled differently)
|
// Handle non-source lines
|
||||||
if line.Kind != preproc.Source {
|
if line.Kind != preproc.Source {
|
||||||
if line.Kind == preproc.Assembler {
|
if line.Kind == preproc.Assembler {
|
||||||
// Expand |varname| -> scoped_varname for local variables in ASM blocks
|
// Expand |varname| -> scoped_varname for local variables in ASM blocks
|
||||||
|
|
@ -77,8 +87,10 @@ func (c *Compiler) Compile(lines []preproc.Line) ([]string, error) {
|
||||||
text = text[:start] + expandedName + text[end+1:]
|
text = text[:start] + expandedName + text[end+1:]
|
||||||
}
|
}
|
||||||
codeOutput = append(codeOutput, text)
|
codeOutput = append(codeOutput, text)
|
||||||
|
} else if line.Kind == preproc.Script {
|
||||||
|
// Collect script lines for execution
|
||||||
|
scriptBuffer = append(scriptBuffer, line.Text)
|
||||||
}
|
}
|
||||||
// Script lines ignored for now
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
77
internal/compiler/scriptexec.go
Normal file
77
internal/compiler/scriptexec.go
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
package compiler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.starlark.net/lib/math"
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
)
|
||||||
|
|
||||||
|
// executeScript runs a Starlark script and returns the output lines
|
||||||
|
func executeScript(scriptLines []string, ctx *CompilerContext) ([]string, error) {
|
||||||
|
// Join script lines
|
||||||
|
scriptText := strings.Join(scriptLines, "\n")
|
||||||
|
|
||||||
|
// Expand |varname| -> actual variable names
|
||||||
|
scriptText = expandVariables(scriptText, ctx)
|
||||||
|
|
||||||
|
// Wrap in function (Starlark requires control flow inside functions)
|
||||||
|
wrappedScript := "def _main():\n"
|
||||||
|
for _, line := range strings.Split(scriptText, "\n") {
|
||||||
|
wrappedScript += " " + line + "\n"
|
||||||
|
}
|
||||||
|
wrappedScript += "_main()\n"
|
||||||
|
|
||||||
|
// Capture print output
|
||||||
|
var output bytes.Buffer
|
||||||
|
thread := &starlark.Thread{
|
||||||
|
Print: func(_ *starlark.Thread, msg string) {
|
||||||
|
output.WriteString(msg)
|
||||||
|
output.WriteString("\n")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set execution limit (prevent infinite loops)
|
||||||
|
thread.SetMaxExecutionSteps(1000000) // 1M steps
|
||||||
|
|
||||||
|
// Predeclared functions (math module)
|
||||||
|
predeclared := starlark.StringDict{
|
||||||
|
"math": math.Module,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
_, err := starlark.ExecFile(thread, "script.star", wrappedScript, predeclared)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split output into lines for assembly
|
||||||
|
outputStr := output.String()
|
||||||
|
if outputStr == "" {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
lines := strings.Split(strings.TrimRight(outputStr, "\n"), "\n")
|
||||||
|
return lines, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// expandVariables replaces |varname| with expanded variable names from symbol table
|
||||||
|
func expandVariables(text string, ctx *CompilerContext) string {
|
||||||
|
result := text
|
||||||
|
for {
|
||||||
|
start := strings.IndexByte(result, '|')
|
||||||
|
if start == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
end := strings.IndexByte(result[start+1:], '|')
|
||||||
|
if end == -1 {
|
||||||
|
break // unclosed, let script fail
|
||||||
|
}
|
||||||
|
end += start + 1
|
||||||
|
|
||||||
|
varName := result[start+1 : end]
|
||||||
|
expandedName := ctx.SymbolTable.ExpandName(varName, ctx.CurrentScope())
|
||||||
|
result = result[:start] + expandedName + result[end+1:]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
29
vendor/go.starlark.net/LICENSE
generated
vendored
Normal file
29
vendor/go.starlark.net/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
Copyright (c) 2017 The Bazel Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
1927
vendor/go.starlark.net/internal/compile/compile.go
generated
vendored
Normal file
1927
vendor/go.starlark.net/internal/compile/compile.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
399
vendor/go.starlark.net/internal/compile/serial.go
generated
vendored
Normal file
399
vendor/go.starlark.net/internal/compile/serial.go
generated
vendored
Normal file
|
|
@ -0,0 +1,399 @@
|
||||||
|
package compile
|
||||||
|
|
||||||
|
// This file defines functions to read and write a compile.Program to a file.
|
||||||
|
//
|
||||||
|
// It is the client's responsibility to avoid version skew between the
|
||||||
|
// compiler used to produce a file and the interpreter that consumes it.
|
||||||
|
// The version number is provided as a constant.
|
||||||
|
// Incompatible protocol changes should also increment the version number.
|
||||||
|
//
|
||||||
|
// Encoding
|
||||||
|
//
|
||||||
|
// Program:
|
||||||
|
// "sky!" [4]byte # magic number
|
||||||
|
// str uint32le # offset of <strings> section
|
||||||
|
// version varint # must match Version
|
||||||
|
// filename string
|
||||||
|
// numloads varint
|
||||||
|
// loads []Ident
|
||||||
|
// numnames varint
|
||||||
|
// names []string
|
||||||
|
// numconsts varint
|
||||||
|
// consts []Constant
|
||||||
|
// numglobals varint
|
||||||
|
// globals []Ident
|
||||||
|
// toplevel Funcode
|
||||||
|
// numfuncs varint
|
||||||
|
// funcs []Funcode
|
||||||
|
// recursion varint (0 or 1)
|
||||||
|
// <strings> []byte # concatenation of all referenced strings
|
||||||
|
// EOF
|
||||||
|
//
|
||||||
|
// Funcode:
|
||||||
|
// id Ident
|
||||||
|
// code []byte
|
||||||
|
// pclinetablen varint
|
||||||
|
// pclinetab []varint
|
||||||
|
// numlocals varint
|
||||||
|
// locals []Ident
|
||||||
|
// numcells varint
|
||||||
|
// cells []int
|
||||||
|
// numfreevars varint
|
||||||
|
// freevar []Ident
|
||||||
|
// maxstack varint
|
||||||
|
// numparams varint
|
||||||
|
// numkwonlyparams varint
|
||||||
|
// hasvarargs varint (0 or 1)
|
||||||
|
// haskwargs varint (0 or 1)
|
||||||
|
//
|
||||||
|
// Ident:
|
||||||
|
// filename string
|
||||||
|
// line, col varint
|
||||||
|
//
|
||||||
|
// Constant: # type data
|
||||||
|
// type varint # 0=string string
|
||||||
|
// data ... # 1=bytes string
|
||||||
|
// # 2=int varint
|
||||||
|
// # 3=float varint (bits as uint64)
|
||||||
|
// # 4=bigint string (decimal ASCII text)
|
||||||
|
//
|
||||||
|
// The encoding starts with a four-byte magic number.
|
||||||
|
// The next four bytes are a little-endian uint32
|
||||||
|
// that provides the offset of the string section
|
||||||
|
// at the end of the file, which contains the ordered
|
||||||
|
// concatenation of all strings referenced by the
|
||||||
|
// program. This design permits the decoder to read
|
||||||
|
// the first and second parts of the file into different
|
||||||
|
// memory allocations: the first (the encoded program)
|
||||||
|
// is transient, but the second (the strings) persists
|
||||||
|
// for the life of the Program.
|
||||||
|
//
|
||||||
|
// Within the encoded program, all strings are referred
|
||||||
|
// to by their length. As the encoder and decoder process
|
||||||
|
// the entire file sequentially, they are in lock step,
|
||||||
|
// so the start offset of each string is implicit.
|
||||||
|
//
|
||||||
|
// Program.Code is represented as a []byte slice to permit
|
||||||
|
// modification when breakpoints are set. All other strings
|
||||||
|
// are represented as strings. They all (unsafely) share the
|
||||||
|
// same backing byte slice.
|
||||||
|
//
|
||||||
|
// Aside from the str field, all integers are encoded as varints.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
debugpkg "runtime/debug"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
const magic = "!sky"
|
||||||
|
|
||||||
|
// Encode encodes a compiled Starlark program.
|
||||||
|
func (prog *Program) Encode() []byte {
|
||||||
|
var e encoder
|
||||||
|
e.p = append(e.p, magic...)
|
||||||
|
e.p = append(e.p, "????"...) // string data offset; filled in later
|
||||||
|
e.int(Version)
|
||||||
|
e.string(prog.Toplevel.Pos.Filename())
|
||||||
|
e.bindings(prog.Loads)
|
||||||
|
e.int(len(prog.Names))
|
||||||
|
for _, name := range prog.Names {
|
||||||
|
e.string(name)
|
||||||
|
}
|
||||||
|
e.int(len(prog.Constants))
|
||||||
|
for _, c := range prog.Constants {
|
||||||
|
switch c := c.(type) {
|
||||||
|
case string:
|
||||||
|
e.int(0)
|
||||||
|
e.string(c)
|
||||||
|
case Bytes:
|
||||||
|
e.int(1)
|
||||||
|
e.string(string(c))
|
||||||
|
case int64:
|
||||||
|
e.int(2)
|
||||||
|
e.int64(c)
|
||||||
|
case float64:
|
||||||
|
e.int(3)
|
||||||
|
e.uint64(math.Float64bits(c))
|
||||||
|
case *big.Int:
|
||||||
|
e.int(4)
|
||||||
|
e.string(c.Text(10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.bindings(prog.Globals)
|
||||||
|
e.function(prog.Toplevel)
|
||||||
|
e.int(len(prog.Functions))
|
||||||
|
for _, fn := range prog.Functions {
|
||||||
|
e.function(fn)
|
||||||
|
}
|
||||||
|
e.int(b2i(prog.Recursion))
|
||||||
|
|
||||||
|
// Patch in the offset of the string data section.
|
||||||
|
binary.LittleEndian.PutUint32(e.p[4:8], uint32(len(e.p)))
|
||||||
|
|
||||||
|
return append(e.p, e.s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type encoder struct {
|
||||||
|
p []byte // encoded program
|
||||||
|
s []byte // strings
|
||||||
|
tmp [binary.MaxVarintLen64]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) int(x int) {
|
||||||
|
e.int64(int64(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) int64(x int64) {
|
||||||
|
n := binary.PutVarint(e.tmp[:], x)
|
||||||
|
e.p = append(e.p, e.tmp[:n]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uint64(x uint64) {
|
||||||
|
n := binary.PutUvarint(e.tmp[:], x)
|
||||||
|
e.p = append(e.p, e.tmp[:n]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) string(s string) {
|
||||||
|
e.int(len(s))
|
||||||
|
e.s = append(e.s, s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) bytes(b []byte) {
|
||||||
|
e.int(len(b))
|
||||||
|
e.s = append(e.s, b...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) binding(bind Binding) {
|
||||||
|
e.string(bind.Name)
|
||||||
|
e.int(int(bind.Pos.Line))
|
||||||
|
e.int(int(bind.Pos.Col))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) bindings(binds []Binding) {
|
||||||
|
e.int(len(binds))
|
||||||
|
for _, bind := range binds {
|
||||||
|
e.binding(bind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) function(fn *Funcode) {
|
||||||
|
e.binding(Binding{fn.Name, fn.Pos})
|
||||||
|
e.string(fn.Doc)
|
||||||
|
e.bytes(fn.Code)
|
||||||
|
e.int(len(fn.pclinetab))
|
||||||
|
for _, x := range fn.pclinetab {
|
||||||
|
e.int64(int64(x))
|
||||||
|
}
|
||||||
|
e.bindings(fn.Locals)
|
||||||
|
e.int(len(fn.Cells))
|
||||||
|
for _, index := range fn.Cells {
|
||||||
|
e.int(index)
|
||||||
|
}
|
||||||
|
e.bindings(fn.FreeVars)
|
||||||
|
e.int(fn.MaxStack)
|
||||||
|
e.int(fn.NumParams)
|
||||||
|
e.int(fn.NumKwonlyParams)
|
||||||
|
e.int(b2i(fn.HasVarargs))
|
||||||
|
e.int(b2i(fn.HasKwargs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func b2i(b bool) int {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeProgram decodes a compiled Starlark program from data.
|
||||||
|
func DecodeProgram(data []byte) (_ *Program, err error) {
|
||||||
|
if len(data) < len(magic) {
|
||||||
|
return nil, fmt.Errorf("not a compiled module: no magic number")
|
||||||
|
}
|
||||||
|
if got := string(data[:4]); got != magic {
|
||||||
|
return nil, fmt.Errorf("not a compiled module: got magic number %q, want %q",
|
||||||
|
got, magic)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if x := recover(); x != nil {
|
||||||
|
debugpkg.PrintStack()
|
||||||
|
err = fmt.Errorf("internal error while decoding program: %v", x)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
offset := binary.LittleEndian.Uint32(data[4:8])
|
||||||
|
d := decoder{
|
||||||
|
p: data[8:offset],
|
||||||
|
s: append([]byte(nil), data[offset:]...), // allocate a copy, which will persist
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := d.int(); v != Version {
|
||||||
|
return nil, fmt.Errorf("version mismatch: read %d, want %d", v, Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := d.string()
|
||||||
|
d.filename = &filename
|
||||||
|
|
||||||
|
loads := d.bindings()
|
||||||
|
|
||||||
|
names := make([]string, d.int())
|
||||||
|
for i := range names {
|
||||||
|
names[i] = d.string()
|
||||||
|
}
|
||||||
|
|
||||||
|
// constants
|
||||||
|
constants := make([]interface{}, d.int())
|
||||||
|
for i := range constants {
|
||||||
|
var c interface{}
|
||||||
|
switch d.int() {
|
||||||
|
case 0:
|
||||||
|
c = d.string()
|
||||||
|
case 1:
|
||||||
|
c = Bytes(d.string())
|
||||||
|
case 2:
|
||||||
|
c = d.int64()
|
||||||
|
case 3:
|
||||||
|
c = math.Float64frombits(d.uint64())
|
||||||
|
case 4:
|
||||||
|
c, _ = new(big.Int).SetString(d.string(), 10)
|
||||||
|
}
|
||||||
|
constants[i] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
globals := d.bindings()
|
||||||
|
toplevel := d.function()
|
||||||
|
funcs := make([]*Funcode, d.int())
|
||||||
|
for i := range funcs {
|
||||||
|
funcs[i] = d.function()
|
||||||
|
}
|
||||||
|
recursion := d.int() != 0
|
||||||
|
|
||||||
|
prog := &Program{
|
||||||
|
Loads: loads,
|
||||||
|
Names: names,
|
||||||
|
Constants: constants,
|
||||||
|
Globals: globals,
|
||||||
|
Functions: funcs,
|
||||||
|
Toplevel: toplevel,
|
||||||
|
Recursion: recursion,
|
||||||
|
}
|
||||||
|
toplevel.Prog = prog
|
||||||
|
for _, f := range funcs {
|
||||||
|
f.Prog = prog
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(d.p)+len(d.s) > 0 {
|
||||||
|
return nil, fmt.Errorf("internal error: unconsumed data during decoding")
|
||||||
|
}
|
||||||
|
|
||||||
|
return prog, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type decoder struct {
|
||||||
|
p []byte // encoded program
|
||||||
|
s []byte // strings
|
||||||
|
filename *string // (indirect to avoid keeping decoder live)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) int() int {
|
||||||
|
return int(d.int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) int64() int64 {
|
||||||
|
x, len := binary.Varint(d.p[:])
|
||||||
|
d.p = d.p[len:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) uint64() uint64 {
|
||||||
|
x, len := binary.Uvarint(d.p[:])
|
||||||
|
d.p = d.p[len:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) string() (s string) {
|
||||||
|
if slice := d.bytes(); len(slice) > 0 {
|
||||||
|
// Avoid a memory allocation for each string
|
||||||
|
// by unsafely aliasing slice.
|
||||||
|
type string struct {
|
||||||
|
data *byte
|
||||||
|
len int
|
||||||
|
}
|
||||||
|
ptr := (*string)(unsafe.Pointer(&s))
|
||||||
|
ptr.data = &slice[0]
|
||||||
|
ptr.len = len(slice)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) bytes() []byte {
|
||||||
|
len := d.int()
|
||||||
|
r := d.s[:len:len]
|
||||||
|
d.s = d.s[len:]
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) binding() Binding {
|
||||||
|
name := d.string()
|
||||||
|
line := int32(d.int())
|
||||||
|
col := int32(d.int())
|
||||||
|
return Binding{Name: name, Pos: syntax.MakePosition(d.filename, line, col)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) bindings() []Binding {
|
||||||
|
bindings := make([]Binding, d.int())
|
||||||
|
for i := range bindings {
|
||||||
|
bindings[i] = d.binding()
|
||||||
|
}
|
||||||
|
return bindings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) ints() []int {
|
||||||
|
ints := make([]int, d.int())
|
||||||
|
for i := range ints {
|
||||||
|
ints[i] = d.int()
|
||||||
|
}
|
||||||
|
return ints
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) bool() bool { return d.int() != 0 }
|
||||||
|
|
||||||
|
func (d *decoder) function() *Funcode {
|
||||||
|
id := d.binding()
|
||||||
|
doc := d.string()
|
||||||
|
code := d.bytes()
|
||||||
|
pclinetab := make([]uint16, d.int())
|
||||||
|
for i := range pclinetab {
|
||||||
|
pclinetab[i] = uint16(d.int())
|
||||||
|
}
|
||||||
|
locals := d.bindings()
|
||||||
|
cells := d.ints()
|
||||||
|
freevars := d.bindings()
|
||||||
|
maxStack := d.int()
|
||||||
|
numParams := d.int()
|
||||||
|
numKwonlyParams := d.int()
|
||||||
|
hasVarargs := d.int() != 0
|
||||||
|
hasKwargs := d.int() != 0
|
||||||
|
return &Funcode{
|
||||||
|
// Prog is filled in later.
|
||||||
|
Pos: id.Pos,
|
||||||
|
Name: id.Name,
|
||||||
|
Doc: doc,
|
||||||
|
Code: code,
|
||||||
|
pclinetab: pclinetab,
|
||||||
|
Locals: locals,
|
||||||
|
Cells: cells,
|
||||||
|
FreeVars: freevars,
|
||||||
|
MaxStack: maxStack,
|
||||||
|
NumParams: numParams,
|
||||||
|
NumKwonlyParams: numKwonlyParams,
|
||||||
|
HasVarargs: hasVarargs,
|
||||||
|
HasKwargs: hasKwargs,
|
||||||
|
}
|
||||||
|
}
|
||||||
115
vendor/go.starlark.net/internal/spell/spell.go
generated
vendored
Normal file
115
vendor/go.starlark.net/internal/spell/spell.go
generated
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
// Package spell file defines a simple spelling checker for use in attribute errors
|
||||||
|
// such as "no such field .foo; did you mean .food?".
|
||||||
|
package spell
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Nearest returns the element of candidates
|
||||||
|
// nearest to x using the Levenshtein metric,
|
||||||
|
// or "" if none were promising.
|
||||||
|
func Nearest(x string, candidates []string) string {
|
||||||
|
// Ignore underscores and case when matching.
|
||||||
|
fold := func(s string) string {
|
||||||
|
return strings.Map(func(r rune) rune {
|
||||||
|
if r == '_' {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return unicode.ToLower(r)
|
||||||
|
}, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
x = fold(x)
|
||||||
|
|
||||||
|
var best string
|
||||||
|
bestD := (len(x) + 1) / 2 // allow up to 50% typos
|
||||||
|
for _, c := range candidates {
|
||||||
|
d := levenshtein(x, fold(c), bestD)
|
||||||
|
if d < bestD {
|
||||||
|
bestD = d
|
||||||
|
best = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best
|
||||||
|
}
|
||||||
|
|
||||||
|
// levenshtein returns the non-negative Levenshtein edit distance
|
||||||
|
// between the byte strings x and y.
|
||||||
|
//
|
||||||
|
// If the computed distance exceeds max,
|
||||||
|
// the function may return early with an approximate value > max.
|
||||||
|
func levenshtein(x, y string, max int) int {
|
||||||
|
// This implementation is derived from one by Laurent Le Brun in
|
||||||
|
// Bazel that uses the single-row space efficiency trick
|
||||||
|
// described at bitbucket.org/clearer/iosifovich.
|
||||||
|
|
||||||
|
// Let x be the shorter string.
|
||||||
|
if len(x) > len(y) {
|
||||||
|
x, y = y, x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove common prefix.
|
||||||
|
for i := 0; i < len(x); i++ {
|
||||||
|
if x[i] != y[i] {
|
||||||
|
x = x[i:]
|
||||||
|
y = y[i:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if x == "" {
|
||||||
|
return len(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d := abs(len(x) - len(y)); d > max {
|
||||||
|
return d // excessive length divergence
|
||||||
|
}
|
||||||
|
|
||||||
|
row := make([]int, len(y)+1)
|
||||||
|
for i := range row {
|
||||||
|
row[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i <= len(x); i++ {
|
||||||
|
row[0] = i
|
||||||
|
best := i
|
||||||
|
prev := i - 1
|
||||||
|
for j := 1; j <= len(y); j++ {
|
||||||
|
a := prev + b2i(x[i-1] != y[j-1]) // substitution
|
||||||
|
b := 1 + row[j-1] // deletion
|
||||||
|
c := 1 + row[j] // insertion
|
||||||
|
k := min(a, min(b, c))
|
||||||
|
prev, row[j] = row[j], k
|
||||||
|
best = min(best, k)
|
||||||
|
}
|
||||||
|
if best > max {
|
||||||
|
return best
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return row[len(y)]
|
||||||
|
}
|
||||||
|
|
||||||
|
func b2i(b bool) int {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func min(x, y int) int {
|
||||||
|
if x < y {
|
||||||
|
return x
|
||||||
|
} else {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func abs(x int) int {
|
||||||
|
if x >= 0 {
|
||||||
|
return x
|
||||||
|
} else {
|
||||||
|
return -x
|
||||||
|
}
|
||||||
|
}
|
||||||
205
vendor/go.starlark.net/lib/math/math.go
generated
vendored
Normal file
205
vendor/go.starlark.net/lib/math/math.go
generated
vendored
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
// Copyright 2021 The Bazel 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 math provides basic constants and mathematical functions.
|
||||||
|
package math // import "go.starlark.net/lib/math"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
"go.starlark.net/starlarkstruct"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Module math is a Starlark module of math-related functions and constants.
|
||||||
|
// The module defines the following functions:
|
||||||
|
//
|
||||||
|
// ceil(x) - Returns the ceiling of x, the smallest integer greater than or equal to x.
|
||||||
|
// copysign(x, y) - Returns a value with the magnitude of x and the sign of y.
|
||||||
|
// fabs(x) - Returns the absolute value of x as float.
|
||||||
|
// floor(x) - Returns the floor of x, the largest integer less than or equal to x.
|
||||||
|
// mod(x, y) - Returns the floating-point remainder of x/y. The magnitude of the result is less than y and its sign agrees with that of x.
|
||||||
|
// pow(x, y) - Returns x**y, the base-x exponential of y.
|
||||||
|
// remainder(x, y) - Returns the IEEE 754 floating-point remainder of x/y.
|
||||||
|
// round(x) - Returns the nearest integer, rounding half away from zero.
|
||||||
|
//
|
||||||
|
// exp(x) - Returns e raised to the power x, where e = 2.718281… is the base of natural logarithms.
|
||||||
|
// sqrt(x) - Returns the square root of x.
|
||||||
|
//
|
||||||
|
// acos(x) - Returns the arc cosine of x, in radians.
|
||||||
|
// asin(x) - Returns the arc sine of x, in radians.
|
||||||
|
// atan(x) - Returns the arc tangent of x, in radians.
|
||||||
|
// atan2(y, x) - Returns atan(y / x), in radians.
|
||||||
|
// The result is between -pi and pi.
|
||||||
|
// The vector in the plane from the origin to point (x, y) makes this angle with the positive X axis.
|
||||||
|
// The point of atan2() is that the signs of both inputs are known to it, so it can compute the correct
|
||||||
|
// quadrant for the angle.
|
||||||
|
// For example, atan(1) and atan2(1, 1) are both pi/4, but atan2(-1, -1) is -3*pi/4.
|
||||||
|
// cos(x) - Returns the cosine of x, in radians.
|
||||||
|
// hypot(x, y) - Returns the Euclidean norm, sqrt(x*x + y*y). This is the length of the vector from the origin to point (x, y).
|
||||||
|
// sin(x) - Returns the sine of x, in radians.
|
||||||
|
// tan(x) - Returns the tangent of x, in radians.
|
||||||
|
//
|
||||||
|
// degrees(x) - Converts angle x from radians to degrees.
|
||||||
|
// radians(x) - Converts angle x from degrees to radians.
|
||||||
|
//
|
||||||
|
// acosh(x) - Returns the inverse hyperbolic cosine of x.
|
||||||
|
// asinh(x) - Returns the inverse hyperbolic sine of x.
|
||||||
|
// atanh(x) - Returns the inverse hyperbolic tangent of x.
|
||||||
|
// cosh(x) - Returns the hyperbolic cosine of x.
|
||||||
|
// sinh(x) - Returns the hyperbolic sine of x.
|
||||||
|
// tanh(x) - Returns the hyperbolic tangent of x.
|
||||||
|
//
|
||||||
|
// log(x, base) - Returns the logarithm of x in the given base, or natural logarithm by default.
|
||||||
|
//
|
||||||
|
// gamma(x) - Returns the Gamma function of x.
|
||||||
|
//
|
||||||
|
// All functions accept both int and float values as arguments.
|
||||||
|
//
|
||||||
|
// The module also defines approximations of the following constants:
|
||||||
|
//
|
||||||
|
// e - The base of natural logarithms, approximately 2.71828.
|
||||||
|
// pi - The ratio of a circle's circumference to its diameter, approximately 3.14159.
|
||||||
|
var Module = &starlarkstruct.Module{
|
||||||
|
Name: "math",
|
||||||
|
Members: starlark.StringDict{
|
||||||
|
"ceil": starlark.NewBuiltin("ceil", ceil),
|
||||||
|
"copysign": newBinaryBuiltin("copysign", math.Copysign),
|
||||||
|
"fabs": newUnaryBuiltin("fabs", math.Abs),
|
||||||
|
"floor": starlark.NewBuiltin("floor", floor),
|
||||||
|
"mod": newBinaryBuiltin("mod", math.Mod),
|
||||||
|
"pow": newBinaryBuiltin("pow", math.Pow),
|
||||||
|
"remainder": newBinaryBuiltin("remainder", math.Remainder),
|
||||||
|
"round": newUnaryBuiltin("round", math.Round),
|
||||||
|
|
||||||
|
"exp": newUnaryBuiltin("exp", math.Exp),
|
||||||
|
"sqrt": newUnaryBuiltin("sqrt", math.Sqrt),
|
||||||
|
|
||||||
|
"acos": newUnaryBuiltin("acos", math.Acos),
|
||||||
|
"asin": newUnaryBuiltin("asin", math.Asin),
|
||||||
|
"atan": newUnaryBuiltin("atan", math.Atan),
|
||||||
|
"atan2": newBinaryBuiltin("atan2", math.Atan2),
|
||||||
|
"cos": newUnaryBuiltin("cos", math.Cos),
|
||||||
|
"hypot": newBinaryBuiltin("hypot", math.Hypot),
|
||||||
|
"sin": newUnaryBuiltin("sin", math.Sin),
|
||||||
|
"tan": newUnaryBuiltin("tan", math.Tan),
|
||||||
|
|
||||||
|
"degrees": newUnaryBuiltin("degrees", degrees),
|
||||||
|
"radians": newUnaryBuiltin("radians", radians),
|
||||||
|
|
||||||
|
"acosh": newUnaryBuiltin("acosh", math.Acosh),
|
||||||
|
"asinh": newUnaryBuiltin("asinh", math.Asinh),
|
||||||
|
"atanh": newUnaryBuiltin("atanh", math.Atanh),
|
||||||
|
"cosh": newUnaryBuiltin("cosh", math.Cosh),
|
||||||
|
"sinh": newUnaryBuiltin("sinh", math.Sinh),
|
||||||
|
"tanh": newUnaryBuiltin("tanh", math.Tanh),
|
||||||
|
|
||||||
|
"log": starlark.NewBuiltin("log", log),
|
||||||
|
|
||||||
|
"gamma": newUnaryBuiltin("gamma", math.Gamma),
|
||||||
|
|
||||||
|
"e": starlark.Float(math.E),
|
||||||
|
"pi": starlark.Float(math.Pi),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// floatOrInt is an Unpacker that converts a Starlark int or float to Go's float64.
|
||||||
|
type floatOrInt float64
|
||||||
|
|
||||||
|
func (p *floatOrInt) Unpack(v starlark.Value) error {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case starlark.Int:
|
||||||
|
*p = floatOrInt(v.Float())
|
||||||
|
return nil
|
||||||
|
case starlark.Float:
|
||||||
|
*p = floatOrInt(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("got %s, want float or int", v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUnaryBuiltin wraps a unary floating-point Go function
|
||||||
|
// as a Starlark built-in that accepts int or float arguments.
|
||||||
|
func newUnaryBuiltin(name string, fn func(float64) float64) *starlark.Builtin {
|
||||||
|
return starlark.NewBuiltin(name, func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var x floatOrInt
|
||||||
|
if err := starlark.UnpackPositionalArgs(name, args, kwargs, 1, &x); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return starlark.Float(fn(float64(x))), nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBinaryBuiltin wraps a binary floating-point Go function
|
||||||
|
// as a Starlark built-in that accepts int or float arguments.
|
||||||
|
func newBinaryBuiltin(name string, fn func(float64, float64) float64) *starlark.Builtin {
|
||||||
|
return starlark.NewBuiltin(name, func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var x, y floatOrInt
|
||||||
|
if err := starlark.UnpackPositionalArgs(name, args, kwargs, 2, &x, &y); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return starlark.Float(fn(float64(x), float64(y))), nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// log wraps the Log function
|
||||||
|
//
|
||||||
|
// as a Starlark built-in that accepts int or float arguments.
|
||||||
|
func log(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var (
|
||||||
|
x floatOrInt
|
||||||
|
base floatOrInt = math.E
|
||||||
|
)
|
||||||
|
if err := starlark.UnpackPositionalArgs("log", args, kwargs, 1, &x, &base); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if base == 1 {
|
||||||
|
return nil, errors.New("division by zero")
|
||||||
|
}
|
||||||
|
return starlark.Float(math.Log(float64(x)) / math.Log(float64(base))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ceil(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var x starlark.Value
|
||||||
|
|
||||||
|
if err := starlark.UnpackPositionalArgs("ceil", args, kwargs, 1, &x); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := x.(type) {
|
||||||
|
case starlark.Int:
|
||||||
|
return t, nil
|
||||||
|
case starlark.Float:
|
||||||
|
return starlark.NumberToInt(starlark.Float(math.Ceil(float64(t))))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("got %s, want float or int", x.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func floor(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var x starlark.Value
|
||||||
|
|
||||||
|
if err := starlark.UnpackPositionalArgs("floor", args, kwargs, 1, &x); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := x.(type) {
|
||||||
|
case starlark.Int:
|
||||||
|
return t, nil
|
||||||
|
case starlark.Float:
|
||||||
|
return starlark.NumberToInt(starlark.Float(math.Floor(float64(t))))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("got %s, want float or int", x.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func degrees(x float64) float64 {
|
||||||
|
return 360 * x / (2 * math.Pi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func radians(x float64) float64 {
|
||||||
|
return 2 * math.Pi * x / 360
|
||||||
|
}
|
||||||
74
vendor/go.starlark.net/resolve/binding.go
generated
vendored
Normal file
74
vendor/go.starlark.net/resolve/binding.go
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright 2019 The Bazel 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 resolve
|
||||||
|
|
||||||
|
import "go.starlark.net/syntax"
|
||||||
|
|
||||||
|
// This file defines resolver data types saved in the syntax tree.
|
||||||
|
// We cannot guarantee API stability for these types
|
||||||
|
// as they are closely tied to the implementation.
|
||||||
|
|
||||||
|
// A Binding contains resolver information about an identifier.
|
||||||
|
// The resolver populates the Binding field of each syntax.Identifier.
|
||||||
|
// The Binding ties together all identifiers that denote the same variable.
|
||||||
|
type Binding struct {
|
||||||
|
Scope Scope
|
||||||
|
|
||||||
|
// Index records the index into the enclosing
|
||||||
|
// - {DefStmt,File}.Locals, if Scope==Local
|
||||||
|
// - DefStmt.FreeVars, if Scope==Free
|
||||||
|
// - File.Globals, if Scope==Global.
|
||||||
|
// It is zero if Scope is Predeclared, Universal, or Undefined.
|
||||||
|
Index int
|
||||||
|
|
||||||
|
First *syntax.Ident // first binding use (iff Scope==Local/Free/Global)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Scope of Binding indicates what kind of scope it has.
|
||||||
|
type Scope uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Undefined Scope = iota // name is not defined
|
||||||
|
Local // name is local to its function or file
|
||||||
|
Cell // name is function-local but shared with a nested function
|
||||||
|
Free // name is cell of some enclosing function
|
||||||
|
Global // name is global to module
|
||||||
|
Predeclared // name is predeclared for this module (e.g. glob)
|
||||||
|
Universal // name is universal (e.g. len)
|
||||||
|
)
|
||||||
|
|
||||||
|
var scopeNames = [...]string{
|
||||||
|
Undefined: "undefined",
|
||||||
|
Local: "local",
|
||||||
|
Cell: "cell",
|
||||||
|
Free: "free",
|
||||||
|
Global: "global",
|
||||||
|
Predeclared: "predeclared",
|
||||||
|
Universal: "universal",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scope Scope) String() string { return scopeNames[scope] }
|
||||||
|
|
||||||
|
// A Module contains resolver information about a file.
|
||||||
|
// The resolver populates the Module field of each syntax.File.
|
||||||
|
type Module struct {
|
||||||
|
Locals []*Binding // the file's (comprehension-)local variables
|
||||||
|
Globals []*Binding // the file's global variables
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Function contains resolver information about a named or anonymous function.
|
||||||
|
// The resolver populates the Function field of each syntax.DefStmt and syntax.LambdaExpr.
|
||||||
|
type Function struct {
|
||||||
|
Pos syntax.Position // of DEF or LAMBDA
|
||||||
|
Name string // name of def, or "lambda"
|
||||||
|
Params []syntax.Expr // param = ident | ident=expr | * | *ident | **ident
|
||||||
|
Body []syntax.Stmt // contains synthetic 'return expr' for lambda
|
||||||
|
|
||||||
|
HasVarargs bool // whether params includes *args (convenience)
|
||||||
|
HasKwargs bool // whether params includes **kwargs (convenience)
|
||||||
|
NumKwonlyParams int // number of keyword-only optional parameters
|
||||||
|
Locals []*Binding // this function's local/cell variables, parameters first
|
||||||
|
FreeVars []*Binding // enclosing cells to capture in closure
|
||||||
|
}
|
||||||
996
vendor/go.starlark.net/resolve/resolve.go
generated
vendored
Normal file
996
vendor/go.starlark.net/resolve/resolve.go
generated
vendored
Normal file
|
|
@ -0,0 +1,996 @@
|
||||||
|
// Copyright 2017 The Bazel 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 resolve defines a name-resolution pass for Starlark abstract
|
||||||
|
// syntax trees.
|
||||||
|
//
|
||||||
|
// The resolver sets the Locals and FreeVars arrays of each DefStmt and
|
||||||
|
// the LocalIndex field of each syntax.Ident that refers to a local or
|
||||||
|
// free variable. It also sets the Locals array of a File for locals
|
||||||
|
// bound by top-level comprehensions and load statements.
|
||||||
|
// Identifiers for global variables do not get an index.
|
||||||
|
package resolve // import "go.starlark.net/resolve"
|
||||||
|
|
||||||
|
// All references to names are statically resolved. Names may be
|
||||||
|
// predeclared, global, or local to a function or file.
|
||||||
|
// File-local variables include those bound by top-level comprehensions
|
||||||
|
// and by load statements. ("Top-level" means "outside of any function".)
|
||||||
|
// The resolver maps each global name to a small integer and each local
|
||||||
|
// name to a small integer; these integers enable a fast and compact
|
||||||
|
// representation of globals and locals in the evaluator.
|
||||||
|
//
|
||||||
|
// As an optimization, the resolver classifies each predeclared name as
|
||||||
|
// either universal (e.g. None, len) or per-module (e.g. glob in Bazel's
|
||||||
|
// build language), enabling the evaluator to share the representation
|
||||||
|
// of the universal environment across all modules.
|
||||||
|
//
|
||||||
|
// The lexical environment is a tree of blocks with the file block at
|
||||||
|
// its root. The file's child blocks may be of two kinds: functions
|
||||||
|
// and comprehensions, and these may have further children of either
|
||||||
|
// kind.
|
||||||
|
//
|
||||||
|
// Python-style resolution requires multiple passes because a name is
|
||||||
|
// determined to be local to a function only if the function contains a
|
||||||
|
// "binding" use of it; similarly, a name is determined to be global (as
|
||||||
|
// opposed to predeclared) if the module contains a top-level binding use.
|
||||||
|
// Unlike ordinary top-level assignments, the bindings created by load
|
||||||
|
// statements are local to the file block.
|
||||||
|
// A non-binding use may lexically precede the binding to which it is resolved.
|
||||||
|
// In the first pass, we inspect each function, recording in
|
||||||
|
// 'uses' each identifier and the environment block in which it occurs.
|
||||||
|
// If a use of a name is binding, such as a function parameter or
|
||||||
|
// assignment, we add the name to the block's bindings mapping and add a
|
||||||
|
// local variable to the enclosing function.
|
||||||
|
//
|
||||||
|
// As we finish resolving each function, we inspect all the uses within
|
||||||
|
// that function and discard ones that were found to be function-local. The
|
||||||
|
// remaining ones must be either free (local to some lexically enclosing
|
||||||
|
// function), or top-level (global, predeclared, or file-local), but we cannot tell
|
||||||
|
// which until we have finished inspecting the outermost enclosing
|
||||||
|
// function. At that point, we can distinguish local from top-level names
|
||||||
|
// (and this is when Python would compute free variables).
|
||||||
|
//
|
||||||
|
// However, Starlark additionally requires that all references to global
|
||||||
|
// names are satisfied by some declaration in the current module;
|
||||||
|
// Starlark permits a function to forward-reference a global or file-local
|
||||||
|
// that has not
|
||||||
|
// been declared yet so long as it is declared before the end of the
|
||||||
|
// module. So, instead of re-resolving the unresolved references after
|
||||||
|
// each top-level function, we defer this until the end of the module
|
||||||
|
// and ensure that all such references are satisfied by some definition.
|
||||||
|
//
|
||||||
|
// At the end of the module, we visit each of the nested function blocks
|
||||||
|
// in bottom-up order, doing a recursive lexical lookup for each
|
||||||
|
// unresolved name. If the name is found to be local to some enclosing
|
||||||
|
// function, we must create a DefStmt.FreeVar (capture) parameter for
|
||||||
|
// each intervening function. We enter these synthetic bindings into
|
||||||
|
// the bindings map so that we create at most one freevar per name. If
|
||||||
|
// the name was not local, we check that it was defined at module level.
|
||||||
|
//
|
||||||
|
// We resolve all uses of locals in the module (due to load statements
|
||||||
|
// and comprehensions) in a similar way and compute the file's set of
|
||||||
|
// local variables.
|
||||||
|
//
|
||||||
|
// Starlark enforces that all global names are assigned at most once on
|
||||||
|
// all control flow paths by forbidding if/else statements and loops at
|
||||||
|
// top level. A global may be used before it is defined, leading to a
|
||||||
|
// dynamic error. However, the AllowGlobalReassign flag (really: allow
|
||||||
|
// top-level reassign) makes the resolver allow multiple to a variable
|
||||||
|
// at top-level. It also allows if-, for-, and while-loops at top-level,
|
||||||
|
// which in turn may make the evaluator dynamically assign multiple
|
||||||
|
// values to a variable at top-level. (These two roles should be separated.)
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.starlark.net/internal/spell"
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
const debug = false
|
||||||
|
const doesnt = "this Starlark dialect does not "
|
||||||
|
|
||||||
|
// Global options: these features are either not standard Starlark
|
||||||
|
// (yet), or deprecated features of the BUILD language, so we put them
|
||||||
|
// behind flags.
|
||||||
|
//
|
||||||
|
// Deprecated: use an explicit [syntax.FileOptions] argument instead,
|
||||||
|
// as it avoids all the usual problems of global variables,
|
||||||
|
// and permits finer control.
|
||||||
|
//
|
||||||
|
// For example The legacy AllowGlobalReassign flag controls three
|
||||||
|
// FileOptions: the availability of 'while' loops at all; the use of
|
||||||
|
// if/for/while constructs at top level; and the ability to reassign
|
||||||
|
// a global variable.
|
||||||
|
var (
|
||||||
|
AllowGlobalReassign = false // allow reassignment to top-level names; while loops; and if/for/while at top-level
|
||||||
|
AllowRecursion = false // allow recursive functions
|
||||||
|
LoadBindsGlobally = false // load creates global not file-local bindings (deprecated)
|
||||||
|
|
||||||
|
// obsolete flags for features that are now standard. No effect.
|
||||||
|
AllowBitwise = true
|
||||||
|
AllowFloat = true
|
||||||
|
AllowLambda = true
|
||||||
|
AllowNestedDef = true
|
||||||
|
AllowSet = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// File resolves the specified file and records information about the
|
||||||
|
// module in file.Module.
|
||||||
|
//
|
||||||
|
// The isPredeclared and isUniversal predicates report whether a name is
|
||||||
|
// a pre-declared identifier (visible in the current module) or a
|
||||||
|
// universal identifier (visible in every module).
|
||||||
|
// Clients should typically pass predeclared.Has for the first and
|
||||||
|
// starlark.Universe.Has for the second, where predeclared is the
|
||||||
|
// module's StringDict of predeclared names and starlark.Universe is the
|
||||||
|
// standard set of built-ins.
|
||||||
|
// The isUniverse predicate is supplied a parameter to avoid a cyclic
|
||||||
|
// dependency upon starlark.Universe, not because users should ever need
|
||||||
|
// to redefine it.
|
||||||
|
func File(file *syntax.File, isPredeclared, isUniversal func(name string) bool) error {
|
||||||
|
return REPLChunk(file, nil, isPredeclared, isUniversal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// REPLChunk is a generalization of the File function that supports a
|
||||||
|
// non-empty initial global block, as occurs in a REPL.
|
||||||
|
func REPLChunk(file *syntax.File, isGlobal, isPredeclared, isUniversal func(name string) bool) error {
|
||||||
|
r := newResolver(file.Options, isGlobal, isPredeclared, isUniversal)
|
||||||
|
r.stmts(file.Stmts)
|
||||||
|
|
||||||
|
r.env.resolveLocalUses()
|
||||||
|
|
||||||
|
// At the end of the module, resolve all non-local variable references,
|
||||||
|
// computing closures.
|
||||||
|
// Function bodies may contain forward references to later global declarations.
|
||||||
|
r.resolveNonLocalUses(r.env)
|
||||||
|
|
||||||
|
file.Module = &Module{
|
||||||
|
Locals: r.moduleLocals,
|
||||||
|
Globals: r.moduleGlobals,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r.errors) > 0 {
|
||||||
|
return r.errors
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expr calls [ExprOptions] using [syntax.LegacyFileOptions].
|
||||||
|
//
|
||||||
|
// Deprecated: use [ExprOptions] with [syntax.FileOptions] instead,
|
||||||
|
// because this function relies on legacy global variables.
|
||||||
|
func Expr(expr syntax.Expr, isPredeclared, isUniversal func(name string) bool) ([]*Binding, error) {
|
||||||
|
return ExprOptions(syntax.LegacyFileOptions(), expr, isPredeclared, isUniversal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExprOptions resolves the specified expression.
|
||||||
|
// It returns the local variables bound within the expression.
|
||||||
|
//
|
||||||
|
// The isPredeclared and isUniversal predicates behave as for the File function
|
||||||
|
func ExprOptions(opts *syntax.FileOptions, expr syntax.Expr, isPredeclared, isUniversal func(name string) bool) ([]*Binding, error) {
|
||||||
|
r := newResolver(opts, nil, isPredeclared, isUniversal)
|
||||||
|
r.expr(expr)
|
||||||
|
r.env.resolveLocalUses()
|
||||||
|
r.resolveNonLocalUses(r.env) // globals & universals
|
||||||
|
if len(r.errors) > 0 {
|
||||||
|
return nil, r.errors
|
||||||
|
}
|
||||||
|
return r.moduleLocals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// An ErrorList is a non-empty list of resolver error messages.
|
||||||
|
type ErrorList []Error // len > 0
|
||||||
|
|
||||||
|
func (e ErrorList) Error() string { return e[0].Error() }
|
||||||
|
|
||||||
|
// An Error describes the nature and position of a resolver error.
|
||||||
|
type Error struct {
|
||||||
|
Pos syntax.Position
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Error) Error() string { return e.Pos.String() + ": " + e.Msg }
|
||||||
|
|
||||||
|
func newResolver(options *syntax.FileOptions, isGlobal, isPredeclared, isUniversal func(name string) bool) *resolver {
|
||||||
|
file := new(block)
|
||||||
|
return &resolver{
|
||||||
|
options: options,
|
||||||
|
file: file,
|
||||||
|
env: file,
|
||||||
|
isGlobal: isGlobal,
|
||||||
|
isPredeclared: isPredeclared,
|
||||||
|
isUniversal: isUniversal,
|
||||||
|
globals: make(map[string]*Binding),
|
||||||
|
predeclared: make(map[string]*Binding),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type resolver struct {
|
||||||
|
options *syntax.FileOptions
|
||||||
|
|
||||||
|
// env is the current local environment:
|
||||||
|
// a linked list of blocks, innermost first.
|
||||||
|
// The tail of the list is the file block.
|
||||||
|
env *block
|
||||||
|
file *block // file block (contains load bindings)
|
||||||
|
|
||||||
|
// moduleLocals contains the local variables of the module
|
||||||
|
// (due to load statements and comprehensions outside any function).
|
||||||
|
// moduleGlobals contains the global variables of the module.
|
||||||
|
moduleLocals []*Binding
|
||||||
|
moduleGlobals []*Binding
|
||||||
|
|
||||||
|
// globals maps each global name in the module to its binding.
|
||||||
|
// predeclared does the same for predeclared and universal names.
|
||||||
|
globals map[string]*Binding
|
||||||
|
predeclared map[string]*Binding
|
||||||
|
|
||||||
|
// These predicates report whether a name is
|
||||||
|
// pre-declared, either in this module or universally,
|
||||||
|
// or already declared in the module globals (as in a REPL).
|
||||||
|
// isGlobal may be nil.
|
||||||
|
isGlobal, isPredeclared, isUniversal func(name string) bool
|
||||||
|
|
||||||
|
loops int // number of enclosing for/while loops in current function (or file, if top-level)
|
||||||
|
ifstmts int // number of enclosing if statements loops
|
||||||
|
|
||||||
|
errors ErrorList
|
||||||
|
}
|
||||||
|
|
||||||
|
// container returns the innermost enclosing "container" block:
|
||||||
|
// a function (function != nil) or file (function == nil).
|
||||||
|
// Container blocks accumulate local variable bindings.
|
||||||
|
func (r *resolver) container() *block {
|
||||||
|
for b := r.env; ; b = b.parent {
|
||||||
|
if b.function != nil || b == r.file {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) push(b *block) {
|
||||||
|
r.env.children = append(r.env.children, b)
|
||||||
|
b.parent = r.env
|
||||||
|
r.env = b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) pop() { r.env = r.env.parent }
|
||||||
|
|
||||||
|
type block struct {
|
||||||
|
parent *block // nil for file block
|
||||||
|
|
||||||
|
// In the file (root) block, both these fields are nil.
|
||||||
|
function *Function // only for function blocks
|
||||||
|
comp *syntax.Comprehension // only for comprehension blocks
|
||||||
|
|
||||||
|
// bindings maps a name to its binding.
|
||||||
|
// A local binding has an index into its innermost enclosing container's locals array.
|
||||||
|
// A free binding has an index into its innermost enclosing function's freevars array.
|
||||||
|
bindings map[string]*Binding
|
||||||
|
|
||||||
|
// children records the child blocks of the current one.
|
||||||
|
children []*block
|
||||||
|
|
||||||
|
// uses records all identifiers seen in this container (function or file),
|
||||||
|
// and a reference to the environment in which they appear.
|
||||||
|
// As we leave each container block, we resolve them,
|
||||||
|
// so that only free and global ones remain.
|
||||||
|
// At the end of each top-level function we compute closures.
|
||||||
|
uses []use
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *block) bind(name string, bind *Binding) {
|
||||||
|
if b.bindings == nil {
|
||||||
|
b.bindings = make(map[string]*Binding)
|
||||||
|
}
|
||||||
|
b.bindings[name] = bind
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *block) String() string {
|
||||||
|
if b.function != nil {
|
||||||
|
return "function block at " + fmt.Sprint(b.function.Pos)
|
||||||
|
}
|
||||||
|
if b.comp != nil {
|
||||||
|
return "comprehension block at " + fmt.Sprint(b.comp.Span())
|
||||||
|
}
|
||||||
|
return "file block"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) errorf(posn syntax.Position, format string, args ...interface{}) {
|
||||||
|
r.errors = append(r.errors, Error{posn, fmt.Sprintf(format, args...)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// A use records an identifier and the environment in which it appears.
|
||||||
|
type use struct {
|
||||||
|
id *syntax.Ident
|
||||||
|
env *block
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind creates a binding for id: a global (not file-local)
|
||||||
|
// binding at top-level, a local binding otherwise.
|
||||||
|
// At top-level, it reports an error if a global or file-local
|
||||||
|
// binding already exists, unless AllowGlobalReassign.
|
||||||
|
// It sets id.Binding to the binding (whether old or new),
|
||||||
|
// and returns whether a binding already existed.
|
||||||
|
func (r *resolver) bind(id *syntax.Ident) bool {
|
||||||
|
// Binding outside any local (comprehension/function) block?
|
||||||
|
if r.env == r.file {
|
||||||
|
bind, ok := r.file.bindings[id.Name]
|
||||||
|
if !ok {
|
||||||
|
bind, ok = r.globals[id.Name]
|
||||||
|
if !ok {
|
||||||
|
// first global binding of this name
|
||||||
|
bind = &Binding{
|
||||||
|
First: id,
|
||||||
|
Scope: Global,
|
||||||
|
Index: len(r.moduleGlobals),
|
||||||
|
}
|
||||||
|
r.globals[id.Name] = bind
|
||||||
|
r.moduleGlobals = append(r.moduleGlobals, bind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ok && !r.options.GlobalReassign {
|
||||||
|
r.errorf(id.NamePos, "cannot reassign %s %s declared at %s",
|
||||||
|
bind.Scope, id.Name, bind.First.NamePos)
|
||||||
|
}
|
||||||
|
id.Binding = bind
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.bindLocal(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) bindLocal(id *syntax.Ident) bool {
|
||||||
|
// Mark this name as local to current block.
|
||||||
|
// Assign it a new local (positive) index in the current container.
|
||||||
|
_, ok := r.env.bindings[id.Name]
|
||||||
|
if !ok {
|
||||||
|
var locals *[]*Binding
|
||||||
|
if fn := r.container().function; fn != nil {
|
||||||
|
locals = &fn.Locals
|
||||||
|
} else {
|
||||||
|
locals = &r.moduleLocals
|
||||||
|
}
|
||||||
|
bind := &Binding{
|
||||||
|
First: id,
|
||||||
|
Scope: Local,
|
||||||
|
Index: len(*locals),
|
||||||
|
}
|
||||||
|
r.env.bind(id.Name, bind)
|
||||||
|
*locals = append(*locals, bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.use(id)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) use(id *syntax.Ident) {
|
||||||
|
use := use{id, r.env}
|
||||||
|
|
||||||
|
// The spec says that if there is a global binding of a name
|
||||||
|
// then all references to that name in that block refer to the
|
||||||
|
// global, even if the use precedes the def---just as for locals.
|
||||||
|
// For example, in this code,
|
||||||
|
//
|
||||||
|
// print(len); len=1; print(len)
|
||||||
|
//
|
||||||
|
// both occurrences of len refer to the len=1 binding, which
|
||||||
|
// completely shadows the predeclared len function.
|
||||||
|
//
|
||||||
|
// The rationale for these semantics, which differ from Python,
|
||||||
|
// is that the static meaning of len (a reference to a global)
|
||||||
|
// does not change depending on where it appears in the file.
|
||||||
|
// Of course, its dynamic meaning does change, from an error
|
||||||
|
// into a valid reference, so it's not clear these semantics
|
||||||
|
// have any practical advantage.
|
||||||
|
//
|
||||||
|
// In any case, the Bazel implementation lags behind the spec
|
||||||
|
// and follows Python behavior, so the first use of len refers
|
||||||
|
// to the predeclared function. This typically used in a BUILD
|
||||||
|
// file that redefines a predeclared name half way through,
|
||||||
|
// for example:
|
||||||
|
//
|
||||||
|
// proto_library(...) # built-in rule
|
||||||
|
// load("myproto.bzl", "proto_library")
|
||||||
|
// proto_library(...) # user-defined rule
|
||||||
|
//
|
||||||
|
// We will piggyback support for the legacy semantics on the
|
||||||
|
// AllowGlobalReassign flag, which is loosely related and also
|
||||||
|
// required for Bazel.
|
||||||
|
if r.options.GlobalReassign && r.env == r.file {
|
||||||
|
r.useToplevel(use)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b := r.container()
|
||||||
|
b.uses = append(b.uses, use)
|
||||||
|
}
|
||||||
|
|
||||||
|
// useToplevel resolves use.id as a reference to a name visible at top-level.
|
||||||
|
// The use.env field captures the original environment for error reporting.
|
||||||
|
func (r *resolver) useToplevel(use use) (bind *Binding) {
|
||||||
|
id := use.id
|
||||||
|
|
||||||
|
if prev, ok := r.file.bindings[id.Name]; ok {
|
||||||
|
// use of load-defined name in file block
|
||||||
|
bind = prev
|
||||||
|
} else if prev, ok := r.globals[id.Name]; ok {
|
||||||
|
// use of global declared by module
|
||||||
|
bind = prev
|
||||||
|
} else if r.isGlobal != nil && r.isGlobal(id.Name) {
|
||||||
|
// use of global defined in a previous REPL chunk
|
||||||
|
bind = &Binding{
|
||||||
|
First: id, // wrong: this is not even a binding use
|
||||||
|
Scope: Global,
|
||||||
|
Index: len(r.moduleGlobals),
|
||||||
|
}
|
||||||
|
r.globals[id.Name] = bind
|
||||||
|
r.moduleGlobals = append(r.moduleGlobals, bind)
|
||||||
|
} else if prev, ok := r.predeclared[id.Name]; ok {
|
||||||
|
// repeated use of predeclared or universal
|
||||||
|
bind = prev
|
||||||
|
} else if r.isPredeclared(id.Name) {
|
||||||
|
// use of pre-declared name
|
||||||
|
bind = &Binding{Scope: Predeclared}
|
||||||
|
r.predeclared[id.Name] = bind // save it
|
||||||
|
} else if r.isUniversal(id.Name) {
|
||||||
|
// use of universal name
|
||||||
|
if !r.options.Set && id.Name == "set" {
|
||||||
|
r.errorf(id.NamePos, doesnt+"support sets")
|
||||||
|
}
|
||||||
|
bind = &Binding{Scope: Universal}
|
||||||
|
r.predeclared[id.Name] = bind // save it
|
||||||
|
} else {
|
||||||
|
bind = &Binding{Scope: Undefined}
|
||||||
|
var hint string
|
||||||
|
if n := r.spellcheck(use); n != "" {
|
||||||
|
hint = fmt.Sprintf(" (did you mean %s?)", n)
|
||||||
|
}
|
||||||
|
r.errorf(id.NamePos, "undefined: %s%s", id.Name, hint)
|
||||||
|
}
|
||||||
|
id.Binding = bind
|
||||||
|
return bind
|
||||||
|
}
|
||||||
|
|
||||||
|
// spellcheck returns the most likely misspelling of
|
||||||
|
// the name use.id in the environment use.env.
|
||||||
|
func (r *resolver) spellcheck(use use) string {
|
||||||
|
var names []string
|
||||||
|
|
||||||
|
// locals
|
||||||
|
for b := use.env; b != nil; b = b.parent {
|
||||||
|
for name := range b.bindings {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// globals
|
||||||
|
//
|
||||||
|
// We have no way to enumerate the sets whose membership
|
||||||
|
// tests are isPredeclared, isUniverse, and isGlobal,
|
||||||
|
// which includes prior names in the REPL session.
|
||||||
|
for _, bind := range r.moduleGlobals {
|
||||||
|
names = append(names, bind.First.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(names)
|
||||||
|
return spell.Nearest(use.id.Name, names)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveLocalUses is called when leaving a container (function/module)
|
||||||
|
// block. It resolves all uses of locals/cells within that block.
|
||||||
|
func (b *block) resolveLocalUses() {
|
||||||
|
unresolved := b.uses[:0]
|
||||||
|
for _, use := range b.uses {
|
||||||
|
if bind := lookupLocal(use); bind != nil && (bind.Scope == Local || bind.Scope == Cell) {
|
||||||
|
use.id.Binding = bind
|
||||||
|
} else {
|
||||||
|
unresolved = append(unresolved, use)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.uses = unresolved
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) stmts(stmts []syntax.Stmt) {
|
||||||
|
for _, stmt := range stmts {
|
||||||
|
r.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) stmt(stmt syntax.Stmt) {
|
||||||
|
switch stmt := stmt.(type) {
|
||||||
|
case *syntax.ExprStmt:
|
||||||
|
r.expr(stmt.X)
|
||||||
|
|
||||||
|
case *syntax.BranchStmt:
|
||||||
|
if r.loops == 0 && (stmt.Token == syntax.BREAK || stmt.Token == syntax.CONTINUE) {
|
||||||
|
r.errorf(stmt.TokenPos, "%s not in a loop", stmt.Token)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.IfStmt:
|
||||||
|
if !r.options.TopLevelControl && r.container().function == nil {
|
||||||
|
r.errorf(stmt.If, "if statement not within a function")
|
||||||
|
}
|
||||||
|
r.expr(stmt.Cond)
|
||||||
|
r.ifstmts++
|
||||||
|
r.stmts(stmt.True)
|
||||||
|
r.stmts(stmt.False)
|
||||||
|
r.ifstmts--
|
||||||
|
|
||||||
|
case *syntax.AssignStmt:
|
||||||
|
r.expr(stmt.RHS)
|
||||||
|
isAugmented := stmt.Op != syntax.EQ
|
||||||
|
r.assign(stmt.LHS, isAugmented)
|
||||||
|
|
||||||
|
case *syntax.DefStmt:
|
||||||
|
r.bind(stmt.Name)
|
||||||
|
fn := &Function{
|
||||||
|
Name: stmt.Name.Name,
|
||||||
|
Pos: stmt.Def,
|
||||||
|
Params: stmt.Params,
|
||||||
|
Body: stmt.Body,
|
||||||
|
}
|
||||||
|
stmt.Function = fn
|
||||||
|
r.function(fn, stmt.Def)
|
||||||
|
|
||||||
|
case *syntax.ForStmt:
|
||||||
|
if !r.options.TopLevelControl && r.container().function == nil {
|
||||||
|
r.errorf(stmt.For, "for loop not within a function")
|
||||||
|
}
|
||||||
|
r.expr(stmt.X)
|
||||||
|
const isAugmented = false
|
||||||
|
r.assign(stmt.Vars, isAugmented)
|
||||||
|
r.loops++
|
||||||
|
r.stmts(stmt.Body)
|
||||||
|
r.loops--
|
||||||
|
|
||||||
|
case *syntax.WhileStmt:
|
||||||
|
if !r.options.While {
|
||||||
|
r.errorf(stmt.While, doesnt+"support while loops")
|
||||||
|
}
|
||||||
|
if !r.options.TopLevelControl && r.container().function == nil {
|
||||||
|
r.errorf(stmt.While, "while loop not within a function")
|
||||||
|
}
|
||||||
|
r.expr(stmt.Cond)
|
||||||
|
r.loops++
|
||||||
|
r.stmts(stmt.Body)
|
||||||
|
r.loops--
|
||||||
|
|
||||||
|
case *syntax.ReturnStmt:
|
||||||
|
if r.container().function == nil {
|
||||||
|
r.errorf(stmt.Return, "return statement not within a function")
|
||||||
|
}
|
||||||
|
if stmt.Result != nil {
|
||||||
|
r.expr(stmt.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.LoadStmt:
|
||||||
|
// A load statement may not be nested in any other statement.
|
||||||
|
if r.container().function != nil {
|
||||||
|
r.errorf(stmt.Load, "load statement within a function")
|
||||||
|
} else if r.loops > 0 {
|
||||||
|
r.errorf(stmt.Load, "load statement within a loop")
|
||||||
|
} else if r.ifstmts > 0 {
|
||||||
|
r.errorf(stmt.Load, "load statement within a conditional")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, from := range stmt.From {
|
||||||
|
if from.Name == "" {
|
||||||
|
r.errorf(from.NamePos, "load: empty identifier")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if from.Name[0] == '_' {
|
||||||
|
r.errorf(from.NamePos, "load: names with leading underscores are not exported: %s", from.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := stmt.To[i]
|
||||||
|
if r.options.LoadBindsGlobally {
|
||||||
|
r.bind(id)
|
||||||
|
} else if r.bindLocal(id) && !r.options.GlobalReassign {
|
||||||
|
// "Global" in AllowGlobalReassign is a misnomer for "toplevel".
|
||||||
|
// Sadly we can't report the previous declaration
|
||||||
|
// as id.Binding may not be set yet.
|
||||||
|
r.errorf(id.NamePos, "cannot reassign top-level %s", id.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Panicf("unexpected stmt %T", stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) assign(lhs syntax.Expr, isAugmented bool) {
|
||||||
|
switch lhs := lhs.(type) {
|
||||||
|
case *syntax.Ident:
|
||||||
|
// x = ...
|
||||||
|
r.bind(lhs)
|
||||||
|
|
||||||
|
case *syntax.IndexExpr:
|
||||||
|
// x[i] = ...
|
||||||
|
r.expr(lhs.X)
|
||||||
|
r.expr(lhs.Y)
|
||||||
|
|
||||||
|
case *syntax.DotExpr:
|
||||||
|
// x.f = ...
|
||||||
|
r.expr(lhs.X)
|
||||||
|
|
||||||
|
case *syntax.TupleExpr:
|
||||||
|
// (x, y) = ...
|
||||||
|
if isAugmented {
|
||||||
|
r.errorf(syntax.Start(lhs), "can't use tuple expression in augmented assignment")
|
||||||
|
}
|
||||||
|
for _, elem := range lhs.List {
|
||||||
|
r.assign(elem, isAugmented)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.ListExpr:
|
||||||
|
// [x, y, z] = ...
|
||||||
|
if isAugmented {
|
||||||
|
r.errorf(syntax.Start(lhs), "can't use list expression in augmented assignment")
|
||||||
|
}
|
||||||
|
for _, elem := range lhs.List {
|
||||||
|
r.assign(elem, isAugmented)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.ParenExpr:
|
||||||
|
r.assign(lhs.X, isAugmented)
|
||||||
|
|
||||||
|
default:
|
||||||
|
name := strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", lhs), "*syntax."))
|
||||||
|
r.errorf(syntax.Start(lhs), "can't assign to %s", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) expr(e syntax.Expr) {
|
||||||
|
switch e := e.(type) {
|
||||||
|
case *syntax.Ident:
|
||||||
|
r.use(e)
|
||||||
|
|
||||||
|
case *syntax.Literal:
|
||||||
|
|
||||||
|
case *syntax.ListExpr:
|
||||||
|
for _, x := range e.List {
|
||||||
|
r.expr(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.CondExpr:
|
||||||
|
r.expr(e.Cond)
|
||||||
|
r.expr(e.True)
|
||||||
|
r.expr(e.False)
|
||||||
|
|
||||||
|
case *syntax.IndexExpr:
|
||||||
|
r.expr(e.X)
|
||||||
|
r.expr(e.Y)
|
||||||
|
|
||||||
|
case *syntax.DictEntry:
|
||||||
|
r.expr(e.Key)
|
||||||
|
r.expr(e.Value)
|
||||||
|
|
||||||
|
case *syntax.SliceExpr:
|
||||||
|
r.expr(e.X)
|
||||||
|
if e.Lo != nil {
|
||||||
|
r.expr(e.Lo)
|
||||||
|
}
|
||||||
|
if e.Hi != nil {
|
||||||
|
r.expr(e.Hi)
|
||||||
|
}
|
||||||
|
if e.Step != nil {
|
||||||
|
r.expr(e.Step)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.Comprehension:
|
||||||
|
// The 'in' operand of the first clause (always a ForClause)
|
||||||
|
// is resolved in the outer block; consider: [x for x in x].
|
||||||
|
clause := e.Clauses[0].(*syntax.ForClause)
|
||||||
|
r.expr(clause.X)
|
||||||
|
|
||||||
|
// A list/dict comprehension defines a new lexical block.
|
||||||
|
// Locals defined within the block will be allotted
|
||||||
|
// distinct slots in the locals array of the innermost
|
||||||
|
// enclosing container (function/module) block.
|
||||||
|
r.push(&block{comp: e})
|
||||||
|
|
||||||
|
const isAugmented = false
|
||||||
|
r.assign(clause.Vars, isAugmented)
|
||||||
|
|
||||||
|
for _, clause := range e.Clauses[1:] {
|
||||||
|
switch clause := clause.(type) {
|
||||||
|
case *syntax.IfClause:
|
||||||
|
r.expr(clause.Cond)
|
||||||
|
case *syntax.ForClause:
|
||||||
|
r.assign(clause.Vars, isAugmented)
|
||||||
|
r.expr(clause.X)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.expr(e.Body) // body may be *DictEntry
|
||||||
|
r.pop()
|
||||||
|
|
||||||
|
case *syntax.TupleExpr:
|
||||||
|
for _, x := range e.List {
|
||||||
|
r.expr(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.DictExpr:
|
||||||
|
for _, entry := range e.List {
|
||||||
|
entry := entry.(*syntax.DictEntry)
|
||||||
|
r.expr(entry.Key)
|
||||||
|
r.expr(entry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.UnaryExpr:
|
||||||
|
r.expr(e.X)
|
||||||
|
|
||||||
|
case *syntax.BinaryExpr:
|
||||||
|
r.expr(e.X)
|
||||||
|
r.expr(e.Y)
|
||||||
|
|
||||||
|
case *syntax.DotExpr:
|
||||||
|
r.expr(e.X)
|
||||||
|
// ignore e.Name
|
||||||
|
|
||||||
|
case *syntax.CallExpr:
|
||||||
|
r.expr(e.Fn)
|
||||||
|
var seenVarargs, seenKwargs bool
|
||||||
|
var seenName map[string]bool
|
||||||
|
var n, p int
|
||||||
|
for _, arg := range e.Args {
|
||||||
|
pos, _ := arg.Span()
|
||||||
|
if unop, ok := arg.(*syntax.UnaryExpr); ok && unop.Op == syntax.STARSTAR {
|
||||||
|
// **kwargs
|
||||||
|
if seenKwargs {
|
||||||
|
r.errorf(pos, "multiple **kwargs not allowed")
|
||||||
|
}
|
||||||
|
seenKwargs = true
|
||||||
|
r.expr(arg)
|
||||||
|
} else if ok && unop.Op == syntax.STAR {
|
||||||
|
// *args
|
||||||
|
if seenKwargs {
|
||||||
|
r.errorf(pos, "*args may not follow **kwargs")
|
||||||
|
} else if seenVarargs {
|
||||||
|
r.errorf(pos, "multiple *args not allowed")
|
||||||
|
}
|
||||||
|
seenVarargs = true
|
||||||
|
r.expr(arg)
|
||||||
|
} else if binop, ok := arg.(*syntax.BinaryExpr); ok && binop.Op == syntax.EQ {
|
||||||
|
// k=v
|
||||||
|
n++
|
||||||
|
if seenKwargs {
|
||||||
|
r.errorf(pos, "keyword argument may not follow **kwargs")
|
||||||
|
} else if seenVarargs {
|
||||||
|
r.errorf(pos, "keyword argument may not follow *args")
|
||||||
|
}
|
||||||
|
x := binop.X.(*syntax.Ident)
|
||||||
|
if seenName[x.Name] {
|
||||||
|
r.errorf(x.NamePos, "keyword argument %q is repeated", x.Name)
|
||||||
|
} else {
|
||||||
|
if seenName == nil {
|
||||||
|
seenName = make(map[string]bool)
|
||||||
|
}
|
||||||
|
seenName[x.Name] = true
|
||||||
|
}
|
||||||
|
r.expr(binop.Y)
|
||||||
|
} else {
|
||||||
|
// positional argument
|
||||||
|
p++
|
||||||
|
if seenVarargs {
|
||||||
|
r.errorf(pos, "positional argument may not follow *args")
|
||||||
|
} else if seenKwargs {
|
||||||
|
r.errorf(pos, "positional argument may not follow **kwargs")
|
||||||
|
} else if len(seenName) > 0 {
|
||||||
|
r.errorf(pos, "positional argument may not follow named")
|
||||||
|
}
|
||||||
|
r.expr(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail gracefully if compiler-imposed limit is exceeded.
|
||||||
|
if p >= 256 {
|
||||||
|
pos, _ := e.Span()
|
||||||
|
r.errorf(pos, "%v positional arguments in call, limit is 255", p)
|
||||||
|
}
|
||||||
|
if n >= 256 {
|
||||||
|
pos, _ := e.Span()
|
||||||
|
r.errorf(pos, "%v keyword arguments in call, limit is 255", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.LambdaExpr:
|
||||||
|
fn := &Function{
|
||||||
|
Name: "lambda",
|
||||||
|
Pos: e.Lambda,
|
||||||
|
Params: e.Params,
|
||||||
|
Body: []syntax.Stmt{&syntax.ReturnStmt{Result: e.Body}},
|
||||||
|
}
|
||||||
|
e.Function = fn
|
||||||
|
r.function(fn, e.Lambda)
|
||||||
|
|
||||||
|
case *syntax.ParenExpr:
|
||||||
|
r.expr(e.X)
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Panicf("unexpected expr %T", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) function(function *Function, pos syntax.Position) {
|
||||||
|
// Resolve defaults in enclosing environment.
|
||||||
|
for _, param := range function.Params {
|
||||||
|
if binary, ok := param.(*syntax.BinaryExpr); ok {
|
||||||
|
r.expr(binary.Y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter function block.
|
||||||
|
b := &block{function: function}
|
||||||
|
r.push(b)
|
||||||
|
|
||||||
|
// Save the current loop count and reset it for the new function
|
||||||
|
outerLoops := r.loops
|
||||||
|
r.loops = 0
|
||||||
|
|
||||||
|
var seenOptional bool
|
||||||
|
var star *syntax.UnaryExpr // * or *args param
|
||||||
|
var starStar *syntax.Ident // **kwargs ident
|
||||||
|
var numKwonlyParams int
|
||||||
|
for _, param := range function.Params {
|
||||||
|
switch param := param.(type) {
|
||||||
|
case *syntax.Ident:
|
||||||
|
// e.g. x
|
||||||
|
if starStar != nil {
|
||||||
|
r.errorf(param.NamePos, "required parameter may not follow **%s", starStar.Name)
|
||||||
|
} else if star != nil {
|
||||||
|
numKwonlyParams++
|
||||||
|
} else if seenOptional {
|
||||||
|
r.errorf(param.NamePos, "required parameter may not follow optional")
|
||||||
|
}
|
||||||
|
if r.bind(param) {
|
||||||
|
r.errorf(param.NamePos, "duplicate parameter: %s", param.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *syntax.BinaryExpr:
|
||||||
|
// e.g. y=dflt
|
||||||
|
if starStar != nil {
|
||||||
|
r.errorf(param.OpPos, "optional parameter may not follow **%s", starStar.Name)
|
||||||
|
} else if star != nil {
|
||||||
|
numKwonlyParams++
|
||||||
|
}
|
||||||
|
if id := param.X.(*syntax.Ident); r.bind(id) {
|
||||||
|
r.errorf(param.OpPos, "duplicate parameter: %s", id.Name)
|
||||||
|
}
|
||||||
|
seenOptional = true
|
||||||
|
|
||||||
|
case *syntax.UnaryExpr:
|
||||||
|
// * or *args or **kwargs
|
||||||
|
if param.Op == syntax.STAR {
|
||||||
|
if starStar != nil {
|
||||||
|
r.errorf(param.OpPos, "* parameter may not follow **%s", starStar.Name)
|
||||||
|
} else if star != nil {
|
||||||
|
r.errorf(param.OpPos, "multiple * parameters not allowed")
|
||||||
|
} else {
|
||||||
|
star = param
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if starStar != nil {
|
||||||
|
r.errorf(param.OpPos, "multiple ** parameters not allowed")
|
||||||
|
}
|
||||||
|
starStar = param.X.(*syntax.Ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the *args and **kwargs parameters at the end,
|
||||||
|
// so that regular parameters a/b/c are contiguous and
|
||||||
|
// there is no hole for the "*":
|
||||||
|
// def f(a, b, *args, c=0, **kwargs)
|
||||||
|
// def f(a, b, *, c=0, **kwargs)
|
||||||
|
if star != nil {
|
||||||
|
if id, _ := star.X.(*syntax.Ident); id != nil {
|
||||||
|
// *args
|
||||||
|
if r.bind(id) {
|
||||||
|
r.errorf(id.NamePos, "duplicate parameter: %s", id.Name)
|
||||||
|
}
|
||||||
|
function.HasVarargs = true
|
||||||
|
} else if numKwonlyParams == 0 {
|
||||||
|
r.errorf(star.OpPos, "bare * must be followed by keyword-only parameters")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if starStar != nil {
|
||||||
|
if r.bind(starStar) {
|
||||||
|
r.errorf(starStar.NamePos, "duplicate parameter: %s", starStar.Name)
|
||||||
|
}
|
||||||
|
function.HasKwargs = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function.NumKwonlyParams = numKwonlyParams
|
||||||
|
r.stmts(function.Body)
|
||||||
|
|
||||||
|
// Resolve all uses of this function's local vars,
|
||||||
|
// and keep just the remaining uses of free/global vars.
|
||||||
|
b.resolveLocalUses()
|
||||||
|
|
||||||
|
// Leave function block.
|
||||||
|
r.pop()
|
||||||
|
|
||||||
|
// Restore the outer loop count
|
||||||
|
r.loops = outerLoops
|
||||||
|
|
||||||
|
// References within the function body to globals are not
|
||||||
|
// resolved until the end of the module.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) resolveNonLocalUses(b *block) {
|
||||||
|
// First resolve inner blocks.
|
||||||
|
for _, child := range b.children {
|
||||||
|
r.resolveNonLocalUses(child)
|
||||||
|
}
|
||||||
|
for _, use := range b.uses {
|
||||||
|
use.id.Binding = r.lookupLexical(use, use.env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupLocal looks up an identifier within its immediately enclosing function.
|
||||||
|
func lookupLocal(use use) *Binding {
|
||||||
|
for env := use.env; env != nil; env = env.parent {
|
||||||
|
if bind, ok := env.bindings[use.id.Name]; ok {
|
||||||
|
if bind.Scope == Free {
|
||||||
|
// shouldn't exist till later
|
||||||
|
log.Panicf("%s: internal error: %s, %v", use.id.NamePos, use.id.Name, bind)
|
||||||
|
}
|
||||||
|
return bind // found
|
||||||
|
}
|
||||||
|
if env.function != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil // not found in this function
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupLexical looks up an identifier use.id within its lexically enclosing environment.
|
||||||
|
// The use.env field captures the original environment for error reporting.
|
||||||
|
func (r *resolver) lookupLexical(use use, env *block) (bind *Binding) {
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("lookupLexical %s in %s = ...\n", use.id.Name, env)
|
||||||
|
defer func() { fmt.Printf("= %v\n", bind) }()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this the file block?
|
||||||
|
if env == r.file {
|
||||||
|
return r.useToplevel(use) // file-local, global, predeclared, or not found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defined in this block?
|
||||||
|
bind, ok := env.bindings[use.id.Name]
|
||||||
|
if !ok {
|
||||||
|
// Defined in parent block?
|
||||||
|
bind = r.lookupLexical(use, env.parent)
|
||||||
|
if env.function != nil && (bind.Scope == Local || bind.Scope == Free || bind.Scope == Cell) {
|
||||||
|
// Found in parent block, which belongs to enclosing function.
|
||||||
|
// Add the parent's binding to the function's freevars,
|
||||||
|
// and add a new 'free' binding to the inner function's block,
|
||||||
|
// and turn the parent's local into cell.
|
||||||
|
if bind.Scope == Local {
|
||||||
|
bind.Scope = Cell
|
||||||
|
}
|
||||||
|
index := len(env.function.FreeVars)
|
||||||
|
env.function.FreeVars = append(env.function.FreeVars, bind)
|
||||||
|
bind = &Binding{
|
||||||
|
First: bind.First,
|
||||||
|
Scope: Free,
|
||||||
|
Index: index,
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("creating freevar %v in function at %s: %s\n",
|
||||||
|
len(env.function.FreeVars), env.function.Pos, use.id.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memoize, to avoid duplicate free vars
|
||||||
|
// and redundant global (failing) lookups.
|
||||||
|
env.bind(use.id.Name, bind)
|
||||||
|
}
|
||||||
|
return bind
|
||||||
|
}
|
||||||
60
vendor/go.starlark.net/starlark/debug.go
generated
vendored
Normal file
60
vendor/go.starlark.net/starlark/debug.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
package starlark
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file defines an experimental API for the debugging tools.
|
||||||
|
// Some of these declarations expose details of internal packages.
|
||||||
|
// (The debugger makes liberal use of exported fields of unexported types.)
|
||||||
|
// Breaking changes may occur without notice.
|
||||||
|
|
||||||
|
// A Binding is the name and position of a binding identifier.
|
||||||
|
type Binding struct {
|
||||||
|
Name string
|
||||||
|
Pos syntax.Position
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumLocals returns the number of local variables of this frame.
|
||||||
|
// It is zero unless fr.Callable() is a *Function.
|
||||||
|
func (fr *frame) NumLocals() int { return len(fr.locals) }
|
||||||
|
|
||||||
|
// Local returns the binding (name and binding position) and value of
|
||||||
|
// the i'th local variable of the frame's function.
|
||||||
|
// Beware: the value may be nil if it has not yet been assigned!
|
||||||
|
//
|
||||||
|
// The index i must be less than [NumLocals].
|
||||||
|
// Local may be called only while the frame is active.
|
||||||
|
//
|
||||||
|
// This function is provided only for debugging tools.
|
||||||
|
func (fr *frame) Local(i int) (Binding, Value) {
|
||||||
|
return Binding(fr.callable.(*Function).funcode.Locals[i]), fr.locals[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// DebugFrame is the debugger API for a frame of the interpreter's call stack.
|
||||||
|
//
|
||||||
|
// Most applications have no need for this API; use CallFrame instead.
|
||||||
|
//
|
||||||
|
// It may be tempting to use this interface when implementing built-in
|
||||||
|
// functions. Beware that reflection over the call stack is easily
|
||||||
|
// abused, leading to built-in functions whose behavior is mysterious
|
||||||
|
// and unpredictable.
|
||||||
|
//
|
||||||
|
// Clients must not retain a DebugFrame nor call any of its methods once
|
||||||
|
// the current built-in call has returned or execution has resumed
|
||||||
|
// after a breakpoint as this may have unpredictable effects, including
|
||||||
|
// but not limited to retention of object that would otherwise be garbage.
|
||||||
|
type DebugFrame interface {
|
||||||
|
Callable() Callable // returns the frame's function
|
||||||
|
NumLocals() int // returns the number of local variables in this frame
|
||||||
|
Local(i int) (Binding, Value) // returns the binding and value of the (Starlark) frame's ith local variable
|
||||||
|
Position() syntax.Position // returns the current position of execution in this frame
|
||||||
|
}
|
||||||
|
|
||||||
|
// DebugFrame returns the debugger interface for
|
||||||
|
// the specified frame of the interpreter's call stack.
|
||||||
|
// Frame numbering is as for Thread.CallFrame: 0 <= depth < thread.CallStackDepth().
|
||||||
|
//
|
||||||
|
// This function is intended for use in debugging tools.
|
||||||
|
// Most applications should have no need for it; use CallFrame instead.
|
||||||
|
func (thread *Thread) DebugFrame(depth int) DebugFrame { return thread.frameAt(depth) }
|
||||||
3
vendor/go.starlark.net/starlark/empty.s
generated
vendored
Normal file
3
vendor/go.starlark.net/starlark/empty.s
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
// The presence of this file allows the package to use the
|
||||||
|
// "go:linkname" hack to call non-exported functions in the
|
||||||
|
// Go runtime, such as hardware-accelerated string hashing.
|
||||||
1641
vendor/go.starlark.net/starlark/eval.go
generated
vendored
Normal file
1641
vendor/go.starlark.net/starlark/eval.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
450
vendor/go.starlark.net/starlark/hashtable.go
generated
vendored
Normal file
450
vendor/go.starlark.net/starlark/hashtable.go
generated
vendored
Normal file
|
|
@ -0,0 +1,450 @@
|
||||||
|
// Copyright 2017 The Bazel 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 starlark
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hash/maphash"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// hashtable is used to represent Starlark dict and set values.
|
||||||
|
// It is a hash table whose key/value entries form a doubly-linked list
|
||||||
|
// in the order the entries were inserted.
|
||||||
|
//
|
||||||
|
// Initialized instances of hashtable must not be copied.
|
||||||
|
type hashtable struct {
|
||||||
|
table []bucket // len is zero or a power of two
|
||||||
|
bucket0 [1]bucket // inline allocation for small maps.
|
||||||
|
len uint32
|
||||||
|
itercount uint32 // number of active iterators (ignored if frozen)
|
||||||
|
head *entry // insertion order doubly-linked list; may be nil
|
||||||
|
tailLink **entry // address of nil link at end of list (perhaps &head)
|
||||||
|
frozen bool
|
||||||
|
|
||||||
|
_ noCopy // triggers vet copylock check on this type.
|
||||||
|
}
|
||||||
|
|
||||||
|
// noCopy is zero-sized type that triggers vet's copylock check.
|
||||||
|
// See https://github.com/golang/go/issues/8005#issuecomment-190753527.
|
||||||
|
type noCopy struct{}
|
||||||
|
|
||||||
|
func (*noCopy) Lock() {}
|
||||||
|
func (*noCopy) Unlock() {}
|
||||||
|
|
||||||
|
const bucketSize = 8
|
||||||
|
|
||||||
|
type bucket struct {
|
||||||
|
entries [bucketSize]entry
|
||||||
|
next *bucket // linked list of buckets
|
||||||
|
}
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
hash uint32 // nonzero => in use
|
||||||
|
key, value Value
|
||||||
|
next *entry // insertion order doubly-linked list; may be nil
|
||||||
|
prevLink **entry // address of link to this entry (perhaps &head)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) init(size int) {
|
||||||
|
if size < 0 {
|
||||||
|
panic("size < 0")
|
||||||
|
}
|
||||||
|
nb := 1
|
||||||
|
for overloaded(size, nb) {
|
||||||
|
nb = nb << 1
|
||||||
|
}
|
||||||
|
if nb < 2 {
|
||||||
|
ht.table = ht.bucket0[:1]
|
||||||
|
} else {
|
||||||
|
ht.table = make([]bucket, nb)
|
||||||
|
}
|
||||||
|
ht.tailLink = &ht.head
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) freeze() {
|
||||||
|
if !ht.frozen {
|
||||||
|
ht.frozen = true
|
||||||
|
for e := ht.head; e != nil; e = e.next {
|
||||||
|
e.key.Freeze()
|
||||||
|
e.value.Freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) insert(k, v Value) error {
|
||||||
|
if err := ht.checkMutable("insert into"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ht.table == nil {
|
||||||
|
ht.init(1)
|
||||||
|
}
|
||||||
|
h, err := k.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if h == 0 {
|
||||||
|
h = 1 // zero is reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
var insert *entry
|
||||||
|
|
||||||
|
// Inspect each bucket in the bucket list.
|
||||||
|
p := &ht.table[h&(uint32(len(ht.table)-1))]
|
||||||
|
for {
|
||||||
|
for i := range p.entries {
|
||||||
|
e := &p.entries[i]
|
||||||
|
if e.hash != h {
|
||||||
|
if e.hash == 0 {
|
||||||
|
// Found empty entry; make a note.
|
||||||
|
insert = e
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if eq, err := Equal(k, e.key); err != nil {
|
||||||
|
return err // e.g. excessively recursive tuple
|
||||||
|
} else if !eq {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Key already present; update value.
|
||||||
|
e.value = v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p.next == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p = p.next
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key not found. p points to the last bucket.
|
||||||
|
|
||||||
|
// Does the number of elements exceed the buckets' load factor?
|
||||||
|
if overloaded(int(ht.len), len(ht.table)) {
|
||||||
|
ht.grow()
|
||||||
|
goto retry
|
||||||
|
}
|
||||||
|
|
||||||
|
if insert == nil {
|
||||||
|
// No space in existing buckets. Add a new one to the bucket list.
|
||||||
|
b := new(bucket)
|
||||||
|
p.next = b
|
||||||
|
insert = &b.entries[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert key/value pair.
|
||||||
|
insert.hash = h
|
||||||
|
insert.key = k
|
||||||
|
insert.value = v
|
||||||
|
|
||||||
|
// Append entry to doubly-linked list.
|
||||||
|
insert.prevLink = ht.tailLink
|
||||||
|
*ht.tailLink = insert
|
||||||
|
ht.tailLink = &insert.next
|
||||||
|
|
||||||
|
ht.len++
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func overloaded(elems, buckets int) bool {
|
||||||
|
const loadFactor = 6.5 // just a guess
|
||||||
|
return elems >= bucketSize && float64(elems) >= loadFactor*float64(buckets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) grow() {
|
||||||
|
// Double the number of buckets and rehash.
|
||||||
|
//
|
||||||
|
// Even though this makes reentrant calls to ht.insert,
|
||||||
|
// calls Equals unnecessarily (since there can't be duplicate keys),
|
||||||
|
// and recomputes the hash unnecessarily, the gains from
|
||||||
|
// avoiding these steps were found to be too small to justify
|
||||||
|
// the extra logic: -2% on hashtable benchmark.
|
||||||
|
ht.table = make([]bucket, len(ht.table)<<1)
|
||||||
|
oldhead := ht.head
|
||||||
|
ht.head = nil
|
||||||
|
ht.tailLink = &ht.head
|
||||||
|
ht.len = 0
|
||||||
|
for e := oldhead; e != nil; e = e.next {
|
||||||
|
ht.insert(e.key, e.value)
|
||||||
|
}
|
||||||
|
ht.bucket0[0] = bucket{} // clear out unused initial bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) lookup(k Value) (v Value, found bool, err error) {
|
||||||
|
h, err := k.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err // unhashable
|
||||||
|
}
|
||||||
|
if h == 0 {
|
||||||
|
h = 1 // zero is reserved
|
||||||
|
}
|
||||||
|
if ht.table == nil {
|
||||||
|
return None, false, nil // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspect each bucket in the bucket list.
|
||||||
|
for p := &ht.table[h&(uint32(len(ht.table)-1))]; p != nil; p = p.next {
|
||||||
|
for i := range p.entries {
|
||||||
|
e := &p.entries[i]
|
||||||
|
if e.hash == h {
|
||||||
|
if eq, err := Equal(k, e.key); err != nil {
|
||||||
|
return nil, false, err // e.g. excessively recursive tuple
|
||||||
|
} else if eq {
|
||||||
|
return e.value, true, nil // found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None, false, nil // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
// count returns the number of distinct elements of iter that are elements of ht.
|
||||||
|
func (ht *hashtable) count(iter Iterator) (int, error) {
|
||||||
|
if ht.table == nil {
|
||||||
|
return 0, nil // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
var k Value
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
// Use a bitset per table entry to record seen elements of ht.
|
||||||
|
// Elements are identified by their bucket number and index within the bucket.
|
||||||
|
// Each bitset gets one word initially, but may grow.
|
||||||
|
storage := make([]big.Word, len(ht.table))
|
||||||
|
bitsets := make([]big.Int, len(ht.table))
|
||||||
|
for i := range bitsets {
|
||||||
|
bitsets[i].SetBits(storage[i : i+1 : i+1])
|
||||||
|
}
|
||||||
|
for iter.Next(&k) && count != int(ht.len) {
|
||||||
|
h, err := k.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err // unhashable
|
||||||
|
}
|
||||||
|
if h == 0 {
|
||||||
|
h = 1 // zero is reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspect each bucket in the bucket list.
|
||||||
|
bucketId := h & (uint32(len(ht.table) - 1))
|
||||||
|
i := 0
|
||||||
|
for p := &ht.table[bucketId]; p != nil; p = p.next {
|
||||||
|
for j := range p.entries {
|
||||||
|
e := &p.entries[j]
|
||||||
|
if e.hash == h {
|
||||||
|
if eq, err := Equal(k, e.key); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if eq {
|
||||||
|
bitIndex := i<<3 + j
|
||||||
|
if bitsets[bucketId].Bit(bitIndex) == 0 {
|
||||||
|
bitsets[bucketId].SetBit(&bitsets[bucketId], bitIndex, 1)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Items returns all the items in the map (as key/value pairs) in insertion order.
|
||||||
|
func (ht *hashtable) items() []Tuple {
|
||||||
|
items := make([]Tuple, 0, ht.len)
|
||||||
|
array := make([]Value, ht.len*2) // allocate a single backing array
|
||||||
|
for e := ht.head; e != nil; e = e.next {
|
||||||
|
pair := Tuple(array[:2:2])
|
||||||
|
array = array[2:]
|
||||||
|
pair[0] = e.key
|
||||||
|
pair[1] = e.value
|
||||||
|
items = append(items, pair)
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) first() (Value, bool) {
|
||||||
|
if ht.head != nil {
|
||||||
|
return ht.head.key, true
|
||||||
|
}
|
||||||
|
return None, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) keys() []Value {
|
||||||
|
keys := make([]Value, 0, ht.len)
|
||||||
|
for e := ht.head; e != nil; e = e.next {
|
||||||
|
keys = append(keys, e.key)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) delete(k Value) (v Value, found bool, err error) {
|
||||||
|
if err := ht.checkMutable("delete from"); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
if ht.table == nil {
|
||||||
|
return None, false, nil // empty
|
||||||
|
}
|
||||||
|
h, err := k.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err // unhashable
|
||||||
|
}
|
||||||
|
if h == 0 {
|
||||||
|
h = 1 // zero is reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspect each bucket in the bucket list.
|
||||||
|
for p := &ht.table[h&(uint32(len(ht.table)-1))]; p != nil; p = p.next {
|
||||||
|
for i := range p.entries {
|
||||||
|
e := &p.entries[i]
|
||||||
|
if e.hash == h {
|
||||||
|
if eq, err := Equal(k, e.key); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
} else if eq {
|
||||||
|
// Remove e from doubly-linked list.
|
||||||
|
*e.prevLink = e.next
|
||||||
|
if e.next == nil {
|
||||||
|
ht.tailLink = e.prevLink // deletion of last entry
|
||||||
|
} else {
|
||||||
|
e.next.prevLink = e.prevLink
|
||||||
|
}
|
||||||
|
|
||||||
|
v := e.value
|
||||||
|
*e = entry{}
|
||||||
|
ht.len--
|
||||||
|
return v, true, nil // found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): opt: remove completely empty bucket from bucket list.
|
||||||
|
|
||||||
|
return None, false, nil // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkMutable reports an error if the hash table should not be mutated.
|
||||||
|
// verb+" dict" should describe the operation.
|
||||||
|
func (ht *hashtable) checkMutable(verb string) error {
|
||||||
|
if ht.frozen {
|
||||||
|
return fmt.Errorf("cannot %s frozen hash table", verb)
|
||||||
|
}
|
||||||
|
if ht.itercount > 0 {
|
||||||
|
return fmt.Errorf("cannot %s hash table during iteration", verb)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) clear() error {
|
||||||
|
if err := ht.checkMutable("clear"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ht.table != nil {
|
||||||
|
for i := range ht.table {
|
||||||
|
ht.table[i] = bucket{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ht.head = nil
|
||||||
|
ht.tailLink = &ht.head
|
||||||
|
ht.len = 0
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) addAll(other *hashtable) error {
|
||||||
|
for e := other.head; e != nil; e = e.next {
|
||||||
|
if err := ht.insert(e.key, e.value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump is provided as an aid to debugging.
|
||||||
|
func (ht *hashtable) dump() {
|
||||||
|
fmt.Printf("hashtable %p len=%d head=%p tailLink=%p",
|
||||||
|
ht, ht.len, ht.head, ht.tailLink)
|
||||||
|
if ht.tailLink != nil {
|
||||||
|
fmt.Printf(" *tailLink=%p", *ht.tailLink)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
for j := range ht.table {
|
||||||
|
fmt.Printf("bucket chain %d\n", j)
|
||||||
|
for p := &ht.table[j]; p != nil; p = p.next {
|
||||||
|
fmt.Printf("bucket %p\n", p)
|
||||||
|
for i := range p.entries {
|
||||||
|
e := &p.entries[i]
|
||||||
|
fmt.Printf("\tentry %d @ %p hash=%d key=%v value=%v\n",
|
||||||
|
i, e, e.hash, e.key, e.value)
|
||||||
|
fmt.Printf("\t\tnext=%p &next=%p prev=%p",
|
||||||
|
e.next, &e.next, e.prevLink)
|
||||||
|
if e.prevLink != nil {
|
||||||
|
fmt.Printf(" *prev=%p", *e.prevLink)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *hashtable) iterate() *keyIterator {
|
||||||
|
if !ht.frozen {
|
||||||
|
ht.itercount++
|
||||||
|
}
|
||||||
|
return &keyIterator{ht: ht, e: ht.head}
|
||||||
|
}
|
||||||
|
|
||||||
|
type keyIterator struct {
|
||||||
|
ht *hashtable
|
||||||
|
e *entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *keyIterator) Next(k *Value) bool {
|
||||||
|
if it.e != nil {
|
||||||
|
*k = it.e.key
|
||||||
|
it.e = it.e.next
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *keyIterator) Done() {
|
||||||
|
if !it.ht.frozen {
|
||||||
|
it.ht.itercount--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// entries is a go1.23 iterator over the entries of the hash table.
|
||||||
|
func (ht *hashtable) entries(yield func(k, v Value) bool) {
|
||||||
|
if !ht.frozen {
|
||||||
|
ht.itercount++
|
||||||
|
defer func() { ht.itercount-- }()
|
||||||
|
}
|
||||||
|
for e := ht.head; e != nil && yield(e.key, e.value); e = e.next {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var seed = maphash.MakeSeed()
|
||||||
|
|
||||||
|
// hashString computes the hash of s.
|
||||||
|
func hashString(s string) uint32 {
|
||||||
|
if len(s) >= 12 {
|
||||||
|
// Call the Go runtime's optimized hash implementation,
|
||||||
|
// which uses the AES instructions on amd64 and arm64 machines.
|
||||||
|
h := maphash.String(seed, s)
|
||||||
|
return uint32(h>>32) | uint32(h)
|
||||||
|
}
|
||||||
|
return softHashString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// softHashString computes the 32-bit FNV-1a hash of s in software.
|
||||||
|
func softHashString(s string) uint32 {
|
||||||
|
var h uint32 = 2166136261
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
h ^= uint32(s[i])
|
||||||
|
h *= 16777619
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
459
vendor/go.starlark.net/starlark/int.go
generated
vendored
Normal file
459
vendor/go.starlark.net/starlark/int.go
generated
vendored
Normal file
|
|
@ -0,0 +1,459 @@
|
||||||
|
// Copyright 2017 The Bazel 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 starlark
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Int is the type of a Starlark int.
|
||||||
|
//
|
||||||
|
// The zero value is not a legal value; use MakeInt(0).
|
||||||
|
type Int struct{ impl intImpl }
|
||||||
|
|
||||||
|
// --- high-level accessors ---
|
||||||
|
|
||||||
|
// MakeInt returns a Starlark int for the specified signed integer.
|
||||||
|
func MakeInt(x int) Int { return MakeInt64(int64(x)) }
|
||||||
|
|
||||||
|
// MakeInt64 returns a Starlark int for the specified int64.
|
||||||
|
func MakeInt64(x int64) Int {
|
||||||
|
if math.MinInt32 <= x && x <= math.MaxInt32 {
|
||||||
|
return makeSmallInt(x)
|
||||||
|
}
|
||||||
|
return makeBigInt(big.NewInt(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeUint returns a Starlark int for the specified unsigned integer.
|
||||||
|
func MakeUint(x uint) Int { return MakeUint64(uint64(x)) }
|
||||||
|
|
||||||
|
// MakeUint64 returns a Starlark int for the specified uint64.
|
||||||
|
func MakeUint64(x uint64) Int {
|
||||||
|
if x <= math.MaxInt32 {
|
||||||
|
return makeSmallInt(int64(x))
|
||||||
|
}
|
||||||
|
return makeBigInt(new(big.Int).SetUint64(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeBigInt returns a Starlark int for the specified big.Int.
|
||||||
|
// The new Int value will contain a copy of x. The caller is safe to modify x.
|
||||||
|
func MakeBigInt(x *big.Int) Int {
|
||||||
|
if isSmall(x) {
|
||||||
|
return makeSmallInt(x.Int64())
|
||||||
|
}
|
||||||
|
z := new(big.Int).Set(x)
|
||||||
|
return makeBigInt(z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSmall(x *big.Int) bool {
|
||||||
|
n := x.BitLen()
|
||||||
|
return n < 32 || n == 32 && x.Int64() == math.MinInt32
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
zero, one = makeSmallInt(0), makeSmallInt(1)
|
||||||
|
oneBig = big.NewInt(1)
|
||||||
|
|
||||||
|
_ HasUnary = Int{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Unary implements the operations +int, -int, and ~int.
|
||||||
|
func (i Int) Unary(op syntax.Token) (Value, error) {
|
||||||
|
switch op {
|
||||||
|
case syntax.MINUS:
|
||||||
|
return zero.Sub(i), nil
|
||||||
|
case syntax.PLUS:
|
||||||
|
return i, nil
|
||||||
|
case syntax.TILDE:
|
||||||
|
return i.Not(), nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns the value as an int64.
|
||||||
|
// If it is not exactly representable the result is undefined and ok is false.
|
||||||
|
func (i Int) Int64() (_ int64, ok bool) {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
x, acc := bigintToInt64(iBig)
|
||||||
|
if acc != big.Exact {
|
||||||
|
return // inexact
|
||||||
|
}
|
||||||
|
return x, true
|
||||||
|
}
|
||||||
|
return iSmall, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// BigInt returns a new big.Int with the same value as the Int.
|
||||||
|
func (i Int) BigInt() *big.Int {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
return new(big.Int).Set(iBig)
|
||||||
|
}
|
||||||
|
return big.NewInt(iSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bigInt returns the value as a big.Int.
|
||||||
|
// It differs from BigInt in that this method returns the actual
|
||||||
|
// reference and any modification will change the state of i.
|
||||||
|
func (i Int) bigInt() *big.Int {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
return iBig
|
||||||
|
}
|
||||||
|
return big.NewInt(iSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns the value as a uint64.
|
||||||
|
// If it is not exactly representable the result is undefined and ok is false.
|
||||||
|
func (i Int) Uint64() (_ uint64, ok bool) {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
x, acc := bigintToUint64(iBig)
|
||||||
|
if acc != big.Exact {
|
||||||
|
return // inexact
|
||||||
|
}
|
||||||
|
return x, true
|
||||||
|
}
|
||||||
|
if iSmall < 0 {
|
||||||
|
return // inexact
|
||||||
|
}
|
||||||
|
return uint64(iSmall), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// The math/big API should provide this function.
|
||||||
|
func bigintToInt64(i *big.Int) (int64, big.Accuracy) {
|
||||||
|
sign := i.Sign()
|
||||||
|
if sign > 0 {
|
||||||
|
if i.Cmp(maxint64) > 0 {
|
||||||
|
return math.MaxInt64, big.Below
|
||||||
|
}
|
||||||
|
} else if sign < 0 {
|
||||||
|
if i.Cmp(minint64) < 0 {
|
||||||
|
return math.MinInt64, big.Above
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i.Int64(), big.Exact
|
||||||
|
}
|
||||||
|
|
||||||
|
// The math/big API should provide this function.
|
||||||
|
func bigintToUint64(i *big.Int) (uint64, big.Accuracy) {
|
||||||
|
sign := i.Sign()
|
||||||
|
if sign > 0 {
|
||||||
|
if i.BitLen() > 64 {
|
||||||
|
return math.MaxUint64, big.Below
|
||||||
|
}
|
||||||
|
} else if sign < 0 {
|
||||||
|
return 0, big.Above
|
||||||
|
}
|
||||||
|
return i.Uint64(), big.Exact
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
minint64 = new(big.Int).SetInt64(math.MinInt64)
|
||||||
|
maxint64 = new(big.Int).SetInt64(math.MaxInt64)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (i Int) Format(s fmt.State, ch rune) {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
iBig.Format(s, ch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
big.NewInt(iSmall).Format(s, ch)
|
||||||
|
}
|
||||||
|
func (i Int) String() string {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
return iBig.Text(10)
|
||||||
|
}
|
||||||
|
return strconv.FormatInt(iSmall, 10)
|
||||||
|
}
|
||||||
|
func (i Int) Type() string { return "int" }
|
||||||
|
func (i Int) Freeze() {} // immutable
|
||||||
|
func (i Int) Truth() Bool { return i.Sign() != 0 }
|
||||||
|
func (i Int) Hash() (uint32, error) {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
var lo big.Word
|
||||||
|
if iBig != nil {
|
||||||
|
lo = iBig.Bits()[0]
|
||||||
|
} else {
|
||||||
|
lo = big.Word(iSmall)
|
||||||
|
}
|
||||||
|
return 12582917 * uint32(lo+3), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmp implements comparison of two Int values.
|
||||||
|
// Required by the TotallyOrdered interface.
|
||||||
|
func (i Int) Cmp(v Value, depth int) (int, error) {
|
||||||
|
j := v.(Int)
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
jSmall, jBig := j.get()
|
||||||
|
if iBig != nil || jBig != nil {
|
||||||
|
return i.bigInt().Cmp(j.bigInt()), nil
|
||||||
|
}
|
||||||
|
return signum64(iSmall - jSmall), nil // safe: int32 operands
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float returns the float value nearest i.
|
||||||
|
func (i Int) Float() Float {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
// Fast path for hardware int-to-float conversions.
|
||||||
|
if iBig.IsUint64() {
|
||||||
|
return Float(iBig.Uint64())
|
||||||
|
} else if iBig.IsInt64() {
|
||||||
|
return Float(iBig.Int64())
|
||||||
|
} else {
|
||||||
|
// Fast path for very big ints.
|
||||||
|
const maxFiniteLen = 1023 + 1 // max exponent value + implicit mantissa bit
|
||||||
|
if iBig.BitLen() > maxFiniteLen {
|
||||||
|
return Float(math.Inf(iBig.Sign()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, _ := new(big.Float).SetInt(iBig).Float64()
|
||||||
|
return Float(f)
|
||||||
|
}
|
||||||
|
return Float(iSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
// finiteFloat returns the finite float value nearest i,
|
||||||
|
// or an error if the magnitude is too large.
|
||||||
|
func (i Int) finiteFloat() (Float, error) {
|
||||||
|
f := i.Float()
|
||||||
|
if math.IsInf(float64(f), 0) {
|
||||||
|
return 0, fmt.Errorf("int too large to convert to float")
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Int) Sign() int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
if xBig != nil {
|
||||||
|
return xBig.Sign()
|
||||||
|
}
|
||||||
|
return signum64(xSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Int) Add(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).Add(x.bigInt(), y.bigInt()))
|
||||||
|
}
|
||||||
|
return MakeInt64(xSmall + ySmall)
|
||||||
|
}
|
||||||
|
func (x Int) Sub(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).Sub(x.bigInt(), y.bigInt()))
|
||||||
|
}
|
||||||
|
return MakeInt64(xSmall - ySmall)
|
||||||
|
}
|
||||||
|
func (x Int) Mul(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).Mul(x.bigInt(), y.bigInt()))
|
||||||
|
}
|
||||||
|
return MakeInt64(xSmall * ySmall)
|
||||||
|
}
|
||||||
|
func (x Int) Or(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).Or(x.bigInt(), y.bigInt()))
|
||||||
|
}
|
||||||
|
return makeSmallInt(xSmall | ySmall)
|
||||||
|
}
|
||||||
|
func (x Int) And(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).And(x.bigInt(), y.bigInt()))
|
||||||
|
}
|
||||||
|
return makeSmallInt(xSmall & ySmall)
|
||||||
|
}
|
||||||
|
func (x Int) Xor(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).Xor(x.bigInt(), y.bigInt()))
|
||||||
|
}
|
||||||
|
return makeSmallInt(xSmall ^ ySmall)
|
||||||
|
}
|
||||||
|
func (x Int) Not() Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
if xBig != nil {
|
||||||
|
return MakeBigInt(new(big.Int).Not(xBig))
|
||||||
|
}
|
||||||
|
return makeSmallInt(^xSmall)
|
||||||
|
}
|
||||||
|
func (x Int) Lsh(y uint) Int { return MakeBigInt(new(big.Int).Lsh(x.bigInt(), y)) }
|
||||||
|
func (x Int) Rsh(y uint) Int { return MakeBigInt(new(big.Int).Rsh(x.bigInt(), y)) }
|
||||||
|
|
||||||
|
// Precondition: y is nonzero.
|
||||||
|
func (x Int) Div(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
// http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
xb, yb := x.bigInt(), y.bigInt()
|
||||||
|
|
||||||
|
var quo, rem big.Int
|
||||||
|
quo.QuoRem(xb, yb, &rem)
|
||||||
|
if (xb.Sign() < 0) != (yb.Sign() < 0) && rem.Sign() != 0 {
|
||||||
|
quo.Sub(&quo, oneBig)
|
||||||
|
}
|
||||||
|
return MakeBigInt(&quo)
|
||||||
|
}
|
||||||
|
quo := xSmall / ySmall
|
||||||
|
rem := xSmall % ySmall
|
||||||
|
if (xSmall < 0) != (ySmall < 0) && rem != 0 {
|
||||||
|
quo -= 1
|
||||||
|
}
|
||||||
|
return MakeInt64(quo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precondition: y is nonzero.
|
||||||
|
func (x Int) Mod(y Int) Int {
|
||||||
|
xSmall, xBig := x.get()
|
||||||
|
ySmall, yBig := y.get()
|
||||||
|
if xBig != nil || yBig != nil {
|
||||||
|
xb, yb := x.bigInt(), y.bigInt()
|
||||||
|
|
||||||
|
var quo, rem big.Int
|
||||||
|
quo.QuoRem(xb, yb, &rem)
|
||||||
|
if (xb.Sign() < 0) != (yb.Sign() < 0) && rem.Sign() != 0 {
|
||||||
|
rem.Add(&rem, yb)
|
||||||
|
}
|
||||||
|
return MakeBigInt(&rem)
|
||||||
|
}
|
||||||
|
rem := xSmall % ySmall
|
||||||
|
if (xSmall < 0) != (ySmall < 0) && rem != 0 {
|
||||||
|
rem += ySmall
|
||||||
|
}
|
||||||
|
return makeSmallInt(rem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Int) rational() *big.Rat {
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
return new(big.Rat).SetInt(iBig)
|
||||||
|
}
|
||||||
|
return new(big.Rat).SetInt64(iSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt32 returns the value of x if is representable as an int32.
|
||||||
|
func AsInt32(x Value) (int, error) {
|
||||||
|
i, ok := x.(Int)
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("got %s, want int", x.Type())
|
||||||
|
}
|
||||||
|
iSmall, iBig := i.get()
|
||||||
|
if iBig != nil {
|
||||||
|
return 0, fmt.Errorf("%s out of range", i)
|
||||||
|
}
|
||||||
|
return int(iSmall), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsInt sets *ptr to the value of Starlark int x, if it is exactly representable,
|
||||||
|
// otherwise it returns an error.
|
||||||
|
// The type of ptr must be one of the pointer types *int, *int8, *int16, *int32, or *int64,
|
||||||
|
// or one of their unsigned counterparts including *uintptr.
|
||||||
|
func AsInt(x Value, ptr interface{}) error {
|
||||||
|
xint, ok := x.(Int)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want int", x.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
bits := reflect.TypeOf(ptr).Elem().Size() * 8
|
||||||
|
switch ptr.(type) {
|
||||||
|
case *int, *int8, *int16, *int32, *int64:
|
||||||
|
i, ok := xint.Int64()
|
||||||
|
if !ok || bits < 64 && !(-1<<(bits-1) <= i && i < 1<<(bits-1)) {
|
||||||
|
return fmt.Errorf("%s out of range (want value in signed %d-bit range)", xint, bits)
|
||||||
|
}
|
||||||
|
switch ptr := ptr.(type) {
|
||||||
|
case *int:
|
||||||
|
*ptr = int(i)
|
||||||
|
case *int8:
|
||||||
|
*ptr = int8(i)
|
||||||
|
case *int16:
|
||||||
|
*ptr = int16(i)
|
||||||
|
case *int32:
|
||||||
|
*ptr = int32(i)
|
||||||
|
case *int64:
|
||||||
|
*ptr = int64(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *uint, *uint8, *uint16, *uint32, *uint64, *uintptr:
|
||||||
|
i, ok := xint.Uint64()
|
||||||
|
if !ok || bits < 64 && i >= 1<<bits {
|
||||||
|
return fmt.Errorf("%s out of range (want value in unsigned %d-bit range)", xint, bits)
|
||||||
|
}
|
||||||
|
switch ptr := ptr.(type) {
|
||||||
|
case *uint:
|
||||||
|
*ptr = uint(i)
|
||||||
|
case *uint8:
|
||||||
|
*ptr = uint8(i)
|
||||||
|
case *uint16:
|
||||||
|
*ptr = uint16(i)
|
||||||
|
case *uint32:
|
||||||
|
*ptr = uint32(i)
|
||||||
|
case *uint64:
|
||||||
|
*ptr = uint64(i)
|
||||||
|
case *uintptr:
|
||||||
|
*ptr = uintptr(i)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid argument type: %T", ptr))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumberToInt converts a number x to an integer value.
|
||||||
|
// An int is returned unchanged, a float is truncated towards zero.
|
||||||
|
// NumberToInt reports an error for all other values.
|
||||||
|
func NumberToInt(x Value) (Int, error) {
|
||||||
|
switch x := x.(type) {
|
||||||
|
case Int:
|
||||||
|
return x, nil
|
||||||
|
case Float:
|
||||||
|
f := float64(x)
|
||||||
|
if math.IsInf(f, 0) {
|
||||||
|
return zero, fmt.Errorf("cannot convert float infinity to integer")
|
||||||
|
} else if math.IsNaN(f) {
|
||||||
|
return zero, fmt.Errorf("cannot convert float NaN to integer")
|
||||||
|
}
|
||||||
|
return finiteFloatToInt(x), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
return zero, fmt.Errorf("cannot convert %s to int", x.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// finiteFloatToInt converts f to an Int, truncating towards zero.
|
||||||
|
// f must be finite.
|
||||||
|
func finiteFloatToInt(f Float) Int {
|
||||||
|
// We avoid '<= MaxInt64' so that both constants are exactly representable as floats.
|
||||||
|
// See https://github.com/google/starlark-go/issues/375.
|
||||||
|
if math.MinInt64 <= f && f < math.MaxInt64+1 {
|
||||||
|
// small values
|
||||||
|
return MakeInt64(int64(f))
|
||||||
|
}
|
||||||
|
rat := f.rational()
|
||||||
|
if rat == nil {
|
||||||
|
panic(f) // non-finite
|
||||||
|
}
|
||||||
|
return MakeBigInt(new(big.Int).Div(rat.Num(), rat.Denom()))
|
||||||
|
}
|
||||||
33
vendor/go.starlark.net/starlark/int_generic.go
generated
vendored
Normal file
33
vendor/go.starlark.net/starlark/int_generic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
//go:build (!linux && !darwin && !dragonfly && !freebsd && !netbsd && !solaris) || (!amd64 && !arm64 && !mips64x && !ppc64 && !ppc64le && !loong64 && !s390x)
|
||||||
|
|
||||||
|
package starlark
|
||||||
|
|
||||||
|
// generic Int implementation as a union
|
||||||
|
|
||||||
|
import "math/big"
|
||||||
|
|
||||||
|
type intImpl struct {
|
||||||
|
// We use only the signed 32-bit range of small to ensure
|
||||||
|
// that small+small and small*small do not overflow.
|
||||||
|
small_ int64 // minint32 <= small <= maxint32
|
||||||
|
big_ *big.Int // big != nil <=> value is not representable as int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- low-level accessors ---
|
||||||
|
|
||||||
|
// get returns the small and big components of the Int.
|
||||||
|
// small is defined only if big is nil.
|
||||||
|
// small is sign-extended to 64 bits for ease of subsequent arithmetic.
|
||||||
|
func (i Int) get() (small int64, big *big.Int) {
|
||||||
|
return i.impl.small_, i.impl.big_
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precondition: math.MinInt32 <= x && x <= math.MaxInt32
|
||||||
|
func makeSmallInt(x int64) Int {
|
||||||
|
return Int{intImpl{small_: x}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precondition: x cannot be represented as int32.
|
||||||
|
func makeBigInt(x *big.Int) Int {
|
||||||
|
return Int{intImpl{big_: x}}
|
||||||
|
}
|
||||||
89
vendor/go.starlark.net/starlark/int_posix64.go
generated
vendored
Normal file
89
vendor/go.starlark.net/starlark/int_posix64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
//go:build (linux || darwin || dragonfly || freebsd || netbsd || solaris) && (amd64 || arm64 || mips64x || ppc64 || ppc64le || loong64 || s390x)
|
||||||
|
|
||||||
|
package starlark
|
||||||
|
|
||||||
|
// This file defines an optimized Int implementation for 64-bit machines
|
||||||
|
// running POSIX. It reserves a 4GB portion of the address space using
|
||||||
|
// mmap and represents int32 values as addresses within that range. This
|
||||||
|
// disambiguates int32 values from *big.Int pointers, letting all Int
|
||||||
|
// values be represented as an unsafe.Pointer, so that Int-to-Value
|
||||||
|
// interface conversion need not allocate.
|
||||||
|
|
||||||
|
// Although iOS (which, like macOS, appears as darwin/arm64) is
|
||||||
|
// POSIX-compliant, it limits each process to about 700MB of virtual
|
||||||
|
// address space, which defeats the optimization. Similarly,
|
||||||
|
// OpenBSD's default ulimit for virtual memory is a measly GB or so.
|
||||||
|
// On both those platforms the attempted optimization will fail and
|
||||||
|
// fall back to the slow implementation.
|
||||||
|
|
||||||
|
// An alternative approach to this optimization would be to embed the
|
||||||
|
// int32 values in pointers using odd values, which can be distinguished
|
||||||
|
// from (even) *big.Int pointers. However, the Go runtime does not allow
|
||||||
|
// user programs to manufacture pointers to arbitrary locations such as
|
||||||
|
// within the zero page, or non-span, non-mmap, non-stack locations,
|
||||||
|
// and it may panic if it encounters them; see Issue #382.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// intImpl represents a union of (int32, *big.Int) in a single pointer,
|
||||||
|
// so that Int-to-Value conversions need not allocate.
|
||||||
|
//
|
||||||
|
// The pointer is either a *big.Int, if the value is big, or a pointer into a
|
||||||
|
// reserved portion of the address space (smallints), if the value is small
|
||||||
|
// and the address space allocation succeeded.
|
||||||
|
//
|
||||||
|
// See int_generic.go for the basic representation concepts.
|
||||||
|
type intImpl unsafe.Pointer
|
||||||
|
|
||||||
|
// get returns the (small, big) arms of the union.
|
||||||
|
func (i Int) get() (int64, *big.Int) {
|
||||||
|
if smallints == 0 {
|
||||||
|
// optimization disabled
|
||||||
|
if x := (*big.Int)(i.impl); isSmall(x) {
|
||||||
|
return x.Int64(), nil
|
||||||
|
} else {
|
||||||
|
return 0, x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ptr := uintptr(i.impl); ptr >= smallints && ptr < smallints+1<<32 {
|
||||||
|
return math.MinInt32 + int64(ptr-smallints), nil
|
||||||
|
}
|
||||||
|
return 0, (*big.Int)(i.impl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precondition: math.MinInt32 <= x && x <= math.MaxInt32
|
||||||
|
func makeSmallInt(x int64) Int {
|
||||||
|
if smallints == 0 {
|
||||||
|
// optimization disabled
|
||||||
|
return Int{intImpl(big.NewInt(x))}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Int{intImpl(uintptr(x-math.MinInt32) + smallints)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precondition: x cannot be represented as int32.
|
||||||
|
func makeBigInt(x *big.Int) Int { return Int{intImpl(x)} }
|
||||||
|
|
||||||
|
// smallints is the base address of a 2^32 byte memory region.
|
||||||
|
// Pointers to addresses in this region represent int32 values.
|
||||||
|
// We assume smallints is not at the very top of the address space.
|
||||||
|
//
|
||||||
|
// Zero means the optimization is disabled and all Ints allocate a big.Int.
|
||||||
|
var smallints = reserveAddresses(1 << 32)
|
||||||
|
|
||||||
|
func reserveAddresses(len int) uintptr {
|
||||||
|
b, err := unix.Mmap(-1, 0, len, unix.PROT_READ, unix.MAP_PRIVATE|unix.MAP_ANON)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Starlark failed to allocate 4GB address space: %v. Integer performance may suffer.", err)
|
||||||
|
return 0 // optimization disabled
|
||||||
|
}
|
||||||
|
return uintptr(unsafe.Pointer(&b[0]))
|
||||||
|
}
|
||||||
714
vendor/go.starlark.net/starlark/interp.go
generated
vendored
Normal file
714
vendor/go.starlark.net/starlark/interp.go
generated
vendored
Normal file
|
|
@ -0,0 +1,714 @@
|
||||||
|
package starlark
|
||||||
|
|
||||||
|
// This file defines the bytecode interpreter.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sync/atomic"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"go.starlark.net/internal/compile"
|
||||||
|
"go.starlark.net/internal/spell"
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
const vmdebug = false // TODO(adonovan): use a bitfield of specific kinds of error.
|
||||||
|
|
||||||
|
// TODO(adonovan):
|
||||||
|
// - optimize position table.
|
||||||
|
// - opt: record MaxIterStack during compilation and preallocate the stack.
|
||||||
|
|
||||||
|
func (fn *Function) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error) {
|
||||||
|
// Postcondition: args is not mutated. This is stricter than required by Callable,
|
||||||
|
// but allows CALL to avoid a copy.
|
||||||
|
|
||||||
|
f := fn.funcode
|
||||||
|
if f.Prog.Recursion {
|
||||||
|
// prevent stack overflow
|
||||||
|
//
|
||||||
|
// Each CallInternal recursion (via Call) uses ~1.4KB,
|
||||||
|
// but the stack limit is on the order of 1GB, so a
|
||||||
|
// maximum of about 700K recursive calls is possible.
|
||||||
|
// Limit it to much less here.
|
||||||
|
if len(thread.stack) > 100_000 {
|
||||||
|
return nil, fmt.Errorf("Starlark stack overflow")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// detect recursion
|
||||||
|
for _, fr := range thread.stack[:len(thread.stack)-1] {
|
||||||
|
// We look for the same function code,
|
||||||
|
// not function value, otherwise the user could
|
||||||
|
// defeat the check by writing the Y combinator.
|
||||||
|
if frfn, ok := fr.Callable().(*Function); ok && frfn.funcode == f {
|
||||||
|
return nil, fmt.Errorf("function %s called recursively", fn.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fr := thread.frameAt(0)
|
||||||
|
|
||||||
|
// Allocate space for stack and locals.
|
||||||
|
// Logically these do not escape from this frame
|
||||||
|
// (See https://github.com/golang/go/issues/20533.)
|
||||||
|
//
|
||||||
|
// This heap allocation looks expensive, but I was unable to get
|
||||||
|
// more than 1% real time improvement in a large alloc-heavy
|
||||||
|
// benchmark (in which this alloc was 8% of alloc-bytes)
|
||||||
|
// by allocating space for 8 Values in each frame, or
|
||||||
|
// by allocating stack by slicing an array held by the Thread
|
||||||
|
// that is expanded in chunks of min(k, nspace), for k=256 or 1024.
|
||||||
|
nlocals := len(f.Locals)
|
||||||
|
nspace := nlocals + f.MaxStack
|
||||||
|
space := make([]Value, nspace)
|
||||||
|
locals := space[:nlocals:nlocals] // local variables, starting with parameters
|
||||||
|
stack := space[nlocals:] // operand stack
|
||||||
|
|
||||||
|
// Digest arguments and set parameters.
|
||||||
|
err := setArgs(locals, fn, args, kwargs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, thread.evalError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.locals = locals
|
||||||
|
|
||||||
|
if vmdebug {
|
||||||
|
fmt.Printf("Entering %s @ %s\n", f.Name, f.Position(0))
|
||||||
|
fmt.Printf("%d stack, %d locals\n", len(stack), len(locals))
|
||||||
|
defer fmt.Println("Leaving ", f.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spill indicated locals to cells.
|
||||||
|
// Each cell is a separate alloc to avoid spurious liveness.
|
||||||
|
for _, index := range f.Cells {
|
||||||
|
locals[index] = &cell{locals[index]}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): add static check that beneath this point
|
||||||
|
// - there is exactly one return statement
|
||||||
|
// - there is no redefinition of 'err'.
|
||||||
|
|
||||||
|
var iterstack []Iterator // stack of active iterators
|
||||||
|
|
||||||
|
// Use defer so that application panics can pass through
|
||||||
|
// interpreter without leaving thread in a bad state.
|
||||||
|
defer func() {
|
||||||
|
// ITERPOP the rest of the iterator stack.
|
||||||
|
for _, iter := range iterstack {
|
||||||
|
iter.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.locals = nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
sp := 0
|
||||||
|
var pc uint32
|
||||||
|
var result Value
|
||||||
|
code := f.Code
|
||||||
|
loop:
|
||||||
|
for {
|
||||||
|
thread.Steps++
|
||||||
|
if thread.Steps >= thread.maxSteps {
|
||||||
|
if thread.OnMaxSteps != nil {
|
||||||
|
thread.OnMaxSteps(thread)
|
||||||
|
} else {
|
||||||
|
thread.Cancel("too many steps")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if reason := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason))); reason != nil {
|
||||||
|
err = fmt.Errorf("Starlark computation cancelled: %s", *(*string)(reason))
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.pc = pc
|
||||||
|
|
||||||
|
op := compile.Opcode(code[pc])
|
||||||
|
pc++
|
||||||
|
var arg uint32
|
||||||
|
if op >= compile.OpcodeArgMin {
|
||||||
|
// TODO(adonovan): opt: profile this.
|
||||||
|
// Perhaps compiling big endian would be less work to decode?
|
||||||
|
for s := uint(0); ; s += 7 {
|
||||||
|
b := code[pc]
|
||||||
|
pc++
|
||||||
|
arg |= uint32(b&0x7f) << s
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if vmdebug {
|
||||||
|
fmt.Fprintln(os.Stderr, stack[:sp]) // very verbose!
|
||||||
|
compile.PrintOp(f, fr.pc, op, arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case compile.NOP:
|
||||||
|
// nop
|
||||||
|
|
||||||
|
case compile.DUP:
|
||||||
|
stack[sp] = stack[sp-1]
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.DUP2:
|
||||||
|
stack[sp] = stack[sp-2]
|
||||||
|
stack[sp+1] = stack[sp-1]
|
||||||
|
sp += 2
|
||||||
|
|
||||||
|
case compile.POP:
|
||||||
|
sp--
|
||||||
|
|
||||||
|
case compile.EXCH:
|
||||||
|
stack[sp-2], stack[sp-1] = stack[sp-1], stack[sp-2]
|
||||||
|
|
||||||
|
case compile.EQL, compile.NEQ, compile.GT, compile.LT, compile.LE, compile.GE:
|
||||||
|
op := syntax.Token(op-compile.EQL) + syntax.EQL
|
||||||
|
y := stack[sp-1]
|
||||||
|
x := stack[sp-2]
|
||||||
|
sp -= 2
|
||||||
|
ok, err2 := Compare(op, x, y)
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = Bool(ok)
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.PLUS,
|
||||||
|
compile.MINUS,
|
||||||
|
compile.STAR,
|
||||||
|
compile.SLASH,
|
||||||
|
compile.SLASHSLASH,
|
||||||
|
compile.PERCENT,
|
||||||
|
compile.AMP,
|
||||||
|
compile.PIPE,
|
||||||
|
compile.CIRCUMFLEX,
|
||||||
|
compile.LTLT,
|
||||||
|
compile.GTGT,
|
||||||
|
compile.IN:
|
||||||
|
binop := syntax.Token(op-compile.PLUS) + syntax.PLUS
|
||||||
|
if op == compile.IN {
|
||||||
|
binop = syntax.IN // IN token is out of order
|
||||||
|
}
|
||||||
|
y := stack[sp-1]
|
||||||
|
x := stack[sp-2]
|
||||||
|
sp -= 2
|
||||||
|
z, err2 := Binary(binop, x, y)
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = z
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.UPLUS, compile.UMINUS, compile.TILDE:
|
||||||
|
var unop syntax.Token
|
||||||
|
if op == compile.TILDE {
|
||||||
|
unop = syntax.TILDE
|
||||||
|
} else {
|
||||||
|
unop = syntax.Token(op-compile.UPLUS) + syntax.PLUS
|
||||||
|
}
|
||||||
|
x := stack[sp-1]
|
||||||
|
y, err2 := Unary(unop, x)
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp-1] = y
|
||||||
|
|
||||||
|
case compile.INPLACE_ADD:
|
||||||
|
y := stack[sp-1]
|
||||||
|
x := stack[sp-2]
|
||||||
|
sp -= 2
|
||||||
|
|
||||||
|
// It's possible that y is not Iterable but
|
||||||
|
// nonetheless defines x+y, in which case we
|
||||||
|
// should fall back to the general case.
|
||||||
|
var z Value
|
||||||
|
if xlist, ok := x.(*List); ok {
|
||||||
|
if yiter, ok := y.(Iterable); ok {
|
||||||
|
if err = xlist.checkMutable("apply += to"); err != nil {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
listExtend(xlist, yiter)
|
||||||
|
z = xlist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if z == nil {
|
||||||
|
z, err = Binary(syntax.PLUS, x, y)
|
||||||
|
if err != nil {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack[sp] = z
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.INPLACE_PIPE:
|
||||||
|
y := stack[sp-1]
|
||||||
|
x := stack[sp-2]
|
||||||
|
sp -= 2
|
||||||
|
|
||||||
|
// It's possible that y is not Dict but
|
||||||
|
// nonetheless defines x|y, in which case we
|
||||||
|
// should fall back to the general case.
|
||||||
|
var z Value
|
||||||
|
if xdict, ok := x.(*Dict); ok {
|
||||||
|
if ydict, ok := y.(*Dict); ok {
|
||||||
|
if err = xdict.ht.checkMutable("apply |= to"); err != nil {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
xdict.ht.addAll(&ydict.ht) // can't fail
|
||||||
|
z = xdict
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if z == nil {
|
||||||
|
z, err = Binary(syntax.PIPE, x, y)
|
||||||
|
if err != nil {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack[sp] = z
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.NONE:
|
||||||
|
stack[sp] = None
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.TRUE:
|
||||||
|
stack[sp] = True
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.FALSE:
|
||||||
|
stack[sp] = False
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.MANDATORY:
|
||||||
|
stack[sp] = mandatory{}
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.JMP:
|
||||||
|
pc = arg
|
||||||
|
|
||||||
|
case compile.CALL, compile.CALL_VAR, compile.CALL_KW, compile.CALL_VAR_KW:
|
||||||
|
var kwargs Value
|
||||||
|
if op == compile.CALL_KW || op == compile.CALL_VAR_KW {
|
||||||
|
kwargs = stack[sp-1]
|
||||||
|
sp--
|
||||||
|
}
|
||||||
|
|
||||||
|
var args Value
|
||||||
|
if op == compile.CALL_VAR || op == compile.CALL_VAR_KW {
|
||||||
|
args = stack[sp-1]
|
||||||
|
sp--
|
||||||
|
}
|
||||||
|
|
||||||
|
// named args (pairs)
|
||||||
|
var kvpairs []Tuple
|
||||||
|
if nkvpairs := int(arg & 0xff); nkvpairs > 0 {
|
||||||
|
kvpairs = make([]Tuple, 0, nkvpairs)
|
||||||
|
kvpairsAlloc := make(Tuple, 2*nkvpairs) // allocate a single backing array
|
||||||
|
sp -= 2 * nkvpairs
|
||||||
|
for i := 0; i < nkvpairs; i++ {
|
||||||
|
pair := kvpairsAlloc[:2:2]
|
||||||
|
kvpairsAlloc = kvpairsAlloc[2:]
|
||||||
|
pair[0] = stack[sp+2*i] // name
|
||||||
|
pair[1] = stack[sp+2*i+1] // value
|
||||||
|
kvpairs = append(kvpairs, pair)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if kwargs != nil {
|
||||||
|
// Add key/value items from **kwargs dictionary.
|
||||||
|
dict, ok := kwargs.(IterableMapping)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("argument after ** must be a mapping, not %s", kwargs.Type())
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
items := dict.Items()
|
||||||
|
for _, item := range items {
|
||||||
|
if _, ok := item[0].(String); !ok {
|
||||||
|
err = fmt.Errorf("keywords must be strings, not %s", item[0].Type())
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(kvpairs) == 0 {
|
||||||
|
kvpairs = items
|
||||||
|
} else {
|
||||||
|
kvpairs = append(kvpairs, items...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// positional args
|
||||||
|
var positional Tuple
|
||||||
|
if npos := int(arg >> 8); npos > 0 {
|
||||||
|
positional = stack[sp-npos : sp]
|
||||||
|
sp -= npos
|
||||||
|
|
||||||
|
// Copy positional arguments into a new array,
|
||||||
|
// unless the callee is another Starlark function,
|
||||||
|
// in which case it can be trusted not to mutate them.
|
||||||
|
if _, ok := stack[sp-1].(*Function); !ok || args != nil {
|
||||||
|
positional = append(Tuple(nil), positional...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if args != nil {
|
||||||
|
// Add elements from *args sequence.
|
||||||
|
iter := Iterate(args)
|
||||||
|
if iter == nil {
|
||||||
|
err = fmt.Errorf("argument after * must be iterable, not %s", args.Type())
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
var elem Value
|
||||||
|
for iter.Next(&elem) {
|
||||||
|
positional = append(positional, elem)
|
||||||
|
}
|
||||||
|
iter.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
function := stack[sp-1]
|
||||||
|
|
||||||
|
if vmdebug {
|
||||||
|
fmt.Printf("VM call %s args=%s kwargs=%s @%s\n",
|
||||||
|
function, positional, kvpairs, f.Position(fr.pc))
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.endProfSpan()
|
||||||
|
z, err2 := Call(thread, function, positional, kvpairs)
|
||||||
|
thread.beginProfSpan()
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
if vmdebug {
|
||||||
|
fmt.Printf("Resuming %s @ %s\n", f.Name, f.Position(0))
|
||||||
|
}
|
||||||
|
stack[sp-1] = z
|
||||||
|
|
||||||
|
case compile.ITERPUSH:
|
||||||
|
x := stack[sp-1]
|
||||||
|
sp--
|
||||||
|
iter := Iterate(x)
|
||||||
|
if iter == nil {
|
||||||
|
err = fmt.Errorf("%s value is not iterable", x.Type())
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
iterstack = append(iterstack, iter)
|
||||||
|
|
||||||
|
case compile.ITERJMP:
|
||||||
|
iter := iterstack[len(iterstack)-1]
|
||||||
|
if iter.Next(&stack[sp]) {
|
||||||
|
sp++
|
||||||
|
} else {
|
||||||
|
pc = arg
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.ITERPOP:
|
||||||
|
n := len(iterstack) - 1
|
||||||
|
iterstack[n].Done()
|
||||||
|
iterstack = iterstack[:n]
|
||||||
|
|
||||||
|
case compile.NOT:
|
||||||
|
stack[sp-1] = !stack[sp-1].Truth()
|
||||||
|
|
||||||
|
case compile.RETURN:
|
||||||
|
result = stack[sp-1]
|
||||||
|
break loop
|
||||||
|
|
||||||
|
case compile.SETINDEX:
|
||||||
|
z := stack[sp-1]
|
||||||
|
y := stack[sp-2]
|
||||||
|
x := stack[sp-3]
|
||||||
|
sp -= 3
|
||||||
|
err = setIndex(x, y, z)
|
||||||
|
if err != nil {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.INDEX:
|
||||||
|
y := stack[sp-1]
|
||||||
|
x := stack[sp-2]
|
||||||
|
sp -= 2
|
||||||
|
z, err2 := getIndex(x, y)
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = z
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.ATTR:
|
||||||
|
x := stack[sp-1]
|
||||||
|
name := f.Prog.Names[arg]
|
||||||
|
y, err2 := getAttr(x, name)
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp-1] = y
|
||||||
|
|
||||||
|
case compile.SETFIELD:
|
||||||
|
y := stack[sp-1]
|
||||||
|
x := stack[sp-2]
|
||||||
|
sp -= 2
|
||||||
|
name := f.Prog.Names[arg]
|
||||||
|
if err2 := setField(x, name, y); err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.MAKEDICT:
|
||||||
|
stack[sp] = new(Dict)
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.SETDICT, compile.SETDICTUNIQ:
|
||||||
|
dict := stack[sp-3].(*Dict)
|
||||||
|
k := stack[sp-2]
|
||||||
|
v := stack[sp-1]
|
||||||
|
sp -= 3
|
||||||
|
oldlen := dict.Len()
|
||||||
|
if err2 := dict.SetKey(k, v); err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
if op == compile.SETDICTUNIQ && dict.Len() == oldlen {
|
||||||
|
err = fmt.Errorf("duplicate key: %v", k)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.APPEND:
|
||||||
|
elem := stack[sp-1]
|
||||||
|
list := stack[sp-2].(*List)
|
||||||
|
sp -= 2
|
||||||
|
list.elems = append(list.elems, elem)
|
||||||
|
|
||||||
|
case compile.SLICE:
|
||||||
|
x := stack[sp-4]
|
||||||
|
lo := stack[sp-3]
|
||||||
|
hi := stack[sp-2]
|
||||||
|
step := stack[sp-1]
|
||||||
|
sp -= 4
|
||||||
|
res, err2 := slice(x, lo, hi, step)
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = res
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.UNPACK:
|
||||||
|
n := int(arg)
|
||||||
|
iterable := stack[sp-1]
|
||||||
|
sp--
|
||||||
|
iter := Iterate(iterable)
|
||||||
|
if iter == nil {
|
||||||
|
err = fmt.Errorf("got %s in sequence assignment", iterable.Type())
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
sp += n
|
||||||
|
for i < n && iter.Next(&stack[sp-1-i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
var dummy Value
|
||||||
|
if iter.Next(&dummy) {
|
||||||
|
// NB: Len may return -1 here in obscure cases.
|
||||||
|
err = fmt.Errorf("too many values to unpack (got %d, want %d)", Len(iterable), n)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
iter.Done()
|
||||||
|
if i < n {
|
||||||
|
err = fmt.Errorf("too few values to unpack (got %d, want %d)", i, n)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.CJMP:
|
||||||
|
if stack[sp-1].Truth() {
|
||||||
|
pc = arg
|
||||||
|
}
|
||||||
|
sp--
|
||||||
|
|
||||||
|
case compile.CONSTANT:
|
||||||
|
stack[sp] = fn.module.constants[arg]
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.MAKETUPLE:
|
||||||
|
n := int(arg)
|
||||||
|
tuple := make(Tuple, n)
|
||||||
|
sp -= n
|
||||||
|
copy(tuple, stack[sp:])
|
||||||
|
stack[sp] = tuple
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.MAKELIST:
|
||||||
|
n := int(arg)
|
||||||
|
elems := make([]Value, n)
|
||||||
|
sp -= n
|
||||||
|
copy(elems, stack[sp:])
|
||||||
|
stack[sp] = NewList(elems)
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.MAKEFUNC:
|
||||||
|
funcode := f.Prog.Functions[arg]
|
||||||
|
tuple := stack[sp-1].(Tuple)
|
||||||
|
n := len(tuple) - len(funcode.FreeVars)
|
||||||
|
defaults := tuple[:n:n]
|
||||||
|
freevars := tuple[n:]
|
||||||
|
stack[sp-1] = &Function{
|
||||||
|
funcode: funcode,
|
||||||
|
module: fn.module,
|
||||||
|
defaults: defaults,
|
||||||
|
freevars: freevars,
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.LOAD:
|
||||||
|
n := int(arg)
|
||||||
|
module := string(stack[sp-1].(String))
|
||||||
|
sp--
|
||||||
|
|
||||||
|
if thread.Load == nil {
|
||||||
|
err = fmt.Errorf("load not implemented by this application")
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.endProfSpan()
|
||||||
|
dict, err2 := thread.Load(thread, module)
|
||||||
|
thread.beginProfSpan()
|
||||||
|
if err2 != nil {
|
||||||
|
err = wrappedError{
|
||||||
|
msg: fmt.Sprintf("cannot load %s: %v", module, err2),
|
||||||
|
cause: err2,
|
||||||
|
}
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
from := string(stack[sp-1-i].(String))
|
||||||
|
v, ok := dict[from]
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("load: name %s not found in module %s", from, module)
|
||||||
|
if n := spell.Nearest(from, dict.Keys()); n != "" {
|
||||||
|
err = fmt.Errorf("%s (did you mean %s?)", err, n)
|
||||||
|
}
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp-1-i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
case compile.SETLOCAL:
|
||||||
|
locals[arg] = stack[sp-1]
|
||||||
|
sp--
|
||||||
|
|
||||||
|
case compile.SETLOCALCELL:
|
||||||
|
locals[arg].(*cell).v = stack[sp-1]
|
||||||
|
sp--
|
||||||
|
|
||||||
|
case compile.SETGLOBAL:
|
||||||
|
fn.module.globals[arg] = stack[sp-1]
|
||||||
|
sp--
|
||||||
|
|
||||||
|
case compile.LOCAL:
|
||||||
|
x := locals[arg]
|
||||||
|
if x == nil {
|
||||||
|
err = fmt.Errorf("local variable %s referenced before assignment", f.Locals[arg].Name)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = x
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.FREE:
|
||||||
|
stack[sp] = fn.freevars[arg]
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.LOCALCELL:
|
||||||
|
v := locals[arg].(*cell).v
|
||||||
|
if v == nil {
|
||||||
|
err = fmt.Errorf("local variable %s referenced before assignment", f.Locals[arg].Name)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = v
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.FREECELL:
|
||||||
|
v := fn.freevars[arg].(*cell).v
|
||||||
|
if v == nil {
|
||||||
|
err = fmt.Errorf("local variable %s referenced before assignment", f.FreeVars[arg].Name)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = v
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.GLOBAL:
|
||||||
|
x := fn.module.globals[arg]
|
||||||
|
if x == nil {
|
||||||
|
err = fmt.Errorf("global variable %s referenced before assignment", f.Prog.Globals[arg].Name)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = x
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.PREDECLARED:
|
||||||
|
name := f.Prog.Names[arg]
|
||||||
|
x := fn.module.predeclared[name]
|
||||||
|
if x == nil {
|
||||||
|
err = fmt.Errorf("internal error: predeclared variable %s is uninitialized", name)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
stack[sp] = x
|
||||||
|
sp++
|
||||||
|
|
||||||
|
case compile.UNIVERSAL:
|
||||||
|
stack[sp] = Universe[f.Prog.Names[arg]]
|
||||||
|
sp++
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("unimplemented: %s", op)
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// (deferred cleanup runs here)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type wrappedError struct {
|
||||||
|
msg string
|
||||||
|
cause error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e wrappedError) Error() string {
|
||||||
|
return e.msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the xerrors.Wrapper interface
|
||||||
|
// https://godoc.org/golang.org/x/xerrors#Wrapper
|
||||||
|
func (e wrappedError) Unwrap() error {
|
||||||
|
return e.cause
|
||||||
|
}
|
||||||
|
|
||||||
|
// mandatory is a sentinel value used in a function's defaults tuple
|
||||||
|
// to indicate that a (keyword-only) parameter is mandatory.
|
||||||
|
type mandatory struct{}
|
||||||
|
|
||||||
|
func (mandatory) String() string { return "mandatory" }
|
||||||
|
func (mandatory) Type() string { return "mandatory" }
|
||||||
|
func (mandatory) Freeze() {} // immutable
|
||||||
|
func (mandatory) Truth() Bool { return False }
|
||||||
|
func (mandatory) Hash() (uint32, error) { return 0, nil }
|
||||||
|
|
||||||
|
// A cell is a box containing a Value.
|
||||||
|
// Local variables marked as cells hold their value indirectly
|
||||||
|
// so that they may be shared by outer and inner nested functions.
|
||||||
|
// Cells are always accessed using indirect {FREE,LOCAL,SETLOCAL}CELL instructions.
|
||||||
|
// The FreeVars tuple contains only cells.
|
||||||
|
// The FREE instruction always yields a cell.
|
||||||
|
type cell struct{ v Value }
|
||||||
|
|
||||||
|
func (c *cell) String() string { return "cell" }
|
||||||
|
func (c *cell) Type() string { return "cell" }
|
||||||
|
func (c *cell) Freeze() {
|
||||||
|
if c.v != nil {
|
||||||
|
c.v.Freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *cell) Truth() Bool { panic("unreachable") }
|
||||||
|
func (c *cell) Hash() (uint32, error) { panic("unreachable") }
|
||||||
118
vendor/go.starlark.net/starlark/iter.go
generated
vendored
Normal file
118
vendor/go.starlark.net/starlark/iter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
// Copyright 2024 The Bazel 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 go1.23
|
||||||
|
|
||||||
|
package starlark
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"iter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *Dict) Entries() iter.Seq2[Value, Value] { return d.ht.entries }
|
||||||
|
|
||||||
|
// Elements returns a go1.23 iterator over the elements of the list.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// for elem := range list.Elements() { ... }
|
||||||
|
func (l *List) Elements() iter.Seq[Value] {
|
||||||
|
return func(yield func(Value) bool) {
|
||||||
|
if !l.frozen {
|
||||||
|
l.itercount++
|
||||||
|
defer func() { l.itercount-- }()
|
||||||
|
}
|
||||||
|
for _, x := range l.elems {
|
||||||
|
if !yield(x) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elements returns a go1.23 iterator over the elements of the tuple.
|
||||||
|
//
|
||||||
|
// (A Tuple is a slice, so it is of course directly iterable. This
|
||||||
|
// method exists to provide a fast path for the [Elements] standalone
|
||||||
|
// function.)
|
||||||
|
func (t Tuple) Elements() iter.Seq[Value] {
|
||||||
|
return func(yield func(Value) bool) {
|
||||||
|
for _, x := range t {
|
||||||
|
if !yield(x) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) Elements() iter.Seq[Value] {
|
||||||
|
return func(yield func(k Value) bool) {
|
||||||
|
s.ht.entries(func(k, _ Value) bool { return yield(k) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elements returns an iterator for the elements of the iterable value.
|
||||||
|
//
|
||||||
|
// Example of go1.23 iteration:
|
||||||
|
//
|
||||||
|
// for elem := range Elements(iterable) { ... }
|
||||||
|
//
|
||||||
|
// Push iterators are provided as a convenience for Go client code. The
|
||||||
|
// core iteration behavior of Starlark for-loops is defined by the
|
||||||
|
// [Iterable] interface.
|
||||||
|
func Elements(iterable Iterable) iter.Seq[Value] {
|
||||||
|
// Use specialized push iterator if available (*List, Tuple, *Set).
|
||||||
|
type hasElements interface {
|
||||||
|
Elements() iter.Seq[Value]
|
||||||
|
}
|
||||||
|
if iterable, ok := iterable.(hasElements); ok {
|
||||||
|
return iterable.Elements()
|
||||||
|
}
|
||||||
|
|
||||||
|
iter := iterable.Iterate()
|
||||||
|
return func(yield func(Value) bool) {
|
||||||
|
defer iter.Done()
|
||||||
|
var x Value
|
||||||
|
for iter.Next(&x) && yield(x) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entries returns an iterator over the entries (key/value pairs) of
|
||||||
|
// the iterable mapping.
|
||||||
|
//
|
||||||
|
// Example of go1.23 iteration:
|
||||||
|
//
|
||||||
|
// for k, v := range Entries(mapping) { ... }
|
||||||
|
//
|
||||||
|
// Push iterators are provided as a convenience for Go client code. The
|
||||||
|
// core iteration behavior of Starlark for-loops is defined by the
|
||||||
|
// [Iterable] interface.
|
||||||
|
func Entries(mapping IterableMapping) iter.Seq2[Value, Value] {
|
||||||
|
// If available (e.g. *Dict), use specialized push iterator,
|
||||||
|
// as it gets k and v in one shot.
|
||||||
|
type hasEntries interface {
|
||||||
|
Entries() iter.Seq2[Value, Value]
|
||||||
|
}
|
||||||
|
if mapping, ok := mapping.(hasEntries); ok {
|
||||||
|
return mapping.Entries()
|
||||||
|
}
|
||||||
|
|
||||||
|
iter := mapping.Iterate()
|
||||||
|
return func(yield func(k, v Value) bool) {
|
||||||
|
defer iter.Done()
|
||||||
|
var k Value
|
||||||
|
for iter.Next(&k) {
|
||||||
|
v, found, err := mapping.Get(k)
|
||||||
|
if err != nil || !found {
|
||||||
|
panic(fmt.Sprintf("Iterate and Get are inconsistent (mapping=%v, key=%v)",
|
||||||
|
mapping.Type(), k.Type()))
|
||||||
|
}
|
||||||
|
if !yield(k, v) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2501
vendor/go.starlark.net/starlark/library.go
generated
vendored
Normal file
2501
vendor/go.starlark.net/starlark/library.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
458
vendor/go.starlark.net/starlark/profile.go
generated
vendored
Normal file
458
vendor/go.starlark.net/starlark/profile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,458 @@
|
||||||
|
// Copyright 2019 The Bazel 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 starlark
|
||||||
|
|
||||||
|
// This file defines a simple execution-time profiler for Starlark.
|
||||||
|
// It measures the wall time spent executing Starlark code, and emits a
|
||||||
|
// gzipped protocol message in pprof format (github.com/google/pprof).
|
||||||
|
//
|
||||||
|
// When profiling is enabled, the interpreter calls the profiler to
|
||||||
|
// indicate the start and end of each "span" or time interval. A leaf
|
||||||
|
// function (whether Go or Starlark) has a single span. A function that
|
||||||
|
// calls another function has spans for each interval in which it is the
|
||||||
|
// top of the stack. (A LOAD instruction also ends a span.)
|
||||||
|
//
|
||||||
|
// At the start of a span, the interpreter records the current time in
|
||||||
|
// the thread's topmost frame. At the end of the span, it obtains the
|
||||||
|
// time again and subtracts the span start time. The difference is added
|
||||||
|
// to an accumulator variable in the thread. If the accumulator exceeds
|
||||||
|
// some fixed quantum (10ms, say), the profiler records the current call
|
||||||
|
// stack and sends it to the profiler goroutine, along with the number
|
||||||
|
// of quanta, which are subtracted. For example, if the accumulator
|
||||||
|
// holds 3ms and then a completed span adds 25ms to it, its value is 28ms,
|
||||||
|
// which exceeds 10ms. The profiler records a stack with the value 20ms
|
||||||
|
// (2 quanta), and the accumulator is left with 8ms.
|
||||||
|
//
|
||||||
|
// The profiler goroutine converts the stacks into the pprof format and
|
||||||
|
// emits a gzip-compressed protocol message to the designated output
|
||||||
|
// file. We use a hand-written streaming proto encoder to avoid
|
||||||
|
// dependencies on pprof and proto, and to avoid the need to
|
||||||
|
// materialize the profile data structure in memory.
|
||||||
|
//
|
||||||
|
// A limitation of this profiler is that it measures wall time, which
|
||||||
|
// does not necessarily correspond to CPU time. A CPU profiler requires
|
||||||
|
// that only running (not runnable) threads are sampled; this is
|
||||||
|
// commonly achieved by having the kernel deliver a (PROF) signal to an
|
||||||
|
// arbitrary running thread, through setitimer(2). The CPU profiler in the
|
||||||
|
// Go runtime uses this mechanism, but it is not possible for a Go
|
||||||
|
// application to register a SIGPROF handler, nor is it possible for a
|
||||||
|
// Go handler for some other signal to read the stack pointer of
|
||||||
|
// the interrupted thread.
|
||||||
|
//
|
||||||
|
// Two caveats:
|
||||||
|
// (1) it is tempting to send the leaf Frame directly to the profiler
|
||||||
|
// goroutine instead of making a copy of the stack, since a Frame is a
|
||||||
|
// spaghetti stack--a linked list. However, as soon as execution
|
||||||
|
// resumes, the stack's Frame.pc values may be mutated, so Frames are
|
||||||
|
// not safe to share with the asynchronous profiler goroutine.
|
||||||
|
// (2) it is tempting to use Callables as keys in a map when tabulating
|
||||||
|
// the pprof protocols's Function entities. However, we cannot assume
|
||||||
|
// that Callables are valid map keys, and furthermore we must not
|
||||||
|
// pin function values in memory indefinitely as this may cause lambda
|
||||||
|
// values to keep their free variables live much longer than necessary.
|
||||||
|
|
||||||
|
// TODO(adonovan):
|
||||||
|
// - make Start/Stop fully thread-safe.
|
||||||
|
// - fix the pc hack.
|
||||||
|
// - experiment with other values of quantum.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StartProfile enables time profiling of all Starlark threads,
|
||||||
|
// and writes a profile in pprof format to w.
|
||||||
|
// It must be followed by a call to StopProfiler to stop
|
||||||
|
// the profiler and finalize the profile.
|
||||||
|
//
|
||||||
|
// StartProfile returns an error if profiling was already enabled.
|
||||||
|
//
|
||||||
|
// StartProfile must not be called concurrently with Starlark execution.
|
||||||
|
func StartProfile(w io.Writer) error {
|
||||||
|
if !atomic.CompareAndSwapUint32(&profiler.on, 0, 1) {
|
||||||
|
return fmt.Errorf("profiler already running")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): make the API fully concurrency-safe.
|
||||||
|
// The main challenge is racy reads/writes of profiler.events,
|
||||||
|
// and of send/close races on the channel it refers to.
|
||||||
|
// It's easy to solve them with a mutex but harder to do
|
||||||
|
// it efficiently.
|
||||||
|
|
||||||
|
profiler.events = make(chan *profEvent, 1)
|
||||||
|
profiler.done = make(chan error)
|
||||||
|
|
||||||
|
go profile(w)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopProfile stops the profiler started by a prior call to
|
||||||
|
// StartProfile and finalizes the profile. It returns an error if the
|
||||||
|
// profile could not be completed.
|
||||||
|
//
|
||||||
|
// StopProfile must not be called concurrently with Starlark execution.
|
||||||
|
func StopProfile() error {
|
||||||
|
// Terminate the profiler goroutine and get its result.
|
||||||
|
close(profiler.events)
|
||||||
|
err := <-profiler.done
|
||||||
|
|
||||||
|
profiler.done = nil
|
||||||
|
profiler.events = nil
|
||||||
|
atomic.StoreUint32(&profiler.on, 0)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// globals
|
||||||
|
var profiler struct {
|
||||||
|
on uint32 // nonzero => profiler running
|
||||||
|
events chan *profEvent // profile events from interpreter threads
|
||||||
|
done chan error // indicates profiler goroutine is ready
|
||||||
|
}
|
||||||
|
|
||||||
|
func (thread *Thread) beginProfSpan() {
|
||||||
|
if profiler.events == nil {
|
||||||
|
return // profiling not enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.frameAt(0).spanStart = nanotime()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): experiment with smaller values,
|
||||||
|
// which trade space and time for greater precision.
|
||||||
|
const quantum = 10 * time.Millisecond
|
||||||
|
|
||||||
|
func (thread *Thread) endProfSpan() {
|
||||||
|
if profiler.events == nil {
|
||||||
|
return // profiling not enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the span to the thread's accumulator.
|
||||||
|
thread.proftime += time.Duration(nanotime() - thread.frameAt(0).spanStart)
|
||||||
|
if thread.proftime < quantum {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only record complete quanta.
|
||||||
|
n := thread.proftime / quantum
|
||||||
|
thread.proftime -= n * quantum
|
||||||
|
|
||||||
|
// Copy the stack.
|
||||||
|
// (We can't save thread.frame because its pc will change.)
|
||||||
|
ev := &profEvent{
|
||||||
|
thread: thread,
|
||||||
|
time: n * quantum,
|
||||||
|
}
|
||||||
|
ev.stack = ev.stackSpace[:0]
|
||||||
|
for i := range thread.stack {
|
||||||
|
fr := thread.frameAt(i)
|
||||||
|
ev.stack = append(ev.stack, profFrame{
|
||||||
|
pos: fr.Position(),
|
||||||
|
fn: fr.Callable(),
|
||||||
|
pc: fr.pc,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.events <- ev
|
||||||
|
}
|
||||||
|
|
||||||
|
type profEvent struct {
|
||||||
|
thread *Thread // currently unused
|
||||||
|
time time.Duration
|
||||||
|
stack []profFrame
|
||||||
|
stackSpace [8]profFrame // initial space for stack
|
||||||
|
}
|
||||||
|
|
||||||
|
type profFrame struct {
|
||||||
|
fn Callable // don't hold this live for too long (prevents GC of lambdas)
|
||||||
|
pc uint32 // program counter (Starlark frames only)
|
||||||
|
pos syntax.Position // position of pc within this frame
|
||||||
|
}
|
||||||
|
|
||||||
|
// profile is the profiler goroutine.
|
||||||
|
// It runs until StopProfiler is called.
|
||||||
|
func profile(w io.Writer) {
|
||||||
|
// Field numbers from pprof protocol.
|
||||||
|
// See https://github.com/google/pprof/blob/master/proto/profile.proto
|
||||||
|
const (
|
||||||
|
Profile_sample_type = 1 // repeated ValueType
|
||||||
|
Profile_sample = 2 // repeated Sample
|
||||||
|
Profile_mapping = 3 // repeated Mapping
|
||||||
|
Profile_location = 4 // repeated Location
|
||||||
|
Profile_function = 5 // repeated Function
|
||||||
|
Profile_string_table = 6 // repeated string
|
||||||
|
Profile_time_nanos = 9 // int64
|
||||||
|
Profile_duration_nanos = 10 // int64
|
||||||
|
Profile_period_type = 11 // ValueType
|
||||||
|
Profile_period = 12 // int64
|
||||||
|
|
||||||
|
ValueType_type = 1 // int64
|
||||||
|
ValueType_unit = 2 // int64
|
||||||
|
|
||||||
|
Sample_location_id = 1 // repeated uint64
|
||||||
|
Sample_value = 2 // repeated int64
|
||||||
|
Sample_label = 3 // repeated Label
|
||||||
|
|
||||||
|
Label_key = 1 // int64
|
||||||
|
Label_str = 2 // int64
|
||||||
|
Label_num = 3 // int64
|
||||||
|
Label_num_unit = 4 // int64
|
||||||
|
|
||||||
|
Location_id = 1 // uint64
|
||||||
|
Location_mapping_id = 2 // uint64
|
||||||
|
Location_address = 3 // uint64
|
||||||
|
Location_line = 4 // repeated Line
|
||||||
|
|
||||||
|
Line_function_id = 1 // uint64
|
||||||
|
Line_line = 2 // int64
|
||||||
|
|
||||||
|
Function_id = 1 // uint64
|
||||||
|
Function_name = 2 // int64
|
||||||
|
Function_system_name = 3 // int64
|
||||||
|
Function_filename = 4 // int64
|
||||||
|
Function_start_line = 5 // int64
|
||||||
|
)
|
||||||
|
|
||||||
|
bufw := bufio.NewWriter(w) // write file in 4KB (not 240B flate-sized) chunks
|
||||||
|
gz := gzip.NewWriter(bufw)
|
||||||
|
enc := protoEncoder{w: gz}
|
||||||
|
|
||||||
|
// strings
|
||||||
|
stringIndex := make(map[string]int64)
|
||||||
|
str := func(s string) int64 {
|
||||||
|
i, ok := stringIndex[s]
|
||||||
|
if !ok {
|
||||||
|
i = int64(len(stringIndex))
|
||||||
|
enc.string(Profile_string_table, s)
|
||||||
|
stringIndex[s] = i
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
str("") // entry 0
|
||||||
|
|
||||||
|
// functions
|
||||||
|
//
|
||||||
|
// function returns the ID of a Callable for use in Line.FunctionId.
|
||||||
|
// The ID is the same as the function's logical address,
|
||||||
|
// which is supplied by the caller to avoid the need to recompute it.
|
||||||
|
functionId := make(map[uintptr]uint64)
|
||||||
|
function := func(fn Callable, addr uintptr) uint64 {
|
||||||
|
id, ok := functionId[addr]
|
||||||
|
if !ok {
|
||||||
|
id = uint64(addr)
|
||||||
|
|
||||||
|
var pos syntax.Position
|
||||||
|
if fn, ok := fn.(callableWithPosition); ok {
|
||||||
|
pos = fn.Position()
|
||||||
|
}
|
||||||
|
|
||||||
|
name := fn.Name()
|
||||||
|
if name == "<toplevel>" {
|
||||||
|
name = pos.Filename()
|
||||||
|
}
|
||||||
|
|
||||||
|
nameIndex := str(name)
|
||||||
|
|
||||||
|
fun := new(bytes.Buffer)
|
||||||
|
funenc := protoEncoder{w: fun}
|
||||||
|
funenc.uint(Function_id, id)
|
||||||
|
funenc.int(Function_name, nameIndex)
|
||||||
|
funenc.int(Function_system_name, nameIndex)
|
||||||
|
funenc.int(Function_filename, str(pos.Filename()))
|
||||||
|
funenc.int(Function_start_line, int64(pos.Line))
|
||||||
|
enc.bytes(Profile_function, fun.Bytes())
|
||||||
|
|
||||||
|
functionId[addr] = id
|
||||||
|
}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
// locations
|
||||||
|
//
|
||||||
|
// location returns the ID of the location denoted by fr.
|
||||||
|
// For Starlark frames, this is the Frame pc.
|
||||||
|
locationId := make(map[uintptr]uint64)
|
||||||
|
location := func(fr profFrame) uint64 {
|
||||||
|
fnAddr := profFuncAddr(fr.fn)
|
||||||
|
|
||||||
|
// For Starlark functions, the frame position
|
||||||
|
// represents the current PC value.
|
||||||
|
// Mix it into the low bits of the address.
|
||||||
|
// This is super hacky and may result in collisions
|
||||||
|
// in large functions or if functions are numerous.
|
||||||
|
// TODO(adonovan): fix: try making this cleaner by treating
|
||||||
|
// each bytecode segment as a Profile.Mapping.
|
||||||
|
pcAddr := fnAddr
|
||||||
|
if _, ok := fr.fn.(*Function); ok {
|
||||||
|
pcAddr = (pcAddr << 16) ^ uintptr(fr.pc)
|
||||||
|
}
|
||||||
|
|
||||||
|
id, ok := locationId[pcAddr]
|
||||||
|
if !ok {
|
||||||
|
id = uint64(pcAddr)
|
||||||
|
|
||||||
|
line := new(bytes.Buffer)
|
||||||
|
lineenc := protoEncoder{w: line}
|
||||||
|
lineenc.uint(Line_function_id, function(fr.fn, fnAddr))
|
||||||
|
lineenc.int(Line_line, int64(fr.pos.Line))
|
||||||
|
loc := new(bytes.Buffer)
|
||||||
|
locenc := protoEncoder{w: loc}
|
||||||
|
locenc.uint(Location_id, id)
|
||||||
|
locenc.uint(Location_address, uint64(pcAddr))
|
||||||
|
locenc.bytes(Location_line, line.Bytes())
|
||||||
|
enc.bytes(Profile_location, loc.Bytes())
|
||||||
|
|
||||||
|
locationId[pcAddr] = id
|
||||||
|
}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
wallNanos := new(bytes.Buffer)
|
||||||
|
wnenc := protoEncoder{w: wallNanos}
|
||||||
|
wnenc.int(ValueType_type, str("wall"))
|
||||||
|
wnenc.int(ValueType_unit, str("nanoseconds"))
|
||||||
|
|
||||||
|
// informational fields of Profile
|
||||||
|
enc.bytes(Profile_sample_type, wallNanos.Bytes())
|
||||||
|
enc.int(Profile_period, quantum.Nanoseconds()) // magnitude of sampling period
|
||||||
|
enc.bytes(Profile_period_type, wallNanos.Bytes()) // dimension and unit of period
|
||||||
|
enc.int(Profile_time_nanos, time.Now().UnixNano()) // start (real) time of profile
|
||||||
|
|
||||||
|
startNano := nanotime()
|
||||||
|
|
||||||
|
// Read profile events from the channel
|
||||||
|
// until it is closed by StopProfiler.
|
||||||
|
for e := range profiler.events {
|
||||||
|
sample := new(bytes.Buffer)
|
||||||
|
sampleenc := protoEncoder{w: sample}
|
||||||
|
sampleenc.int(Sample_value, e.time.Nanoseconds()) // wall nanoseconds
|
||||||
|
for _, fr := range e.stack {
|
||||||
|
sampleenc.uint(Sample_location_id, location(fr))
|
||||||
|
}
|
||||||
|
enc.bytes(Profile_sample, sample.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
endNano := nanotime()
|
||||||
|
enc.int(Profile_duration_nanos, endNano-startNano)
|
||||||
|
|
||||||
|
err := gz.Close() // Close reports any prior write error
|
||||||
|
if flushErr := bufw.Flush(); err == nil {
|
||||||
|
err = flushErr
|
||||||
|
}
|
||||||
|
profiler.done <- err
|
||||||
|
}
|
||||||
|
|
||||||
|
// nanotime returns the time in nanoseconds since process start.
|
||||||
|
//
|
||||||
|
// This approach, described at
|
||||||
|
// https://github.com/golang/go/issues/61765#issuecomment-1672090302,
|
||||||
|
// is fast, monotonic, and portable, and avoids the previous
|
||||||
|
// dependence on runtime.nanotime using the (unsafe) linkname hack.
|
||||||
|
// In particular, time.Since does less work than time.Now.
|
||||||
|
//
|
||||||
|
// Rejected approaches:
|
||||||
|
//
|
||||||
|
// Using the linkname hack to unsafely access runtime.nanotime.
|
||||||
|
// See #546 and golang/go#67401.
|
||||||
|
//
|
||||||
|
// // POSIX only. REALTIME not MONOTONIC. 17ns.
|
||||||
|
// var tv syscall.Timeval
|
||||||
|
// syscall.Gettimeofday(&tv) // can't fail
|
||||||
|
// return tv.Nano()
|
||||||
|
//
|
||||||
|
// // Portable. REALTIME not MONOTONIC. 46ns.
|
||||||
|
// return time.Now().Nanoseconds()
|
||||||
|
//
|
||||||
|
// // POSIX only. Adds a dependency.
|
||||||
|
// import "golang.org/x/sys/unix"
|
||||||
|
// var ts unix.Timespec
|
||||||
|
// unix.ClockGettime(CLOCK_MONOTONIC, &ts) // can't fail
|
||||||
|
// return unix.TimespecToNsec(ts)
|
||||||
|
func nanotime() int64 {
|
||||||
|
return time.Since(processStart).Nanoseconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
var processStart = time.Now()
|
||||||
|
|
||||||
|
// profFuncAddr returns the canonical "address"
|
||||||
|
// of a Callable for use by the profiler.
|
||||||
|
func profFuncAddr(fn Callable) uintptr {
|
||||||
|
switch fn := fn.(type) {
|
||||||
|
case *Builtin:
|
||||||
|
return reflect.ValueOf(fn.fn).Pointer()
|
||||||
|
case *Function:
|
||||||
|
return uintptr(unsafe.Pointer(fn.funcode))
|
||||||
|
}
|
||||||
|
|
||||||
|
// User-defined callable types are typically of
|
||||||
|
// kind pointer-to-struct. Handle them specially.
|
||||||
|
if v := reflect.ValueOf(fn); v.Type().Kind() == reflect.Ptr {
|
||||||
|
return v.Pointer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address zero is reserved by the protocol.
|
||||||
|
// Use 1 for callables we don't recognize.
|
||||||
|
log.Printf("Starlark profiler: no address for Callable %T", fn)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// We encode the protocol message by hand to avoid making
|
||||||
|
// the interpreter depend on both github.com/google/pprof
|
||||||
|
// and github.com/golang/protobuf.
|
||||||
|
//
|
||||||
|
// This also avoids the need to materialize a protocol message object
|
||||||
|
// tree of unbounded size and serialize it all at the end.
|
||||||
|
// The pprof format appears to have been designed to
|
||||||
|
// permit streaming implementations such as this one.
|
||||||
|
//
|
||||||
|
// See https://developers.google.com/protocol-buffers/docs/encoding.
|
||||||
|
type protoEncoder struct {
|
||||||
|
w io.Writer // *bytes.Buffer or *gzip.Writer
|
||||||
|
tmp [binary.MaxVarintLen64]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *protoEncoder) uvarint(x uint64) {
|
||||||
|
n := binary.PutUvarint(e.tmp[:], x)
|
||||||
|
e.w.Write(e.tmp[:n])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *protoEncoder) tag(field, wire uint) {
|
||||||
|
e.uvarint(uint64(field<<3 | wire))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *protoEncoder) string(field uint, s string) {
|
||||||
|
e.tag(field, 2) // length-delimited
|
||||||
|
e.uvarint(uint64(len(s)))
|
||||||
|
io.WriteString(e.w, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *protoEncoder) bytes(field uint, b []byte) {
|
||||||
|
e.tag(field, 2) // length-delimited
|
||||||
|
e.uvarint(uint64(len(b)))
|
||||||
|
e.w.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *protoEncoder) uint(field uint, x uint64) {
|
||||||
|
e.tag(field, 0) // varint
|
||||||
|
e.uvarint(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *protoEncoder) int(field uint, x int64) {
|
||||||
|
e.tag(field, 0) // varint
|
||||||
|
e.uvarint(uint64(x))
|
||||||
|
}
|
||||||
364
vendor/go.starlark.net/starlark/unpack.go
generated
vendored
Normal file
364
vendor/go.starlark.net/starlark/unpack.go
generated
vendored
Normal file
|
|
@ -0,0 +1,364 @@
|
||||||
|
package starlark
|
||||||
|
|
||||||
|
// This file defines the Unpack helper functions used by
|
||||||
|
// built-in functions to interpret their call arguments.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.starlark.net/internal/spell"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Unpacker defines custom argument unpacking behavior.
|
||||||
|
// See UnpackArgs.
|
||||||
|
type Unpacker interface {
|
||||||
|
Unpack(v Value) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackArgs unpacks the positional and keyword arguments into the
|
||||||
|
// supplied parameter variables. pairs is an alternating list of names
|
||||||
|
// and pointers to variables.
|
||||||
|
//
|
||||||
|
// If the variable is a bool, integer, string, *List, *Dict, Callable,
|
||||||
|
// Iterable, or user-defined implementation of Value,
|
||||||
|
// UnpackArgs performs the appropriate type check.
|
||||||
|
// Predeclared Go integer types use the AsInt check.
|
||||||
|
//
|
||||||
|
// If the parameter name ends with "?", it is optional.
|
||||||
|
//
|
||||||
|
// If the parameter name ends with "??", it is optional and treats the None value
|
||||||
|
// as if the argument was absent.
|
||||||
|
//
|
||||||
|
// If a parameter is marked optional, then all following parameters are
|
||||||
|
// implicitly optional whether or not they are marked.
|
||||||
|
//
|
||||||
|
// If the variable implements Unpacker, its Unpack argument
|
||||||
|
// is called with the argument value, allowing an application
|
||||||
|
// to define its own argument validation and conversion.
|
||||||
|
//
|
||||||
|
// If the variable implements Value, UnpackArgs may call
|
||||||
|
// its Type() method while constructing the error message.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// var (
|
||||||
|
// a Value
|
||||||
|
// b = MakeInt(42)
|
||||||
|
// c Value = starlark.None
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// // 1. mixed parameters, like def f(a, b=42, c=None).
|
||||||
|
// err := UnpackArgs("f", args, kwargs, "a", &a, "b?", &b, "c?", &c)
|
||||||
|
//
|
||||||
|
// // 2. keyword parameters only, like def f(*, a, b, c=None).
|
||||||
|
// if len(args) > 0 {
|
||||||
|
// return fmt.Errorf("f: unexpected positional arguments")
|
||||||
|
// }
|
||||||
|
// err := UnpackArgs("f", args, kwargs, "a", &a, "b?", &b, "c?", &c)
|
||||||
|
//
|
||||||
|
// // 3. positional parameters only, like def f(a, b=42, c=None, /) in Python 3.8.
|
||||||
|
// err := UnpackPositionalArgs("f", args, kwargs, 1, &a, &b, &c)
|
||||||
|
//
|
||||||
|
// More complex forms such as def f(a, b=42, *args, c, d=123, **kwargs)
|
||||||
|
// require additional logic, but their need in built-ins is exceedingly rare.
|
||||||
|
//
|
||||||
|
// In the examples above, the declaration of b with type Int causes UnpackArgs
|
||||||
|
// to require that b's argument value, if provided, is also an int.
|
||||||
|
// To allow arguments of any type, while retaining the default value of 42,
|
||||||
|
// declare b as a Value:
|
||||||
|
//
|
||||||
|
// var b Value = MakeInt(42)
|
||||||
|
//
|
||||||
|
// The zero value of a variable of type Value, such as 'a' in the
|
||||||
|
// examples above, is not a valid Starlark value, so if the parameter is
|
||||||
|
// optional, the caller must explicitly handle the default case by
|
||||||
|
// interpreting nil as None or some computed default. The same is true
|
||||||
|
// for the zero values of variables of type *List, *Dict, Callable, or
|
||||||
|
// Iterable. For example:
|
||||||
|
//
|
||||||
|
// // def myfunc(d=None, e=[], f={})
|
||||||
|
// var (
|
||||||
|
// d Value
|
||||||
|
// e *List
|
||||||
|
// f *Dict
|
||||||
|
// )
|
||||||
|
// err := UnpackArgs("myfunc", args, kwargs, "d?", &d, "e?", &e, "f?", &f)
|
||||||
|
// if d == nil { d = None; }
|
||||||
|
// if e == nil { e = new(List); }
|
||||||
|
// if f == nil { f = new(Dict); }
|
||||||
|
func UnpackArgs(fnname string, args Tuple, kwargs []Tuple, pairs ...any) error {
|
||||||
|
nparams := len(pairs) / 2
|
||||||
|
var defined intset
|
||||||
|
defined.init(nparams)
|
||||||
|
|
||||||
|
paramName := func(x any) (name string, skipNone bool) { // (no free variables)
|
||||||
|
name = x.(string)
|
||||||
|
if strings.HasSuffix(name, "??") {
|
||||||
|
name = strings.TrimSuffix(name, "??")
|
||||||
|
skipNone = true
|
||||||
|
} else if name[len(name)-1] == '?' {
|
||||||
|
name = name[:len(name)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return name, skipNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// positional arguments
|
||||||
|
if len(args) > nparams {
|
||||||
|
return fmt.Errorf("%s: got %d arguments, want at most %d",
|
||||||
|
fnname, len(args), nparams)
|
||||||
|
}
|
||||||
|
for i, arg := range args {
|
||||||
|
defined.set(i)
|
||||||
|
name, skipNone := paramName(pairs[2*i])
|
||||||
|
if skipNone {
|
||||||
|
if _, isNone := arg.(NoneType); isNone {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := UnpackArg(arg, pairs[2*i+1]); err != nil {
|
||||||
|
return fmt.Errorf("%s: for parameter %s: %s", fnname, name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyword arguments
|
||||||
|
kwloop:
|
||||||
|
for _, item := range kwargs {
|
||||||
|
name, arg := item[0].(String), item[1]
|
||||||
|
for i := 0; i < nparams; i++ {
|
||||||
|
pName, skipNone := paramName(pairs[2*i])
|
||||||
|
if pName == string(name) {
|
||||||
|
// found it
|
||||||
|
if defined.set(i) {
|
||||||
|
return fmt.Errorf("%s: got multiple values for keyword argument %s",
|
||||||
|
fnname, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipNone {
|
||||||
|
if _, isNone := arg.(NoneType); isNone {
|
||||||
|
continue kwloop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr := pairs[2*i+1]
|
||||||
|
if err := UnpackArg(arg, ptr); err != nil {
|
||||||
|
return fmt.Errorf("%s: for parameter %s: %s", fnname, name, err)
|
||||||
|
}
|
||||||
|
continue kwloop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := fmt.Errorf("%s: unexpected keyword argument %s", fnname, name)
|
||||||
|
names := make([]string, 0, nparams)
|
||||||
|
for i := 0; i < nparams; i += 2 {
|
||||||
|
param, _ := paramName(pairs[i])
|
||||||
|
names = append(names, param)
|
||||||
|
}
|
||||||
|
if n := spell.Nearest(string(name), names); n != "" {
|
||||||
|
err = fmt.Errorf("%s (did you mean %s?)", err.Error(), n)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all non-optional parameters are defined.
|
||||||
|
for i := 0; i < nparams; i++ {
|
||||||
|
name := pairs[2*i].(string)
|
||||||
|
if strings.HasSuffix(name, "?") {
|
||||||
|
break // optional
|
||||||
|
}
|
||||||
|
// (We needn't check the first len(args).)
|
||||||
|
if i < len(args) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !defined.get(i) {
|
||||||
|
return fmt.Errorf("%s: missing argument for %s", fnname, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackPositionalArgs unpacks the positional arguments into
|
||||||
|
// corresponding variables. Each element of vars is a pointer; see
|
||||||
|
// UnpackArgs for allowed types and conversions.
|
||||||
|
//
|
||||||
|
// UnpackPositionalArgs reports an error if the number of arguments is
|
||||||
|
// less than min or greater than len(vars), if kwargs is nonempty, or if
|
||||||
|
// any conversion fails.
|
||||||
|
//
|
||||||
|
// See UnpackArgs for general comments.
|
||||||
|
func UnpackPositionalArgs(fnname string, args Tuple, kwargs []Tuple, min int, vars ...any) error {
|
||||||
|
if len(kwargs) > 0 {
|
||||||
|
return fmt.Errorf("%s: unexpected keyword arguments", fnname)
|
||||||
|
}
|
||||||
|
max := len(vars)
|
||||||
|
if len(args) < min {
|
||||||
|
var atleast string
|
||||||
|
if min < max {
|
||||||
|
atleast = "at least "
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s: got %d arguments, want %s%d", fnname, len(args), atleast, min)
|
||||||
|
}
|
||||||
|
if len(args) > max {
|
||||||
|
var atmost string
|
||||||
|
if max > min {
|
||||||
|
atmost = "at most "
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s: got %d arguments, want %s%d", fnname, len(args), atmost, max)
|
||||||
|
}
|
||||||
|
for i, arg := range args {
|
||||||
|
if err := UnpackArg(arg, vars[i]); err != nil {
|
||||||
|
return fmt.Errorf("%s: for parameter %d: %s", fnname, i+1, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackArg unpacks a Value v into the variable pointed to by ptr.
|
||||||
|
// See [UnpackArgs] for details, including which types of variable are supported.
|
||||||
|
//
|
||||||
|
// This function defines the unpack operation for a single value.
|
||||||
|
// The implementations of most built-in functions use [UnpackArgs] and
|
||||||
|
// [UnpackPositionalArgs] to unpack a sequence of positional and/or
|
||||||
|
// keyword arguments.
|
||||||
|
func UnpackArg(v Value, ptr any) error {
|
||||||
|
// On failure, don't clobber *ptr.
|
||||||
|
switch ptr := ptr.(type) {
|
||||||
|
case Unpacker:
|
||||||
|
return ptr.Unpack(v)
|
||||||
|
case *Value:
|
||||||
|
*ptr = v
|
||||||
|
case *string:
|
||||||
|
s, ok := AsString(v)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want string", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = s
|
||||||
|
case *bool:
|
||||||
|
b, ok := v.(Bool)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want bool", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = bool(b)
|
||||||
|
case *int, *int8, *int16, *int32, *int64,
|
||||||
|
*uint, *uint8, *uint16, *uint32, *uint64, *uintptr:
|
||||||
|
return AsInt(v, ptr)
|
||||||
|
case *float64:
|
||||||
|
f, ok := v.(Float)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want float", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = float64(f)
|
||||||
|
case **List:
|
||||||
|
list, ok := v.(*List)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want list", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = list
|
||||||
|
case **Dict:
|
||||||
|
dict, ok := v.(*Dict)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want dict", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = dict
|
||||||
|
case *Callable:
|
||||||
|
f, ok := v.(Callable)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want callable", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = f
|
||||||
|
case *Iterable:
|
||||||
|
it, ok := v.(Iterable)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("got %s, want iterable", v.Type())
|
||||||
|
}
|
||||||
|
*ptr = it
|
||||||
|
default:
|
||||||
|
// v must have type *V, where V is some subtype of starlark.Value.
|
||||||
|
ptrv := reflect.ValueOf(ptr)
|
||||||
|
if ptrv.Kind() != reflect.Ptr {
|
||||||
|
log.Panicf("internal error: not a pointer: %T", ptr)
|
||||||
|
}
|
||||||
|
paramVar := ptrv.Elem()
|
||||||
|
if !reflect.TypeOf(v).AssignableTo(paramVar.Type()) {
|
||||||
|
// The value is not assignable to the variable.
|
||||||
|
|
||||||
|
// Detect a possible bug in the Go program that called Unpack:
|
||||||
|
// If the variable *ptr is not a subtype of Value,
|
||||||
|
// no value of v can possibly work.
|
||||||
|
if !paramVar.Type().AssignableTo(reflect.TypeOf(new(Value)).Elem()) {
|
||||||
|
log.Panicf("pointer element type does not implement Value: %T", ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report Starlark dynamic type error.
|
||||||
|
//
|
||||||
|
// We prefer the Starlark Value.Type name over
|
||||||
|
// its Go reflect.Type name, but calling the
|
||||||
|
// Value.Type method on the variable is not safe
|
||||||
|
// in general. If the variable is an interface,
|
||||||
|
// the call will fail. Even if the variable has
|
||||||
|
// a concrete type, it might not be safe to call
|
||||||
|
// Type() on a zero instance. Thus we must use
|
||||||
|
// recover.
|
||||||
|
|
||||||
|
// Default to Go reflect.Type name
|
||||||
|
paramType := paramVar.Type().String()
|
||||||
|
|
||||||
|
// Attempt to call Value.Type method.
|
||||||
|
func() {
|
||||||
|
defer func() { recover() }()
|
||||||
|
if typer, _ := paramVar.Interface().(interface{ Type() string }); typer != nil {
|
||||||
|
paramType = typer.Type()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return fmt.Errorf("got %s, want %s", v.Type(), paramType)
|
||||||
|
}
|
||||||
|
paramVar.Set(reflect.ValueOf(v))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type intset struct {
|
||||||
|
small uint64 // bitset, used if n < 64
|
||||||
|
large map[int]bool // set, used if n >= 64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *intset) init(n int) {
|
||||||
|
if n >= 64 {
|
||||||
|
is.large = make(map[int]bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *intset) set(i int) (prev bool) {
|
||||||
|
if is.large == nil {
|
||||||
|
prev = is.small&(1<<uint(i)) != 0
|
||||||
|
is.small |= 1 << uint(i)
|
||||||
|
} else {
|
||||||
|
prev = is.large[i]
|
||||||
|
is.large[i] = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *intset) get(i int) bool {
|
||||||
|
if is.large == nil {
|
||||||
|
return is.small&(1<<uint(i)) != 0
|
||||||
|
}
|
||||||
|
return is.large[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *intset) len() int {
|
||||||
|
if is.large == nil {
|
||||||
|
// Suboptimal, but used only for error reporting.
|
||||||
|
len := 0
|
||||||
|
for i := 0; i < 64; i++ {
|
||||||
|
if is.small&(1<<uint(i)) != 0 {
|
||||||
|
len++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
return len(is.large)
|
||||||
|
}
|
||||||
1718
vendor/go.starlark.net/starlark/value.go
generated
vendored
Normal file
1718
vendor/go.starlark.net/starlark/value.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
43
vendor/go.starlark.net/starlarkstruct/module.go
generated
vendored
Normal file
43
vendor/go.starlark.net/starlarkstruct/module.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package starlarkstruct
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Module is a named collection of values,
|
||||||
|
// typically a suite of functions imported by a load statement.
|
||||||
|
//
|
||||||
|
// It differs from Struct primarily in that its string representation
|
||||||
|
// does not enumerate its fields.
|
||||||
|
type Module struct {
|
||||||
|
Name string
|
||||||
|
Members starlark.StringDict
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ starlark.HasAttrs = (*Module)(nil)
|
||||||
|
|
||||||
|
func (m *Module) Attr(name string) (starlark.Value, error) { return m.Members[name], nil }
|
||||||
|
func (m *Module) AttrNames() []string { return m.Members.Keys() }
|
||||||
|
func (m *Module) Freeze() { m.Members.Freeze() }
|
||||||
|
func (m *Module) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", m.Type()) }
|
||||||
|
func (m *Module) String() string { return fmt.Sprintf("<module %q>", m.Name) }
|
||||||
|
func (m *Module) Truth() starlark.Bool { return true }
|
||||||
|
func (m *Module) Type() string { return "module" }
|
||||||
|
|
||||||
|
// MakeModule may be used as the implementation of a Starlark built-in
|
||||||
|
// function, module(name, **kwargs). It returns a new module with the
|
||||||
|
// specified name and members.
|
||||||
|
func MakeModule(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
var name string
|
||||||
|
if err := starlark.UnpackPositionalArgs(b.Name(), args, nil, 1, &name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
members := make(starlark.StringDict, len(kwargs))
|
||||||
|
for _, kwarg := range kwargs {
|
||||||
|
k := string(kwarg[0].(starlark.String))
|
||||||
|
members[k] = kwarg[1]
|
||||||
|
}
|
||||||
|
return &Module{name, members}, nil
|
||||||
|
}
|
||||||
284
vendor/go.starlark.net/starlarkstruct/struct.go
generated
vendored
Normal file
284
vendor/go.starlark.net/starlarkstruct/struct.go
generated
vendored
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
// Copyright 2017 The Bazel 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 starlarkstruct defines the Starlark types 'struct' and
|
||||||
|
// 'module', both optional language extensions.
|
||||||
|
package starlarkstruct // import "go.starlark.net/starlarkstruct"
|
||||||
|
|
||||||
|
// It is tempting to introduce a variant of Struct that is a wrapper
|
||||||
|
// around a Go struct value, for stronger typing guarantees and more
|
||||||
|
// efficient and convenient field lookup. However:
|
||||||
|
// 1) all fields of Starlark structs are optional, so we cannot represent
|
||||||
|
// them using more specific types such as String, Int, *Depset, and
|
||||||
|
// *File, as such types give no way to represent missing fields.
|
||||||
|
// 2) the efficiency gain of direct struct field access is rather
|
||||||
|
// marginal: finding the index of a field by binary searching on the
|
||||||
|
// sorted list of field names is quite fast compared to the other
|
||||||
|
// overheads.
|
||||||
|
// 3) the gains in compactness and spatial locality are also rather
|
||||||
|
// marginal: the array behind the []entry slice is (due to field name
|
||||||
|
// strings) only a factor of 2 larger than the corresponding Go struct
|
||||||
|
// would be, and, like the Go struct, requires only a single allocation.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.starlark.net/starlark"
|
||||||
|
"go.starlark.net/syntax"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Make is the implementation of a built-in function that instantiates
|
||||||
|
// an immutable struct from the specified keyword arguments.
|
||||||
|
//
|
||||||
|
// An application can add 'struct' to the Starlark environment like so:
|
||||||
|
//
|
||||||
|
// globals := starlark.StringDict{
|
||||||
|
// "struct": starlark.NewBuiltin("struct", starlarkstruct.Make),
|
||||||
|
// }
|
||||||
|
func Make(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||||
|
if len(args) > 0 {
|
||||||
|
return nil, fmt.Errorf("struct: unexpected positional arguments")
|
||||||
|
}
|
||||||
|
return FromKeywords(Default, kwargs), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromKeywords returns a new struct instance whose fields are specified by the
|
||||||
|
// key/value pairs in kwargs. (Each kwargs[i][0] must be a starlark.String.)
|
||||||
|
func FromKeywords(constructor starlark.Value, kwargs []starlark.Tuple) *Struct {
|
||||||
|
if constructor == nil {
|
||||||
|
panic("nil constructor")
|
||||||
|
}
|
||||||
|
s := &Struct{
|
||||||
|
constructor: constructor,
|
||||||
|
entries: make(entries, 0, len(kwargs)),
|
||||||
|
}
|
||||||
|
for _, kwarg := range kwargs {
|
||||||
|
k := string(kwarg[0].(starlark.String))
|
||||||
|
v := kwarg[1]
|
||||||
|
s.entries = append(s.entries, entry{k, v})
|
||||||
|
}
|
||||||
|
sort.Sort(s.entries)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStringDict returns a new struct instance whose elements are those of d.
|
||||||
|
// The constructor parameter specifies the constructor; use Default for an ordinary struct.
|
||||||
|
func FromStringDict(constructor starlark.Value, d starlark.StringDict) *Struct {
|
||||||
|
if constructor == nil {
|
||||||
|
panic("nil constructor")
|
||||||
|
}
|
||||||
|
s := &Struct{
|
||||||
|
constructor: constructor,
|
||||||
|
entries: make(entries, 0, len(d)),
|
||||||
|
}
|
||||||
|
for k, v := range d {
|
||||||
|
s.entries = append(s.entries, entry{k, v})
|
||||||
|
}
|
||||||
|
sort.Sort(s.entries)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Struct is an immutable Starlark type that maps field names to values.
|
||||||
|
// It is not iterable and does not support len.
|
||||||
|
//
|
||||||
|
// A struct has a constructor, a distinct value that identifies a class
|
||||||
|
// of structs, and which appears in the struct's string representation.
|
||||||
|
//
|
||||||
|
// Operations such as x+y fail if the constructors of the two operands
|
||||||
|
// are not equal.
|
||||||
|
//
|
||||||
|
// The default constructor, Default, is the string "struct", but
|
||||||
|
// clients may wish to 'brand' structs for their own purposes.
|
||||||
|
// The constructor value appears in the printed form of the value,
|
||||||
|
// and is accessible using the Constructor method.
|
||||||
|
//
|
||||||
|
// Use Attr to access its fields and AttrNames to enumerate them.
|
||||||
|
type Struct struct {
|
||||||
|
constructor starlark.Value
|
||||||
|
entries entries // sorted by name
|
||||||
|
frozen bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default is the default constructor for structs.
|
||||||
|
// It is merely the string "struct".
|
||||||
|
const Default = starlark.String("struct")
|
||||||
|
|
||||||
|
type entries []entry
|
||||||
|
|
||||||
|
func (a entries) Len() int { return len(a) }
|
||||||
|
func (a entries) Less(i, j int) bool { return a[i].name < a[j].name }
|
||||||
|
func (a entries) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
name string
|
||||||
|
value starlark.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ starlark.HasAttrs = (*Struct)(nil)
|
||||||
|
_ starlark.HasBinary = (*Struct)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToStringDict adds a name/value entry to d for each field of the struct.
|
||||||
|
func (s *Struct) ToStringDict(d starlark.StringDict) {
|
||||||
|
for _, e := range s.entries {
|
||||||
|
d[e.name] = e.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) String() string {
|
||||||
|
buf := new(strings.Builder)
|
||||||
|
switch constructor := s.constructor.(type) {
|
||||||
|
case starlark.String:
|
||||||
|
// NB: The Java implementation always prints struct
|
||||||
|
// even for Bazel provider instances.
|
||||||
|
buf.WriteString(constructor.GoString()) // avoid String()'s quotation
|
||||||
|
default:
|
||||||
|
buf.WriteString(s.constructor.String())
|
||||||
|
}
|
||||||
|
buf.WriteByte('(')
|
||||||
|
for i, e := range s.entries {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteString(", ")
|
||||||
|
}
|
||||||
|
buf.WriteString(e.name)
|
||||||
|
buf.WriteString(" = ")
|
||||||
|
buf.WriteString(e.value.String())
|
||||||
|
}
|
||||||
|
buf.WriteByte(')')
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor returns the constructor used to create this struct.
|
||||||
|
func (s *Struct) Constructor() starlark.Value { return s.constructor }
|
||||||
|
|
||||||
|
func (s *Struct) Type() string { return "struct" }
|
||||||
|
func (s *Struct) Truth() starlark.Bool { return true } // even when empty
|
||||||
|
func (s *Struct) Hash() (uint32, error) {
|
||||||
|
// Same algorithm as Tuple.hash, but with different primes.
|
||||||
|
var x, m uint32 = 8731, 9839
|
||||||
|
for _, e := range s.entries {
|
||||||
|
namehash, _ := starlark.String(e.name).Hash()
|
||||||
|
x = x ^ 3*namehash
|
||||||
|
y, err := e.value.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
x = x ^ y*m
|
||||||
|
m += 7349
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
func (s *Struct) Freeze() {
|
||||||
|
if !s.frozen {
|
||||||
|
s.frozen = true
|
||||||
|
for _, e := range s.entries {
|
||||||
|
e.value.Freeze()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Struct) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
|
||||||
|
if y, ok := y.(*Struct); ok && op == syntax.PLUS {
|
||||||
|
if side == starlark.Right {
|
||||||
|
x, y = y, x
|
||||||
|
}
|
||||||
|
|
||||||
|
if eq, err := starlark.Equal(x.constructor, y.constructor); err != nil {
|
||||||
|
return nil, fmt.Errorf("in %s + %s: error comparing constructors: %v",
|
||||||
|
x.constructor, y.constructor, err)
|
||||||
|
} else if !eq {
|
||||||
|
return nil, fmt.Errorf("cannot add structs of different constructors: %s + %s",
|
||||||
|
x.constructor, y.constructor)
|
||||||
|
}
|
||||||
|
|
||||||
|
z := make(starlark.StringDict, x.len()+y.len())
|
||||||
|
for _, e := range x.entries {
|
||||||
|
z[e.name] = e.value
|
||||||
|
}
|
||||||
|
for _, e := range y.entries {
|
||||||
|
z[e.name] = e.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return FromStringDict(x.constructor, z), nil
|
||||||
|
}
|
||||||
|
return nil, nil // unhandled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attr returns the value of the specified field.
|
||||||
|
func (s *Struct) Attr(name string) (starlark.Value, error) {
|
||||||
|
// Binary search the entries.
|
||||||
|
// This implementation is a specialization of
|
||||||
|
// sort.Search that avoids dynamic dispatch.
|
||||||
|
n := len(s.entries)
|
||||||
|
i, j := 0, n
|
||||||
|
for i < j {
|
||||||
|
h := int(uint(i+j) >> 1)
|
||||||
|
if s.entries[h].name < name {
|
||||||
|
i = h + 1
|
||||||
|
} else {
|
||||||
|
j = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i < n && s.entries[i].name == name {
|
||||||
|
return s.entries[i].value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var ctor string
|
||||||
|
if s.constructor != Default {
|
||||||
|
ctor = s.constructor.String() + " "
|
||||||
|
}
|
||||||
|
return nil, starlark.NoSuchAttrError(
|
||||||
|
fmt.Sprintf("%sstruct has no .%s attribute", ctor, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) len() int { return len(s.entries) }
|
||||||
|
|
||||||
|
// AttrNames returns a new sorted list of the struct fields.
|
||||||
|
func (s *Struct) AttrNames() []string {
|
||||||
|
names := make([]string, len(s.entries))
|
||||||
|
for i, e := range s.entries {
|
||||||
|
names[i] = e.name
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Struct) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) {
|
||||||
|
y := y_.(*Struct)
|
||||||
|
switch op {
|
||||||
|
case syntax.EQL:
|
||||||
|
return structsEqual(x, y, depth)
|
||||||
|
case syntax.NEQ:
|
||||||
|
eq, err := structsEqual(x, y, depth)
|
||||||
|
return !eq, err
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func structsEqual(x, y *Struct, depth int) (bool, error) {
|
||||||
|
if x.len() != y.len() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if eq, err := starlark.Equal(x.constructor, y.constructor); err != nil {
|
||||||
|
return false, fmt.Errorf("error comparing struct constructors %v and %v: %v",
|
||||||
|
x.constructor, y.constructor, err)
|
||||||
|
} else if !eq {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, n := 0, x.len(); i < n; i++ {
|
||||||
|
if x.entries[i].name != y.entries[i].name {
|
||||||
|
return false, nil
|
||||||
|
} else if eq, err := starlark.EqualDepth(x.entries[i].value, y.entries[i].value, depth-1); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !eq {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
129
vendor/go.starlark.net/syntax/grammar.txt
generated
vendored
Normal file
129
vendor/go.starlark.net/syntax/grammar.txt
generated
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
|
||||||
|
Grammar of Starlark
|
||||||
|
==================
|
||||||
|
|
||||||
|
File = {Statement | newline} eof .
|
||||||
|
|
||||||
|
Statement = DefStmt | IfStmt | ForStmt | WhileStmt | SimpleStmt .
|
||||||
|
|
||||||
|
DefStmt = 'def' identifier '(' [Parameters [',']] ')' ':' Suite .
|
||||||
|
|
||||||
|
Parameters = Parameter {',' Parameter}.
|
||||||
|
|
||||||
|
Parameter = identifier | identifier '=' Test | '*' | '*' identifier | '**' identifier .
|
||||||
|
|
||||||
|
IfStmt = 'if' Test ':' Suite {'elif' Test ':' Suite} ['else' ':' Suite] .
|
||||||
|
|
||||||
|
ForStmt = 'for' LoopVariables 'in' Expression ':' Suite .
|
||||||
|
|
||||||
|
WhileStmt = 'while' Test ':' Suite .
|
||||||
|
|
||||||
|
Suite = [newline indent {Statement} outdent] | SimpleStmt .
|
||||||
|
|
||||||
|
SimpleStmt = SmallStmt {';' SmallStmt} [';'] '\n' .
|
||||||
|
# NOTE: '\n' optional at EOF
|
||||||
|
|
||||||
|
SmallStmt = ReturnStmt
|
||||||
|
| BreakStmt | ContinueStmt | PassStmt
|
||||||
|
| AssignStmt
|
||||||
|
| ExprStmt
|
||||||
|
| LoadStmt
|
||||||
|
.
|
||||||
|
|
||||||
|
ReturnStmt = 'return' [Expression] .
|
||||||
|
BreakStmt = 'break' .
|
||||||
|
ContinueStmt = 'continue' .
|
||||||
|
PassStmt = 'pass' .
|
||||||
|
AssignStmt = Expression ('=' | '+=' | '-=' | '*=' | '/=' | '//=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=') Expression .
|
||||||
|
ExprStmt = Expression .
|
||||||
|
|
||||||
|
LoadStmt = 'load' '(' string {',' [identifier '='] string} [','] ')' .
|
||||||
|
|
||||||
|
Test = LambdaExpr
|
||||||
|
| IfExpr
|
||||||
|
| PrimaryExpr
|
||||||
|
| UnaryExpr
|
||||||
|
| BinaryExpr
|
||||||
|
.
|
||||||
|
|
||||||
|
LambdaExpr = 'lambda' [Parameters] ':' Test .
|
||||||
|
|
||||||
|
IfExpr = Test 'if' Test 'else' Test .
|
||||||
|
|
||||||
|
PrimaryExpr = Operand
|
||||||
|
| PrimaryExpr DotSuffix
|
||||||
|
| PrimaryExpr CallSuffix
|
||||||
|
| PrimaryExpr SliceSuffix
|
||||||
|
.
|
||||||
|
|
||||||
|
Operand = identifier
|
||||||
|
| int | float | string
|
||||||
|
| ListExpr | ListComp
|
||||||
|
| DictExpr | DictComp
|
||||||
|
| '(' [Expression [',']] ')'
|
||||||
|
| ('-' | '+') PrimaryExpr
|
||||||
|
.
|
||||||
|
|
||||||
|
DotSuffix = '.' identifier .
|
||||||
|
CallSuffix = '(' [Arguments [',']] ')' .
|
||||||
|
SliceSuffix = '[' [Expression] [':' Test [':' Test]] ']' .
|
||||||
|
|
||||||
|
Arguments = Argument {',' Argument} .
|
||||||
|
Argument = Test | identifier '=' Test | '*' Test | '**' Test .
|
||||||
|
|
||||||
|
ListExpr = '[' [Expression [',']] ']' .
|
||||||
|
ListComp = '[' Test {CompClause} ']'.
|
||||||
|
|
||||||
|
DictExpr = '{' [Entries [',']] '}' .
|
||||||
|
DictComp = '{' Entry {CompClause} '}' .
|
||||||
|
Entries = Entry {',' Entry} .
|
||||||
|
Entry = Test ':' Test .
|
||||||
|
|
||||||
|
CompClause = 'for' LoopVariables 'in' Test | 'if' Test .
|
||||||
|
|
||||||
|
UnaryExpr = 'not' Test .
|
||||||
|
|
||||||
|
BinaryExpr = Test {Binop Test} .
|
||||||
|
|
||||||
|
Binop = 'or'
|
||||||
|
| 'and'
|
||||||
|
| '==' | '!=' | '<' | '>' | '<=' | '>=' | 'in' | 'not' 'in'
|
||||||
|
| '|'
|
||||||
|
| '^'
|
||||||
|
| '&'
|
||||||
|
| '-' | '+'
|
||||||
|
| '*' | '%' | '/' | '//'
|
||||||
|
.
|
||||||
|
|
||||||
|
Expression = Test {',' Test} .
|
||||||
|
# NOTE: trailing comma permitted only when within [...] or (...).
|
||||||
|
|
||||||
|
LoopVariables = PrimaryExpr {',' PrimaryExpr} .
|
||||||
|
|
||||||
|
|
||||||
|
# Notation (similar to Go spec):
|
||||||
|
- lowercase and 'quoted' items are lexical tokens.
|
||||||
|
- Capitalized names denote grammar productions.
|
||||||
|
- (...) implies grouping
|
||||||
|
- x | y means either x or y.
|
||||||
|
- [x] means x is optional
|
||||||
|
- {x} means x is repeated zero or more times
|
||||||
|
- The end of each declaration is marked with a period.
|
||||||
|
|
||||||
|
# Tokens
|
||||||
|
- spaces: newline, eof, indent, outdent.
|
||||||
|
- identifier.
|
||||||
|
- literals: string, int, float.
|
||||||
|
- plus all quoted tokens such as '+=', 'return'.
|
||||||
|
|
||||||
|
# Notes:
|
||||||
|
- Ambiguity is resolved using operator precedence.
|
||||||
|
- The grammar does not enforce the legal order of params and args,
|
||||||
|
nor that the first compclause must be a 'for'.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
- explain how the lexer generates indent, outdent, and newline tokens.
|
||||||
|
- why is unary NOT separated from unary - and +?
|
||||||
|
- the grammar is (mostly) in LL(1) style so, for example,
|
||||||
|
dot expressions are formed suffixes, not complete expressions,
|
||||||
|
which makes the spec harder to read. Reorganize into non-LL(1) form?
|
||||||
63
vendor/go.starlark.net/syntax/options.go
generated
vendored
Normal file
63
vendor/go.starlark.net/syntax/options.go
generated
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2023 The Bazel 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 syntax
|
||||||
|
|
||||||
|
import _ "unsafe" // for linkname
|
||||||
|
|
||||||
|
// FileOptions specifies various per-file options that affect static
|
||||||
|
// aspects of an individual file such as parsing, name resolution, and
|
||||||
|
// code generation. (Options that affect global dynamics are typically
|
||||||
|
// controlled through [go.starlark.net/starlark.Thread].)
|
||||||
|
//
|
||||||
|
// The zero value of FileOptions is the default behavior.
|
||||||
|
//
|
||||||
|
// Many functions in this package come in two versions: the legacy
|
||||||
|
// standalone function (such as [Parse]) uses [LegacyFileOptions],
|
||||||
|
// whereas the more recent method (such as [FileOptions.Parse]) honors the
|
||||||
|
// provided options. The second form is preferred. In other packages,
|
||||||
|
// the modern version is a standalone function with a leading
|
||||||
|
// FileOptions parameter and the name suffix "Options", such as
|
||||||
|
// [go.starlark.net/starlark.ExecFileOptions].
|
||||||
|
type FileOptions struct {
|
||||||
|
// resolver
|
||||||
|
Set bool // allow references to the 'set' built-in function
|
||||||
|
While bool // allow 'while' statements
|
||||||
|
TopLevelControl bool // allow if/for/while statements at top-level
|
||||||
|
GlobalReassign bool // allow reassignment to top-level names
|
||||||
|
LoadBindsGlobally bool // load creates global not file-local bindings (deprecated)
|
||||||
|
|
||||||
|
// compiler
|
||||||
|
Recursion bool // disable recursion check for functions in this file
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): provide a canonical flag parser for FileOptions.
|
||||||
|
// (And use it in the testdata "options:" strings.)
|
||||||
|
|
||||||
|
// LegacyFileOptions returns a new FileOptions containing the current
|
||||||
|
// values of the resolver package's legacy global variables such as
|
||||||
|
// [resolve.AllowRecursion], etc.
|
||||||
|
// These variables may be associated with command-line flags.
|
||||||
|
func LegacyFileOptions() *FileOptions {
|
||||||
|
return &FileOptions{
|
||||||
|
Set: resolverAllowSet,
|
||||||
|
While: resolverAllowGlobalReassign,
|
||||||
|
TopLevelControl: resolverAllowGlobalReassign,
|
||||||
|
GlobalReassign: resolverAllowGlobalReassign,
|
||||||
|
Recursion: resolverAllowRecursion,
|
||||||
|
LoadBindsGlobally: resolverLoadBindsGlobally,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access resolver (legacy) flags, if they are linked in; false otherwise.
|
||||||
|
var (
|
||||||
|
//go:linkname resolverAllowSet go.starlark.net/resolve.AllowSet
|
||||||
|
resolverAllowSet bool
|
||||||
|
//go:linkname resolverAllowGlobalReassign go.starlark.net/resolve.AllowGlobalReassign
|
||||||
|
resolverAllowGlobalReassign bool
|
||||||
|
//go:linkname resolverAllowRecursion go.starlark.net/resolve.AllowRecursion
|
||||||
|
resolverAllowRecursion bool
|
||||||
|
//go:linkname resolverLoadBindsGlobally go.starlark.net/resolve.LoadBindsGlobally
|
||||||
|
resolverLoadBindsGlobally bool
|
||||||
|
)
|
||||||
1062
vendor/go.starlark.net/syntax/parse.go
generated
vendored
Normal file
1062
vendor/go.starlark.net/syntax/parse.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
309
vendor/go.starlark.net/syntax/quote.go
generated
vendored
Normal file
309
vendor/go.starlark.net/syntax/quote.go
generated
vendored
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
// Copyright 2017 The Bazel 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 syntax
|
||||||
|
|
||||||
|
// Starlark quoted string utilities.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// unesc maps single-letter chars following \ to their actual values.
|
||||||
|
var unesc = [256]byte{
|
||||||
|
'a': '\a',
|
||||||
|
'b': '\b',
|
||||||
|
'f': '\f',
|
||||||
|
'n': '\n',
|
||||||
|
'r': '\r',
|
||||||
|
't': '\t',
|
||||||
|
'v': '\v',
|
||||||
|
'\\': '\\',
|
||||||
|
'\'': '\'',
|
||||||
|
'"': '"',
|
||||||
|
}
|
||||||
|
|
||||||
|
// esc maps escape-worthy bytes to the char that should follow \.
|
||||||
|
var esc = [256]byte{
|
||||||
|
'\a': 'a',
|
||||||
|
'\b': 'b',
|
||||||
|
'\f': 'f',
|
||||||
|
'\n': 'n',
|
||||||
|
'\r': 'r',
|
||||||
|
'\t': 't',
|
||||||
|
'\v': 'v',
|
||||||
|
'\\': '\\',
|
||||||
|
'\'': '\'',
|
||||||
|
'"': '"',
|
||||||
|
}
|
||||||
|
|
||||||
|
// unquote unquotes the quoted string, returning the actual
|
||||||
|
// string value, whether the original was triple-quoted,
|
||||||
|
// whether it was a byte string, and an error describing invalid input.
|
||||||
|
func unquote(quoted string) (s string, triple, isByte bool, err error) {
|
||||||
|
// Check for raw prefix: means don't interpret the inner \.
|
||||||
|
raw := false
|
||||||
|
if strings.HasPrefix(quoted, "r") {
|
||||||
|
raw = true
|
||||||
|
quoted = quoted[1:]
|
||||||
|
}
|
||||||
|
// Check for bytes prefix.
|
||||||
|
if strings.HasPrefix(quoted, "b") {
|
||||||
|
isByte = true
|
||||||
|
quoted = quoted[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(quoted) < 2 {
|
||||||
|
err = fmt.Errorf("string literal too short")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if quoted[0] != '"' && quoted[0] != '\'' || quoted[0] != quoted[len(quoted)-1] {
|
||||||
|
err = fmt.Errorf("string literal has invalid quotes")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for triple quoted string.
|
||||||
|
quote := quoted[0]
|
||||||
|
if len(quoted) >= 6 && quoted[1] == quote && quoted[2] == quote && quoted[:3] == quoted[len(quoted)-3:] {
|
||||||
|
triple = true
|
||||||
|
quoted = quoted[3 : len(quoted)-3]
|
||||||
|
} else {
|
||||||
|
quoted = quoted[1 : len(quoted)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now quoted is the quoted data, but no quotes.
|
||||||
|
// If we're in raw mode or there are no escapes or
|
||||||
|
// carriage returns, we're done.
|
||||||
|
var unquoteChars string
|
||||||
|
if raw {
|
||||||
|
unquoteChars = "\r"
|
||||||
|
} else {
|
||||||
|
unquoteChars = "\\\r"
|
||||||
|
}
|
||||||
|
if !strings.ContainsAny(quoted, unquoteChars) {
|
||||||
|
s = quoted
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise process quoted string.
|
||||||
|
// Each iteration processes one escape sequence along with the
|
||||||
|
// plain text leading up to it.
|
||||||
|
buf := new(strings.Builder)
|
||||||
|
for {
|
||||||
|
// Remove prefix before escape sequence.
|
||||||
|
i := strings.IndexAny(quoted, unquoteChars)
|
||||||
|
if i < 0 {
|
||||||
|
i = len(quoted)
|
||||||
|
}
|
||||||
|
buf.WriteString(quoted[:i])
|
||||||
|
quoted = quoted[i:]
|
||||||
|
|
||||||
|
if len(quoted) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process carriage return.
|
||||||
|
if quoted[0] == '\r' {
|
||||||
|
buf.WriteByte('\n')
|
||||||
|
if len(quoted) > 1 && quoted[1] == '\n' {
|
||||||
|
quoted = quoted[2:]
|
||||||
|
} else {
|
||||||
|
quoted = quoted[1:]
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process escape sequence.
|
||||||
|
if len(quoted) == 1 {
|
||||||
|
err = fmt.Errorf(`truncated escape sequence \`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch quoted[1] {
|
||||||
|
default:
|
||||||
|
// In Starlark, like Go, a backslash must escape something.
|
||||||
|
// (Python still treats unnecessary backslashes literally,
|
||||||
|
// but since 3.6 has emitted a deprecation warning.)
|
||||||
|
err = fmt.Errorf("invalid escape sequence \\%c", quoted[1])
|
||||||
|
return
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
// Ignore the escape and the line break.
|
||||||
|
quoted = quoted[2:]
|
||||||
|
|
||||||
|
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"':
|
||||||
|
// One-char escape.
|
||||||
|
// Escapes are allowed for both kinds of quotation
|
||||||
|
// mark, not just the kind in use.
|
||||||
|
buf.WriteByte(unesc[quoted[1]])
|
||||||
|
quoted = quoted[2:]
|
||||||
|
|
||||||
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
|
// Octal escape, up to 3 digits, \OOO.
|
||||||
|
n := int(quoted[1] - '0')
|
||||||
|
quoted = quoted[2:]
|
||||||
|
for i := 1; i < 3; i++ {
|
||||||
|
if len(quoted) == 0 || quoted[0] < '0' || '7' < quoted[0] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
n = n*8 + int(quoted[0]-'0')
|
||||||
|
quoted = quoted[1:]
|
||||||
|
}
|
||||||
|
if !isByte && n > 127 {
|
||||||
|
err = fmt.Errorf(`non-ASCII octal escape \%o (use \u%04X for the UTF-8 encoding of U+%04X)`, n, n, n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n >= 256 {
|
||||||
|
// NOTE: Python silently discards the high bit,
|
||||||
|
// so that '\541' == '\141' == 'a'.
|
||||||
|
// Let's see if we can avoid doing that in BUILD files.
|
||||||
|
err = fmt.Errorf(`invalid escape sequence \%03o`, n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buf.WriteByte(byte(n))
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
// Hexadecimal escape, exactly 2 digits, \xXX. [0-127]
|
||||||
|
if len(quoted) < 4 {
|
||||||
|
err = fmt.Errorf(`truncated escape sequence %s`, quoted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n, err1 := strconv.ParseUint(quoted[2:4], 16, 0)
|
||||||
|
if err1 != nil {
|
||||||
|
err = fmt.Errorf(`invalid escape sequence %s`, quoted[:4])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !isByte && n > 127 {
|
||||||
|
err = fmt.Errorf(`non-ASCII hex escape %s (use \u%04X for the UTF-8 encoding of U+%04X)`,
|
||||||
|
quoted[:4], n, n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buf.WriteByte(byte(n))
|
||||||
|
quoted = quoted[4:]
|
||||||
|
|
||||||
|
case 'u', 'U':
|
||||||
|
// Unicode code point, 4 (\uXXXX) or 8 (\UXXXXXXXX) hex digits.
|
||||||
|
sz := 6
|
||||||
|
if quoted[1] == 'U' {
|
||||||
|
sz = 10
|
||||||
|
}
|
||||||
|
if len(quoted) < sz {
|
||||||
|
err = fmt.Errorf(`truncated escape sequence %s`, quoted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n, err1 := strconv.ParseUint(quoted[2:sz], 16, 0)
|
||||||
|
if err1 != nil {
|
||||||
|
err = fmt.Errorf(`invalid escape sequence %s`, quoted[:sz])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > unicode.MaxRune {
|
||||||
|
err = fmt.Errorf(`code point out of range: %s (max \U%08x)`,
|
||||||
|
quoted[:sz], n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// As in Go, surrogates are disallowed.
|
||||||
|
if 0xD800 <= n && n < 0xE000 {
|
||||||
|
err = fmt.Errorf(`invalid Unicode code point U+%04X`, n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buf.WriteRune(rune(n))
|
||||||
|
quoted = quoted[sz:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s = buf.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexByte returns the index of the first instance of b in s, or else -1.
|
||||||
|
func indexByte(s string, b byte) int {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] == b {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quote returns a Starlark literal that denotes s.
|
||||||
|
// If b, it returns a bytes literal.
|
||||||
|
func Quote(s string, b bool) string {
|
||||||
|
const hex = "0123456789abcdef"
|
||||||
|
var runeTmp [utf8.UTFMax]byte
|
||||||
|
|
||||||
|
buf := make([]byte, 0, 3*len(s)/2)
|
||||||
|
if b {
|
||||||
|
buf = append(buf, 'b')
|
||||||
|
}
|
||||||
|
buf = append(buf, '"')
|
||||||
|
for width := 0; len(s) > 0; s = s[width:] {
|
||||||
|
r := rune(s[0])
|
||||||
|
width = 1
|
||||||
|
if r >= utf8.RuneSelf {
|
||||||
|
r, width = utf8.DecodeRuneInString(s)
|
||||||
|
}
|
||||||
|
if width == 1 && r == utf8.RuneError {
|
||||||
|
// String (!b) literals accept \xXX escapes only for ASCII,
|
||||||
|
// but we must use them here to represent invalid bytes.
|
||||||
|
// The result is not a legal literal.
|
||||||
|
buf = append(buf, `\x`...)
|
||||||
|
buf = append(buf, hex[s[0]>>4])
|
||||||
|
buf = append(buf, hex[s[0]&0xF])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if r == '"' || r == '\\' { // always backslashed
|
||||||
|
buf = append(buf, '\\')
|
||||||
|
buf = append(buf, byte(r))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strconv.IsPrint(r) {
|
||||||
|
n := utf8.EncodeRune(runeTmp[:], r)
|
||||||
|
buf = append(buf, runeTmp[:n]...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch r {
|
||||||
|
case '\a':
|
||||||
|
buf = append(buf, `\a`...)
|
||||||
|
case '\b':
|
||||||
|
buf = append(buf, `\b`...)
|
||||||
|
case '\f':
|
||||||
|
buf = append(buf, `\f`...)
|
||||||
|
case '\n':
|
||||||
|
buf = append(buf, `\n`...)
|
||||||
|
case '\r':
|
||||||
|
buf = append(buf, `\r`...)
|
||||||
|
case '\t':
|
||||||
|
buf = append(buf, `\t`...)
|
||||||
|
case '\v':
|
||||||
|
buf = append(buf, `\v`...)
|
||||||
|
default:
|
||||||
|
switch {
|
||||||
|
case r < ' ' || r == 0x7f:
|
||||||
|
buf = append(buf, `\x`...)
|
||||||
|
buf = append(buf, hex[byte(r)>>4])
|
||||||
|
buf = append(buf, hex[byte(r)&0xF])
|
||||||
|
case r > utf8.MaxRune:
|
||||||
|
r = 0xFFFD
|
||||||
|
fallthrough
|
||||||
|
case r < 0x10000:
|
||||||
|
buf = append(buf, `\u`...)
|
||||||
|
for s := 12; s >= 0; s -= 4 {
|
||||||
|
buf = append(buf, hex[r>>uint(s)&0xF])
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
buf = append(buf, `\U`...)
|
||||||
|
for s := 28; s >= 0; s -= 4 {
|
||||||
|
buf = append(buf, hex[r>>uint(s)&0xF])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf = append(buf, '"')
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
1164
vendor/go.starlark.net/syntax/scan.go
generated
vendored
Normal file
1164
vendor/go.starlark.net/syntax/scan.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
529
vendor/go.starlark.net/syntax/syntax.go
generated
vendored
Normal file
529
vendor/go.starlark.net/syntax/syntax.go
generated
vendored
Normal file
|
|
@ -0,0 +1,529 @@
|
||||||
|
// Copyright 2017 The Bazel 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 syntax provides a Starlark parser and abstract syntax tree.
|
||||||
|
package syntax // import "go.starlark.net/syntax"
|
||||||
|
|
||||||
|
// A Node is a node in a Starlark syntax tree.
|
||||||
|
type Node interface {
|
||||||
|
// Span returns the start and end position of the expression.
|
||||||
|
Span() (start, end Position)
|
||||||
|
|
||||||
|
// Comments returns the comments associated with this node.
|
||||||
|
// It returns nil if RetainComments was not specified during parsing,
|
||||||
|
// or if AllocComments was not called.
|
||||||
|
Comments() *Comments
|
||||||
|
|
||||||
|
// AllocComments allocates a new Comments node if there was none.
|
||||||
|
// This makes possible to add new comments using Comments() method.
|
||||||
|
AllocComments()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Comment represents a single # comment.
|
||||||
|
type Comment struct {
|
||||||
|
Start Position
|
||||||
|
Text string // without trailing newline
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments collects the comments associated with an expression.
|
||||||
|
type Comments struct {
|
||||||
|
Before []Comment // whole-line comments before this expression
|
||||||
|
Suffix []Comment // end-of-line comments after this expression (up to 1)
|
||||||
|
|
||||||
|
// For top-level expressions only, After lists whole-line
|
||||||
|
// comments following the expression.
|
||||||
|
After []Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
// A commentsRef is a possibly-nil reference to a set of comments.
|
||||||
|
// A commentsRef is embedded in each type of syntax node,
|
||||||
|
// and provides its Comments and AllocComments methods.
|
||||||
|
type commentsRef struct{ ref *Comments }
|
||||||
|
|
||||||
|
// Comments returns the comments associated with a syntax node,
|
||||||
|
// or nil if AllocComments has not yet been called.
|
||||||
|
func (cr commentsRef) Comments() *Comments { return cr.ref }
|
||||||
|
|
||||||
|
// AllocComments enables comments to be associated with a syntax node.
|
||||||
|
func (cr *commentsRef) AllocComments() {
|
||||||
|
if cr.ref == nil {
|
||||||
|
cr.ref = new(Comments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start returns the start position of the expression.
|
||||||
|
func Start(n Node) Position {
|
||||||
|
start, _ := n.Span()
|
||||||
|
return start
|
||||||
|
}
|
||||||
|
|
||||||
|
// End returns the end position of the expression.
|
||||||
|
func End(n Node) Position {
|
||||||
|
_, end := n.Span()
|
||||||
|
return end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A File represents a Starlark file.
|
||||||
|
type File struct {
|
||||||
|
commentsRef
|
||||||
|
Path string
|
||||||
|
Stmts []Stmt
|
||||||
|
|
||||||
|
Module interface{} // a *resolve.Module, set by resolver
|
||||||
|
Options *FileOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *File) Span() (start, end Position) {
|
||||||
|
if len(x.Stmts) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
start, _ = x.Stmts[0].Span()
|
||||||
|
_, end = x.Stmts[len(x.Stmts)-1].Span()
|
||||||
|
return start, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Stmt is a Starlark statement.
|
||||||
|
type Stmt interface {
|
||||||
|
Node
|
||||||
|
stmt()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*AssignStmt) stmt() {}
|
||||||
|
func (*BranchStmt) stmt() {}
|
||||||
|
func (*DefStmt) stmt() {}
|
||||||
|
func (*ExprStmt) stmt() {}
|
||||||
|
func (*ForStmt) stmt() {}
|
||||||
|
func (*WhileStmt) stmt() {}
|
||||||
|
func (*IfStmt) stmt() {}
|
||||||
|
func (*LoadStmt) stmt() {}
|
||||||
|
func (*ReturnStmt) stmt() {}
|
||||||
|
|
||||||
|
// An AssignStmt represents an assignment:
|
||||||
|
//
|
||||||
|
// x = 0
|
||||||
|
// x, y = y, x
|
||||||
|
// x += 1
|
||||||
|
type AssignStmt struct {
|
||||||
|
commentsRef
|
||||||
|
OpPos Position
|
||||||
|
Op Token // = EQ | {PLUS,MINUS,STAR,PERCENT}_EQ
|
||||||
|
LHS Expr
|
||||||
|
RHS Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *AssignStmt) Span() (start, end Position) {
|
||||||
|
start, _ = x.LHS.Span()
|
||||||
|
_, end = x.RHS.Span()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// A DefStmt represents a function definition.
|
||||||
|
type DefStmt struct {
|
||||||
|
commentsRef
|
||||||
|
Def Position
|
||||||
|
Name *Ident
|
||||||
|
Lparen Position
|
||||||
|
Params []Expr // param = ident | ident=expr | * | *ident | **ident
|
||||||
|
Rparen Position
|
||||||
|
Body []Stmt
|
||||||
|
|
||||||
|
Function interface{} // a *resolve.Function, set by resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DefStmt) Span() (start, end Position) {
|
||||||
|
_, end = x.Body[len(x.Body)-1].Span()
|
||||||
|
return x.Def, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// An ExprStmt is an expression evaluated for side effects.
|
||||||
|
type ExprStmt struct {
|
||||||
|
commentsRef
|
||||||
|
X Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ExprStmt) Span() (start, end Position) {
|
||||||
|
return x.X.Span()
|
||||||
|
}
|
||||||
|
|
||||||
|
// An IfStmt is a conditional: If Cond: True; else: False.
|
||||||
|
// 'elseif' is desugared into a chain of IfStmts.
|
||||||
|
type IfStmt struct {
|
||||||
|
commentsRef
|
||||||
|
If Position // IF or ELIF
|
||||||
|
Cond Expr
|
||||||
|
True []Stmt
|
||||||
|
ElsePos Position // ELSE or ELIF
|
||||||
|
False []Stmt // optional
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IfStmt) Span() (start, end Position) {
|
||||||
|
body := x.False
|
||||||
|
if body == nil {
|
||||||
|
body = x.True
|
||||||
|
}
|
||||||
|
_, end = body[len(body)-1].Span()
|
||||||
|
return x.If, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A LoadStmt loads another module and binds names from it:
|
||||||
|
// load(Module, "x", y="foo").
|
||||||
|
//
|
||||||
|
// The AST is slightly unfaithful to the concrete syntax here because
|
||||||
|
// Starlark's load statement, so that it can be implemented in Python,
|
||||||
|
// binds some names (like y above) with an identifier and some (like x)
|
||||||
|
// without. For consistency we create fake identifiers for all the
|
||||||
|
// strings.
|
||||||
|
type LoadStmt struct {
|
||||||
|
commentsRef
|
||||||
|
Load Position
|
||||||
|
Module *Literal // a string
|
||||||
|
From []*Ident // name defined in loading module
|
||||||
|
To []*Ident // name in loaded module
|
||||||
|
Rparen Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LoadStmt) Span() (start, end Position) {
|
||||||
|
return x.Load, x.Rparen
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModuleName returns the name of the module loaded by this statement.
|
||||||
|
func (x *LoadStmt) ModuleName() string { return x.Module.Value.(string) }
|
||||||
|
|
||||||
|
// A BranchStmt changes the flow of control: break, continue, pass.
|
||||||
|
type BranchStmt struct {
|
||||||
|
commentsRef
|
||||||
|
Token Token // = BREAK | CONTINUE | PASS
|
||||||
|
TokenPos Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *BranchStmt) Span() (start, end Position) {
|
||||||
|
return x.TokenPos, x.TokenPos.add(x.Token.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ReturnStmt returns from a function.
|
||||||
|
type ReturnStmt struct {
|
||||||
|
commentsRef
|
||||||
|
Return Position
|
||||||
|
Result Expr // may be nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ReturnStmt) Span() (start, end Position) {
|
||||||
|
if x.Result == nil {
|
||||||
|
return x.Return, x.Return.add("return")
|
||||||
|
}
|
||||||
|
_, end = x.Result.Span()
|
||||||
|
return x.Return, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Expr is a Starlark expression.
|
||||||
|
type Expr interface {
|
||||||
|
Node
|
||||||
|
expr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*BinaryExpr) expr() {}
|
||||||
|
func (*CallExpr) expr() {}
|
||||||
|
func (*Comprehension) expr() {}
|
||||||
|
func (*CondExpr) expr() {}
|
||||||
|
func (*DictEntry) expr() {}
|
||||||
|
func (*DictExpr) expr() {}
|
||||||
|
func (*DotExpr) expr() {}
|
||||||
|
func (*Ident) expr() {}
|
||||||
|
func (*IndexExpr) expr() {}
|
||||||
|
func (*LambdaExpr) expr() {}
|
||||||
|
func (*ListExpr) expr() {}
|
||||||
|
func (*Literal) expr() {}
|
||||||
|
func (*ParenExpr) expr() {}
|
||||||
|
func (*SliceExpr) expr() {}
|
||||||
|
func (*TupleExpr) expr() {}
|
||||||
|
func (*UnaryExpr) expr() {}
|
||||||
|
|
||||||
|
// An Ident represents an identifier.
|
||||||
|
type Ident struct {
|
||||||
|
commentsRef
|
||||||
|
NamePos Position
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Binding interface{} // a *resolver.Binding, set by resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Ident) Span() (start, end Position) {
|
||||||
|
return x.NamePos, x.NamePos.add(x.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Literal represents a literal string or number.
|
||||||
|
type Literal struct {
|
||||||
|
commentsRef
|
||||||
|
Token Token // = STRING | BYTES | INT | FLOAT
|
||||||
|
TokenPos Position
|
||||||
|
Raw string // uninterpreted text
|
||||||
|
Value interface{} // = string | int64 | *big.Int | float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Literal) Span() (start, end Position) {
|
||||||
|
return x.TokenPos, x.TokenPos.add(x.Raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ParenExpr represents a parenthesized expression: (X).
|
||||||
|
type ParenExpr struct {
|
||||||
|
commentsRef
|
||||||
|
Lparen Position
|
||||||
|
X Expr
|
||||||
|
Rparen Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ParenExpr) Span() (start, end Position) {
|
||||||
|
return x.Lparen, x.Rparen.add(")")
|
||||||
|
}
|
||||||
|
|
||||||
|
// A CallExpr represents a function call expression: Fn(Args).
|
||||||
|
type CallExpr struct {
|
||||||
|
commentsRef
|
||||||
|
Fn Expr
|
||||||
|
Lparen Position
|
||||||
|
Args []Expr // arg = expr | ident=expr | *expr | **expr
|
||||||
|
Rparen Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CallExpr) Span() (start, end Position) {
|
||||||
|
start, _ = x.Fn.Span()
|
||||||
|
return start, x.Rparen.add(")")
|
||||||
|
}
|
||||||
|
|
||||||
|
// A DotExpr represents a field or method selector: X.Name.
|
||||||
|
type DotExpr struct {
|
||||||
|
commentsRef
|
||||||
|
X Expr
|
||||||
|
Dot Position
|
||||||
|
NamePos Position
|
||||||
|
Name *Ident
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DotExpr) Span() (start, end Position) {
|
||||||
|
start, _ = x.X.Span()
|
||||||
|
_, end = x.Name.Span()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Comprehension represents a list or dict comprehension:
|
||||||
|
// [Body for ... if ...] or {Body for ... if ...}
|
||||||
|
type Comprehension struct {
|
||||||
|
commentsRef
|
||||||
|
Curly bool // {x:y for ...} or {x for ...}, not [x for ...]
|
||||||
|
Lbrack Position
|
||||||
|
Body Expr
|
||||||
|
Clauses []Node // = *ForClause | *IfClause
|
||||||
|
Rbrack Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Comprehension) Span() (start, end Position) {
|
||||||
|
return x.Lbrack, x.Rbrack.add("]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ForStmt represents a loop: for Vars in X: Body.
|
||||||
|
type ForStmt struct {
|
||||||
|
commentsRef
|
||||||
|
For Position
|
||||||
|
Vars Expr // name, or tuple of names
|
||||||
|
X Expr
|
||||||
|
Body []Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ForStmt) Span() (start, end Position) {
|
||||||
|
_, end = x.Body[len(x.Body)-1].Span()
|
||||||
|
return x.For, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A WhileStmt represents a while loop: while X: Body.
|
||||||
|
type WhileStmt struct {
|
||||||
|
commentsRef
|
||||||
|
While Position
|
||||||
|
Cond Expr
|
||||||
|
Body []Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *WhileStmt) Span() (start, end Position) {
|
||||||
|
_, end = x.Body[len(x.Body)-1].Span()
|
||||||
|
return x.While, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ForClause represents a for clause in a list comprehension: for Vars in X.
|
||||||
|
type ForClause struct {
|
||||||
|
commentsRef
|
||||||
|
For Position
|
||||||
|
Vars Expr // name, or tuple of names
|
||||||
|
In Position
|
||||||
|
X Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ForClause) Span() (start, end Position) {
|
||||||
|
_, end = x.X.Span()
|
||||||
|
return x.For, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// An IfClause represents an if clause in a list comprehension: if Cond.
|
||||||
|
type IfClause struct {
|
||||||
|
commentsRef
|
||||||
|
If Position
|
||||||
|
Cond Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IfClause) Span() (start, end Position) {
|
||||||
|
_, end = x.Cond.Span()
|
||||||
|
return x.If, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A DictExpr represents a dictionary literal: { List }.
|
||||||
|
type DictExpr struct {
|
||||||
|
commentsRef
|
||||||
|
Lbrace Position
|
||||||
|
List []Expr // all *DictEntrys
|
||||||
|
Rbrace Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DictExpr) Span() (start, end Position) {
|
||||||
|
return x.Lbrace, x.Rbrace.add("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// A DictEntry represents a dictionary entry: Key: Value.
|
||||||
|
// Used only within a DictExpr.
|
||||||
|
type DictEntry struct {
|
||||||
|
commentsRef
|
||||||
|
Key Expr
|
||||||
|
Colon Position
|
||||||
|
Value Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DictEntry) Span() (start, end Position) {
|
||||||
|
start, _ = x.Key.Span()
|
||||||
|
_, end = x.Value.Span()
|
||||||
|
return start, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A LambdaExpr represents an inline function abstraction.
|
||||||
|
type LambdaExpr struct {
|
||||||
|
commentsRef
|
||||||
|
Lambda Position
|
||||||
|
Params []Expr // param = ident | ident=expr | * | *ident | **ident
|
||||||
|
Body Expr
|
||||||
|
|
||||||
|
Function interface{} // a *resolve.Function, set by resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LambdaExpr) Span() (start, end Position) {
|
||||||
|
_, end = x.Body.Span()
|
||||||
|
return x.Lambda, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ListExpr represents a list literal: [ List ].
|
||||||
|
type ListExpr struct {
|
||||||
|
commentsRef
|
||||||
|
Lbrack Position
|
||||||
|
List []Expr
|
||||||
|
Rbrack Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListExpr) Span() (start, end Position) {
|
||||||
|
return x.Lbrack, x.Rbrack.add("]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CondExpr represents the conditional: X if COND else ELSE.
|
||||||
|
type CondExpr struct {
|
||||||
|
commentsRef
|
||||||
|
If Position
|
||||||
|
Cond Expr
|
||||||
|
True Expr
|
||||||
|
ElsePos Position
|
||||||
|
False Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CondExpr) Span() (start, end Position) {
|
||||||
|
start, _ = x.True.Span()
|
||||||
|
_, end = x.False.Span()
|
||||||
|
return start, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A TupleExpr represents a tuple literal: (List).
|
||||||
|
type TupleExpr struct {
|
||||||
|
commentsRef
|
||||||
|
Lparen Position // optional (e.g. in x, y = 0, 1), but required if List is empty
|
||||||
|
List []Expr
|
||||||
|
Rparen Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TupleExpr) Span() (start, end Position) {
|
||||||
|
if x.Lparen.IsValid() {
|
||||||
|
return x.Lparen, x.Rparen
|
||||||
|
} else {
|
||||||
|
return Start(x.List[0]), End(x.List[len(x.List)-1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A UnaryExpr represents a unary expression: Op X.
|
||||||
|
//
|
||||||
|
// As a special case, UnaryOp{Op:Star} may also represent
|
||||||
|
// the star parameter in def f(*args) or def f(*, x).
|
||||||
|
type UnaryExpr struct {
|
||||||
|
commentsRef
|
||||||
|
OpPos Position
|
||||||
|
Op Token
|
||||||
|
X Expr // may be nil if Op==STAR
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UnaryExpr) Span() (start, end Position) {
|
||||||
|
if x.X != nil {
|
||||||
|
_, end = x.X.Span()
|
||||||
|
} else {
|
||||||
|
end = x.OpPos.add("*")
|
||||||
|
}
|
||||||
|
return x.OpPos, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A BinaryExpr represents a binary expression: X Op Y.
|
||||||
|
//
|
||||||
|
// As a special case, BinaryExpr{Op:EQ} may also
|
||||||
|
// represent a named argument in a call f(k=v)
|
||||||
|
// or a named parameter in a function declaration
|
||||||
|
// def f(param=default).
|
||||||
|
type BinaryExpr struct {
|
||||||
|
commentsRef
|
||||||
|
X Expr
|
||||||
|
OpPos Position
|
||||||
|
Op Token
|
||||||
|
Y Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *BinaryExpr) Span() (start, end Position) {
|
||||||
|
start, _ = x.X.Span()
|
||||||
|
_, end = x.Y.Span()
|
||||||
|
return start, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// A SliceExpr represents a slice or substring expression: X[Lo:Hi:Step].
|
||||||
|
type SliceExpr struct {
|
||||||
|
commentsRef
|
||||||
|
X Expr
|
||||||
|
Lbrack Position
|
||||||
|
Lo, Hi, Step Expr // all optional
|
||||||
|
Rbrack Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SliceExpr) Span() (start, end Position) {
|
||||||
|
start, _ = x.X.Span()
|
||||||
|
return start, x.Rbrack
|
||||||
|
}
|
||||||
|
|
||||||
|
// An IndexExpr represents an index expression: X[Y].
|
||||||
|
type IndexExpr struct {
|
||||||
|
commentsRef
|
||||||
|
X Expr
|
||||||
|
Lbrack Position
|
||||||
|
Y Expr
|
||||||
|
Rbrack Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IndexExpr) Span() (start, end Position) {
|
||||||
|
start, _ = x.X.Span()
|
||||||
|
return start, x.Rbrack
|
||||||
|
}
|
||||||
165
vendor/go.starlark.net/syntax/walk.go
generated
vendored
Normal file
165
vendor/go.starlark.net/syntax/walk.go
generated
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
// Copyright 2017 The Bazel 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 syntax
|
||||||
|
|
||||||
|
// Walk traverses a syntax tree in depth-first order.
|
||||||
|
// It starts by calling f(n); n must not be nil.
|
||||||
|
// If f returns true, Walk calls itself
|
||||||
|
// recursively for each non-nil child of n.
|
||||||
|
// Walk then calls f(nil).
|
||||||
|
func Walk(n Node, f func(Node) bool) {
|
||||||
|
if n == nil {
|
||||||
|
panic("nil")
|
||||||
|
}
|
||||||
|
if !f(n) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): opt: order cases using profile data.
|
||||||
|
switch n := n.(type) {
|
||||||
|
case *File:
|
||||||
|
walkStmts(n.Stmts, f)
|
||||||
|
|
||||||
|
case *ExprStmt:
|
||||||
|
Walk(n.X, f)
|
||||||
|
|
||||||
|
case *BranchStmt:
|
||||||
|
// no-op
|
||||||
|
|
||||||
|
case *IfStmt:
|
||||||
|
Walk(n.Cond, f)
|
||||||
|
walkStmts(n.True, f)
|
||||||
|
walkStmts(n.False, f)
|
||||||
|
|
||||||
|
case *AssignStmt:
|
||||||
|
Walk(n.LHS, f)
|
||||||
|
Walk(n.RHS, f)
|
||||||
|
|
||||||
|
case *DefStmt:
|
||||||
|
Walk(n.Name, f)
|
||||||
|
for _, param := range n.Params {
|
||||||
|
Walk(param, f)
|
||||||
|
}
|
||||||
|
walkStmts(n.Body, f)
|
||||||
|
|
||||||
|
case *ForStmt:
|
||||||
|
Walk(n.Vars, f)
|
||||||
|
Walk(n.X, f)
|
||||||
|
walkStmts(n.Body, f)
|
||||||
|
|
||||||
|
case *WhileStmt:
|
||||||
|
Walk(n.Cond, f)
|
||||||
|
walkStmts(n.Body, f)
|
||||||
|
|
||||||
|
case *ReturnStmt:
|
||||||
|
if n.Result != nil {
|
||||||
|
Walk(n.Result, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *LoadStmt:
|
||||||
|
Walk(n.Module, f)
|
||||||
|
for _, from := range n.From {
|
||||||
|
Walk(from, f)
|
||||||
|
}
|
||||||
|
for _, to := range n.To {
|
||||||
|
Walk(to, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *Ident, *Literal:
|
||||||
|
// no-op
|
||||||
|
|
||||||
|
case *ListExpr:
|
||||||
|
for _, x := range n.List {
|
||||||
|
Walk(x, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ParenExpr:
|
||||||
|
Walk(n.X, f)
|
||||||
|
|
||||||
|
case *CondExpr:
|
||||||
|
Walk(n.Cond, f)
|
||||||
|
Walk(n.True, f)
|
||||||
|
Walk(n.False, f)
|
||||||
|
|
||||||
|
case *IndexExpr:
|
||||||
|
Walk(n.X, f)
|
||||||
|
Walk(n.Y, f)
|
||||||
|
|
||||||
|
case *DictEntry:
|
||||||
|
Walk(n.Key, f)
|
||||||
|
Walk(n.Value, f)
|
||||||
|
|
||||||
|
case *SliceExpr:
|
||||||
|
Walk(n.X, f)
|
||||||
|
if n.Lo != nil {
|
||||||
|
Walk(n.Lo, f)
|
||||||
|
}
|
||||||
|
if n.Hi != nil {
|
||||||
|
Walk(n.Hi, f)
|
||||||
|
}
|
||||||
|
if n.Step != nil {
|
||||||
|
Walk(n.Step, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *Comprehension:
|
||||||
|
Walk(n.Body, f)
|
||||||
|
for _, clause := range n.Clauses {
|
||||||
|
Walk(clause, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *IfClause:
|
||||||
|
Walk(n.Cond, f)
|
||||||
|
|
||||||
|
case *ForClause:
|
||||||
|
Walk(n.Vars, f)
|
||||||
|
Walk(n.X, f)
|
||||||
|
|
||||||
|
case *TupleExpr:
|
||||||
|
for _, x := range n.List {
|
||||||
|
Walk(x, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *DictExpr:
|
||||||
|
for _, entry := range n.List {
|
||||||
|
Walk(entry, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *UnaryExpr:
|
||||||
|
if n.X != nil {
|
||||||
|
Walk(n.X, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *BinaryExpr:
|
||||||
|
Walk(n.X, f)
|
||||||
|
Walk(n.Y, f)
|
||||||
|
|
||||||
|
case *DotExpr:
|
||||||
|
Walk(n.X, f)
|
||||||
|
Walk(n.Name, f)
|
||||||
|
|
||||||
|
case *CallExpr:
|
||||||
|
Walk(n.Fn, f)
|
||||||
|
for _, arg := range n.Args {
|
||||||
|
Walk(arg, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *LambdaExpr:
|
||||||
|
for _, param := range n.Params {
|
||||||
|
Walk(param, f)
|
||||||
|
}
|
||||||
|
Walk(n.Body, f)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
f(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkStmts(stmts []Stmt, f func(Node) bool) {
|
||||||
|
for _, stmt := range stmts {
|
||||||
|
Walk(stmt, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
vendor/golang.org/x/sys/AUTHORS
generated
vendored
Normal file
3
vendor/golang.org/x/sys/AUTHORS
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
|
# The master list of authors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/AUTHORS.
|
||||||
3
vendor/golang.org/x/sys/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/golang.org/x/sys/CONTRIBUTORS
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This source code was written by the Go contributors.
|
||||||
|
# The master list of contributors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||||
27
vendor/golang.org/x/sys/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/sys/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
22
vendor/golang.org/x/sys/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/sys/PATENTS
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
||||||
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2020 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 unsafeheader contains header declarations for the Go runtime's
|
||||||
|
// slice and string implementations.
|
||||||
|
//
|
||||||
|
// This package allows x/sys to use types equivalent to
|
||||||
|
// reflect.SliceHeader and reflect.StringHeader without introducing
|
||||||
|
// a dependency on the (relatively heavy) "reflect" package.
|
||||||
|
package unsafeheader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Slice is the runtime representation of a slice.
|
||||||
|
// It cannot be used safely or portably and its representation may change in a later release.
|
||||||
|
type Slice struct {
|
||||||
|
Data unsafe.Pointer
|
||||||
|
Len int
|
||||||
|
Cap int
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is the runtime representation of a string.
|
||||||
|
// It cannot be used safely or portably and its representation may change in a later release.
|
||||||
|
type String struct {
|
||||||
|
Data unsafe.Pointer
|
||||||
|
Len int
|
||||||
|
}
|
||||||
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
Normal file
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
_obj/
|
||||||
|
unix.test
|
||||||
184
vendor/golang.org/x/sys/unix/README.md
generated
vendored
Normal file
184
vendor/golang.org/x/sys/unix/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
# Building `sys/unix`
|
||||||
|
|
||||||
|
The sys/unix package provides access to the raw system call interface of the
|
||||||
|
underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
|
||||||
|
|
||||||
|
Porting Go to a new architecture/OS combination or adding syscalls, types, or
|
||||||
|
constants to an existing architecture/OS pair requires some manual effort;
|
||||||
|
however, there are tools that automate much of the process.
|
||||||
|
|
||||||
|
## Build Systems
|
||||||
|
|
||||||
|
There are currently two ways we generate the necessary files. We are currently
|
||||||
|
migrating the build system to use containers so the builds are reproducible.
|
||||||
|
This is being done on an OS-by-OS basis. Please update this documentation as
|
||||||
|
components of the build system change.
|
||||||
|
|
||||||
|
### Old Build System (currently for `GOOS != "linux"`)
|
||||||
|
|
||||||
|
The old build system generates the Go files based on the C header files
|
||||||
|
present on your system. This means that files
|
||||||
|
for a given GOOS/GOARCH pair must be generated on a system with that OS and
|
||||||
|
architecture. This also means that the generated code can differ from system
|
||||||
|
to system, based on differences in the header files.
|
||||||
|
|
||||||
|
To avoid this, if you are using the old build system, only generate the Go
|
||||||
|
files on an installation with unmodified header files. It is also important to
|
||||||
|
keep track of which version of the OS the files were generated from (ex.
|
||||||
|
Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
|
||||||
|
and have each OS upgrade correspond to a single change.
|
||||||
|
|
||||||
|
To build the files for your current OS and architecture, make sure GOOS and
|
||||||
|
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
|
||||||
|
your specific system. Running `mkall.sh -n` shows the commands that will be run.
|
||||||
|
|
||||||
|
Requirements: bash, go
|
||||||
|
|
||||||
|
### New Build System (currently for `GOOS == "linux"`)
|
||||||
|
|
||||||
|
The new build system uses a Docker container to generate the go files directly
|
||||||
|
from source checkouts of the kernel and various system libraries. This means
|
||||||
|
that on any platform that supports Docker, all the files using the new build
|
||||||
|
system can be generated at once, and generated files will not change based on
|
||||||
|
what the person running the scripts has installed on their computer.
|
||||||
|
|
||||||
|
The OS specific files for the new build system are located in the `${GOOS}`
|
||||||
|
directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
|
||||||
|
the kernel or system library updates, modify the Dockerfile at
|
||||||
|
`${GOOS}/Dockerfile` to checkout the new release of the source.
|
||||||
|
|
||||||
|
To build all the files under the new build system, you must be on an amd64/Linux
|
||||||
|
system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
|
||||||
|
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
|
||||||
|
system. Running `mkall.sh -n` shows the commands that will be run.
|
||||||
|
|
||||||
|
Requirements: bash, go, docker
|
||||||
|
|
||||||
|
## Component files
|
||||||
|
|
||||||
|
This section describes the various files used in the code generation process.
|
||||||
|
It also contains instructions on how to modify these files to add a new
|
||||||
|
architecture/OS or to add additional syscalls, types, or constants. Note that
|
||||||
|
if you are using the new build system, the scripts/programs cannot be called normally.
|
||||||
|
They must be called from within the docker container.
|
||||||
|
|
||||||
|
### asm files
|
||||||
|
|
||||||
|
The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
|
||||||
|
call dispatch. There are three entry points:
|
||||||
|
```
|
||||||
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||||
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||||
|
```
|
||||||
|
The first and second are the standard ones; they differ only in how many
|
||||||
|
arguments can be passed to the kernel. The third is for low-level use by the
|
||||||
|
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
|
||||||
|
let it know that a system call is running.
|
||||||
|
|
||||||
|
When porting Go to a new architecture/OS, this file must be implemented for
|
||||||
|
each GOOS/GOARCH pair.
|
||||||
|
|
||||||
|
### mksysnum
|
||||||
|
|
||||||
|
Mksysnum is a Go program located at `${GOOS}/mksysnum.go` (or `mksysnum_${GOOS}.go`
|
||||||
|
for the old system). This program takes in a list of header files containing the
|
||||||
|
syscall number declarations and parses them to produce the corresponding list of
|
||||||
|
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
|
||||||
|
constants.
|
||||||
|
|
||||||
|
Adding new syscall numbers is mostly done by running the build on a sufficiently
|
||||||
|
new installation of the target OS (or updating the source checkouts for the
|
||||||
|
new build system). However, depending on the OS, you may need to update the
|
||||||
|
parsing in mksysnum.
|
||||||
|
|
||||||
|
### mksyscall.go
|
||||||
|
|
||||||
|
The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
|
||||||
|
hand-written Go files which implement system calls (for unix, the specific OS,
|
||||||
|
or the specific OS/Architecture pair respectively) that need special handling
|
||||||
|
and list `//sys` comments giving prototypes for ones that can be generated.
|
||||||
|
|
||||||
|
The mksyscall.go program takes the `//sys` and `//sysnb` comments and converts
|
||||||
|
them into syscalls. This requires the name of the prototype in the comment to
|
||||||
|
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
|
||||||
|
prototype can be exported (capitalized) or not.
|
||||||
|
|
||||||
|
Adding a new syscall often just requires adding a new `//sys` function prototype
|
||||||
|
with the desired arguments and a capitalized name so it is exported. However, if
|
||||||
|
you want the interface to the syscall to be different, often one will make an
|
||||||
|
unexported `//sys` prototype, and then write a custom wrapper in
|
||||||
|
`syscall_${GOOS}.go`.
|
||||||
|
|
||||||
|
### types files
|
||||||
|
|
||||||
|
For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
|
||||||
|
`types_${GOOS}.go` on the old system). This file includes standard C headers and
|
||||||
|
creates Go type aliases to the corresponding C types. The file is then fed
|
||||||
|
through godef to get the Go compatible definitions. Finally, the generated code
|
||||||
|
is fed though mkpost.go to format the code correctly and remove any hidden or
|
||||||
|
private identifiers. This cleaned-up code is written to
|
||||||
|
`ztypes_${GOOS}_${GOARCH}.go`.
|
||||||
|
|
||||||
|
The hardest part about preparing this file is figuring out which headers to
|
||||||
|
include and which symbols need to be `#define`d to get the actual data
|
||||||
|
structures that pass through to the kernel system calls. Some C libraries
|
||||||
|
preset alternate versions for binary compatibility and translate them on the
|
||||||
|
way in and out of system calls, but there is almost always a `#define` that can
|
||||||
|
get the real ones.
|
||||||
|
See `types_darwin.go` and `linux/types.go` for examples.
|
||||||
|
|
||||||
|
To add a new type, add in the necessary include statement at the top of the
|
||||||
|
file (if it is not already there) and add in a type alias line. Note that if
|
||||||
|
your type is significantly different on different architectures, you may need
|
||||||
|
some `#if/#elif` macros in your include statements.
|
||||||
|
|
||||||
|
### mkerrors.sh
|
||||||
|
|
||||||
|
This script is used to generate the system's various constants. This doesn't
|
||||||
|
just include the error numbers and error strings, but also the signal numbers
|
||||||
|
and a wide variety of miscellaneous constants. The constants come from the list
|
||||||
|
of include files in the `includes_${uname}` variable. A regex then picks out
|
||||||
|
the desired `#define` statements, and generates the corresponding Go constants.
|
||||||
|
The error numbers and strings are generated from `#include <errno.h>`, and the
|
||||||
|
signal numbers and strings are generated from `#include <signal.h>`. All of
|
||||||
|
these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
|
||||||
|
`_errors.c`, which prints out all the constants.
|
||||||
|
|
||||||
|
To add a constant, add the header that includes it to the appropriate variable.
|
||||||
|
Then, edit the regex (if necessary) to match the desired constant. Avoid making
|
||||||
|
the regex too broad to avoid matching unintended constants.
|
||||||
|
|
||||||
|
### internal/mkmerge
|
||||||
|
|
||||||
|
This program is used to extract duplicate const, func, and type declarations
|
||||||
|
from the generated architecture-specific files listed below, and merge these
|
||||||
|
into a common file for each OS.
|
||||||
|
|
||||||
|
The merge is performed in the following steps:
|
||||||
|
1. Construct the set of common code that is idential in all architecture-specific files.
|
||||||
|
2. Write this common code to the merged file.
|
||||||
|
3. Remove the common code from all architecture-specific files.
|
||||||
|
|
||||||
|
|
||||||
|
## Generated files
|
||||||
|
|
||||||
|
### `zerrors_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A file containing all of the system's generated error numbers, error strings,
|
||||||
|
signal numbers, and constants. Generated by `mkerrors.sh` (see above).
|
||||||
|
|
||||||
|
### `zsyscall_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A file containing all the generated syscalls for a specific GOOS and GOARCH.
|
||||||
|
Generated by `mksyscall.go` (see above).
|
||||||
|
|
||||||
|
### `zsysnum_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A list of numeric constants for all the syscall number of the specific GOOS
|
||||||
|
and GOARCH. Generated by mksysnum (see above).
|
||||||
|
|
||||||
|
### `ztypes_${GOOS}_${GOARCH}.go`
|
||||||
|
|
||||||
|
A file containing Go types for passing into (or returning from) syscalls.
|
||||||
|
Generated by godefs and the types file (see above).
|
||||||
86
vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
Normal file
86
vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// CPU affinity functions
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/bits"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
|
||||||
|
|
||||||
|
// CPUSet represents a CPU affinity mask.
|
||||||
|
type CPUSet [cpuSetSize]cpuMask
|
||||||
|
|
||||||
|
func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
|
||||||
|
_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
|
||||||
|
if e != 0 {
|
||||||
|
return errnoErr(e)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
|
||||||
|
// If pid is 0 the calling thread is used.
|
||||||
|
func SchedGetaffinity(pid int, set *CPUSet) error {
|
||||||
|
return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
|
||||||
|
// If pid is 0 the calling thread is used.
|
||||||
|
func SchedSetaffinity(pid int, set *CPUSet) error {
|
||||||
|
return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero clears the set s, so that it contains no CPUs.
|
||||||
|
func (s *CPUSet) Zero() {
|
||||||
|
for i := range s {
|
||||||
|
s[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuBitsIndex(cpu int) int {
|
||||||
|
return cpu / _NCPUBITS
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuBitsMask(cpu int) cpuMask {
|
||||||
|
return cpuMask(1 << (uint(cpu) % _NCPUBITS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set adds cpu to the set s.
|
||||||
|
func (s *CPUSet) Set(cpu int) {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
s[i] |= cpuBitsMask(cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes cpu from the set s.
|
||||||
|
func (s *CPUSet) Clear(cpu int) {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
s[i] &^= cpuBitsMask(cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet reports whether cpu is in the set s.
|
||||||
|
func (s *CPUSet) IsSet(cpu int) bool {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
return s[i]&cpuBitsMask(cpu) != 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of CPUs in the set s.
|
||||||
|
func (s *CPUSet) Count() int {
|
||||||
|
c := 0
|
||||||
|
for _, b := range s {
|
||||||
|
c += bits.OnesCount64(uint64(b))
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
15
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
Normal file
15
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// 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 (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
type Signal = syscall.Signal
|
||||||
|
type Errno = syscall.Errno
|
||||||
|
type SysProcAttr = syscall.SysProcAttr
|
||||||
18
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
Normal file
18
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// 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 gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go
|
||||||
|
//
|
||||||
|
|
||||||
|
TEXT ·syscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·rawSyscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·rawSyscall6(SB)
|
||||||
29
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2021 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 (freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for 386 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
29
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2021 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 (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for AMD64 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
29
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2021 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 (freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for ARM BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||||
|
B syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·RawSyscall6(SB)
|
||||||
29
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2021 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 (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for ARM64 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
29
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2021 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 (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// System call support for RISCV64 BSD
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
66
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
Normal file
66
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for 386, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
|
||||||
|
// instead of the glibc-specific "CALL 0x10(GS)".
|
||||||
|
#define INVOKE_SYSCALL INT $0x80
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVL trap+0(FP), AX // syscall entry
|
||||||
|
MOVL a1+4(FP), BX
|
||||||
|
MOVL a2+8(FP), CX
|
||||||
|
MOVL a3+12(FP), DX
|
||||||
|
MOVL $0, SI
|
||||||
|
MOVL $0, DI
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, r1+16(FP)
|
||||||
|
MOVL DX, r2+20(FP)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVL trap+0(FP), AX // syscall entry
|
||||||
|
MOVL a1+4(FP), BX
|
||||||
|
MOVL a2+8(FP), CX
|
||||||
|
MOVL a3+12(FP), DX
|
||||||
|
MOVL $0, SI
|
||||||
|
MOVL $0, DI
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, r1+16(FP)
|
||||||
|
MOVL DX, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·socketcall(SB),NOSPLIT,$0-36
|
||||||
|
JMP syscall·socketcall(SB)
|
||||||
|
|
||||||
|
TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
|
||||||
|
JMP syscall·rawsocketcall(SB)
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·seek(SB)
|
||||||
58
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
Normal file
58
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for AMD64, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVQ a1+8(FP), DI
|
||||||
|
MOVQ a2+16(FP), SI
|
||||||
|
MOVQ a3+24(FP), DX
|
||||||
|
MOVQ $0, R10
|
||||||
|
MOVQ $0, R8
|
||||||
|
MOVQ $0, R9
|
||||||
|
MOVQ trap+0(FP), AX // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVQ AX, r1+32(FP)
|
||||||
|
MOVQ DX, r2+40(FP)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVQ a1+8(FP), DI
|
||||||
|
MOVQ a2+16(FP), SI
|
||||||
|
MOVQ a3+24(FP), DX
|
||||||
|
MOVQ $0, R10
|
||||||
|
MOVQ $0, R8
|
||||||
|
MOVQ $0, R9
|
||||||
|
MOVQ trap+0(FP), AX // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVQ AX, r1+32(FP)
|
||||||
|
MOVQ DX, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
|
||||||
|
JMP syscall·gettimeofday(SB)
|
||||||
57
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
Normal file
57
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for arm, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVW trap+0(FP), R7
|
||||||
|
MOVW a1+4(FP), R0
|
||||||
|
MOVW a2+8(FP), R1
|
||||||
|
MOVW a3+12(FP), R2
|
||||||
|
MOVW $0, R3
|
||||||
|
MOVW $0, R4
|
||||||
|
MOVW $0, R5
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, r1+16(FP)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, r2+20(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
B syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVW trap+0(FP), R7 // syscall entry
|
||||||
|
MOVW a1+4(FP), R0
|
||||||
|
MOVW a2+8(FP), R1
|
||||||
|
MOVW a3+12(FP), R2
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, r1+16(FP)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||||
|
B syscall·seek(SB)
|
||||||
53
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
Normal file
53
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright 2015 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 linux && arm64 && gc
|
||||||
|
// +build linux
|
||||||
|
// +build arm64
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
B syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R0
|
||||||
|
MOVD a2+16(FP), R1
|
||||||
|
MOVD a3+24(FP), R2
|
||||||
|
MOVD $0, R3
|
||||||
|
MOVD $0, R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD trap+0(FP), R8 // syscall entry
|
||||||
|
SVC
|
||||||
|
MOVD R0, r1+32(FP) // r1
|
||||||
|
MOVD R1, r2+40(FP) // r2
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
B syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R0
|
||||||
|
MOVD a2+16(FP), R1
|
||||||
|
MOVD a3+24(FP), R2
|
||||||
|
MOVD $0, R3
|
||||||
|
MOVD $0, R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD trap+0(FP), R8 // syscall entry
|
||||||
|
SVC
|
||||||
|
MOVD R0, r1+32(FP)
|
||||||
|
MOVD R1, r2+40(FP)
|
||||||
|
RET
|
||||||
54
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
Normal file
54
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
// 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 linux && loong64 && gc
|
||||||
|
// +build linux
|
||||||
|
// +build loong64
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R11 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R4, r1+32(FP)
|
||||||
|
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R11 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R4, r1+32(FP)
|
||||||
|
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||||
|
RET
|
||||||
57
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
Normal file
57
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright 2015 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 linux && (mips64 || mips64le) && gc
|
||||||
|
// +build linux
|
||||||
|
// +build mips64 mips64le
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for mips64, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R2, r1+32(FP)
|
||||||
|
MOVV R3, r2+40(FP)
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R2, r1+32(FP)
|
||||||
|
MOVV R3, r2+40(FP)
|
||||||
|
RET
|
||||||
55
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
Normal file
55
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright 2016 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 linux && (mips || mipsle) && gc
|
||||||
|
// +build linux
|
||||||
|
// +build mips mipsle
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for mips, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVW a1+4(FP), R4
|
||||||
|
MOVW a2+8(FP), R5
|
||||||
|
MOVW a3+12(FP), R6
|
||||||
|
MOVW R0, R7
|
||||||
|
MOVW trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVW R2, r1+16(FP) // r1
|
||||||
|
MOVW R3, r2+20(FP) // r2
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVW a1+4(FP), R4
|
||||||
|
MOVW a2+8(FP), R5
|
||||||
|
MOVW a3+12(FP), R6
|
||||||
|
MOVW trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVW R2, r1+16(FP)
|
||||||
|
MOVW R3, r2+20(FP)
|
||||||
|
RET
|
||||||
45
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
Normal file
45
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2014 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 linux && (ppc64 || ppc64le) && gc
|
||||||
|
// +build linux
|
||||||
|
// +build ppc64 ppc64le
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for ppc64, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R3
|
||||||
|
MOVD a2+16(FP), R4
|
||||||
|
MOVD a3+24(FP), R5
|
||||||
|
MOVD R0, R6
|
||||||
|
MOVD R0, R7
|
||||||
|
MOVD R0, R8
|
||||||
|
MOVD trap+0(FP), R9 // syscall entry
|
||||||
|
SYSCALL R9
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R4, r2+40(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R3
|
||||||
|
MOVD a2+16(FP), R4
|
||||||
|
MOVD a3+24(FP), R5
|
||||||
|
MOVD R0, R6
|
||||||
|
MOVD R0, R7
|
||||||
|
MOVD R0, R8
|
||||||
|
MOVD trap+0(FP), R9 // syscall entry
|
||||||
|
SYSCALL R9
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R4, r2+40(FP)
|
||||||
|
RET
|
||||||
49
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
Normal file
49
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2019 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 riscv64 && gc
|
||||||
|
// +build riscv64
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for linux/riscv64.
|
||||||
|
//
|
||||||
|
// Where available, just jump to package syscall's implementation of
|
||||||
|
// these functions.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOV a1+8(FP), A0
|
||||||
|
MOV a2+16(FP), A1
|
||||||
|
MOV a3+24(FP), A2
|
||||||
|
MOV trap+0(FP), A7 // syscall entry
|
||||||
|
ECALL
|
||||||
|
MOV A0, r1+32(FP) // r1
|
||||||
|
MOV A1, r2+40(FP) // r2
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOV a1+8(FP), A0
|
||||||
|
MOV a2+16(FP), A1
|
||||||
|
MOV a3+24(FP), A2
|
||||||
|
MOV trap+0(FP), A7 // syscall entry
|
||||||
|
ECALL
|
||||||
|
MOV A0, r1+32(FP)
|
||||||
|
MOV A1, r2+40(FP)
|
||||||
|
RET
|
||||||
57
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
Normal file
57
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright 2016 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 linux && s390x && gc
|
||||||
|
// +build linux
|
||||||
|
// +build s390x
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for s390x, Linux
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
BR syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
BR syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R2
|
||||||
|
MOVD a2+16(FP), R3
|
||||||
|
MOVD a3+24(FP), R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD $0, R6
|
||||||
|
MOVD $0, R7
|
||||||
|
MOVD trap+0(FP), R1 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVD R2, r1+32(FP)
|
||||||
|
MOVD R3, r2+40(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
BR syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
BR syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R2
|
||||||
|
MOVD a2+16(FP), R3
|
||||||
|
MOVD a3+24(FP), R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD $0, R6
|
||||||
|
MOVD $0, R7
|
||||||
|
MOVD trap+0(FP), R1 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVD R2, r1+32(FP)
|
||||||
|
MOVD R3, r2+40(FP)
|
||||||
|
RET
|
||||||
30
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
Normal file
30
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2019 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 gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for mips64, OpenBSD
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
18
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
Normal file
18
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2014 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 gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
|
||||||
|
//
|
||||||
|
|
||||||
|
TEXT ·sysvicall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·sysvicall6(SB)
|
||||||
|
|
||||||
|
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·rawSysvicall6(SB)
|
||||||
426
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
Normal file
426
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
Normal file
|
|
@ -0,0 +1,426 @@
|
||||||
|
// Copyright 2020 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 zos && s390x && gc
|
||||||
|
// +build zos
|
||||||
|
// +build s390x
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define PSALAA 1208(R0)
|
||||||
|
#define GTAB64(x) 80(x)
|
||||||
|
#define LCA64(x) 88(x)
|
||||||
|
#define CAA(x) 8(x)
|
||||||
|
#define EDCHPXV(x) 1016(x) // in the CAA
|
||||||
|
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
||||||
|
|
||||||
|
// SS_*, where x=SAVSTACK_ASYNC
|
||||||
|
#define SS_LE(x) 0(x)
|
||||||
|
#define SS_GO(x) 8(x)
|
||||||
|
#define SS_ERRNO(x) 16(x)
|
||||||
|
#define SS_ERRNOJR(x) 20(x)
|
||||||
|
|
||||||
|
#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
|
||||||
|
|
||||||
|
TEXT ·clearErrno(SB),NOSPLIT,$0-0
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVD $0, 0(R3)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// Returns the address of errno in R3.
|
||||||
|
TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get __errno FuncDesc.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
ADD $(0x156*16), R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Switch to saved LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call __errno function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
|
||||||
|
// Switch back to Go stack.
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R0, r2+40(FP)
|
||||||
|
MOVD R0, err+48(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+48(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R0, r2+40(FP)
|
||||||
|
MOVD R0, err+48(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+48(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+56(FP)
|
||||||
|
MOVD R0, r2+64(FP)
|
||||||
|
MOVD R0, err+72(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+72(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+56(FP)
|
||||||
|
MOVD R0, r2+64(FP)
|
||||||
|
MOVD R0, err+72(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL ·rrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+72(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall9(SB),NOSPLIT,$0
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
MOVD a7+56(FP), R12
|
||||||
|
MOVD R12, (2176+48)(R4)
|
||||||
|
MOVD a8+64(FP), R12
|
||||||
|
MOVD R12, (2176+56)(R4)
|
||||||
|
MOVD a9+72(FP), R12
|
||||||
|
MOVD R12, (2176+64)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+80(FP)
|
||||||
|
MOVD R0, r2+88(FP)
|
||||||
|
MOVD R0, err+96(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+96(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
MOVD a7+56(FP), R12
|
||||||
|
MOVD R12, (2176+48)(R4)
|
||||||
|
MOVD a8+64(FP), R12
|
||||||
|
MOVD R12, (2176+56)(R4)
|
||||||
|
MOVD a9+72(FP), R12
|
||||||
|
MOVD R12, (2176+64)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+80(FP)
|
||||||
|
MOVD R0, r2+88(FP)
|
||||||
|
MOVD R0, err+96(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+96(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
||||||
|
TEXT ·svcCall(SB),NOSPLIT,$0
|
||||||
|
BL runtime·save_g(SB) // Save g and stack pointer
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD R15, 0(R9)
|
||||||
|
|
||||||
|
MOVD argv+8(FP), R1 // Move function arguments into registers
|
||||||
|
MOVD dsa+16(FP), g
|
||||||
|
MOVD fnptr+0(FP), R15
|
||||||
|
|
||||||
|
BYTE $0x0D // Branch to function
|
||||||
|
BYTE $0xEF
|
||||||
|
|
||||||
|
BL runtime·load_g(SB) // Restore g and stack pointer
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R15
|
||||||
|
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func svcLoad(name *byte) unsafe.Pointer
|
||||||
|
TEXT ·svcLoad(SB),NOSPLIT,$0
|
||||||
|
MOVD R15, R2 // Save go stack pointer
|
||||||
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||||
|
MOVD $0x80000000, R1
|
||||||
|
MOVD $0, R15
|
||||||
|
BYTE $0x0A // SVC 08 LOAD
|
||||||
|
BYTE $0x08
|
||||||
|
MOVW R15, R3 // Save return code from SVC
|
||||||
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
CMP R3, $0 // Check SVC return code
|
||||||
|
BNE error
|
||||||
|
|
||||||
|
MOVD $-2, R3 // Reset last bit of entry point to zero
|
||||||
|
AND R0, R3
|
||||||
|
MOVD R3, addr+8(FP) // Return entry point returned by SVC
|
||||||
|
CMP R0, R3 // Check if last bit of entry point was set
|
||||||
|
BNE done
|
||||||
|
|
||||||
|
MOVD R15, R2 // Save go stack pointer
|
||||||
|
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
||||||
|
BYTE $0x0A // SVC 09 DELETE
|
||||||
|
BYTE $0x09
|
||||||
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
|
||||||
|
error:
|
||||||
|
MOVD $0, addr+8(FP) // Return 0 on failure
|
||||||
|
done:
|
||||||
|
XOR R0, R0 // Reset r0 to 0
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
||||||
|
TEXT ·svcUnload(SB),NOSPLIT,$0
|
||||||
|
MOVD R15, R2 // Save go stack pointer
|
||||||
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||||
|
MOVD addr+8(FP), R15
|
||||||
|
BYTE $0x0A // SVC 09
|
||||||
|
BYTE $0x09
|
||||||
|
XOR R0, R0 // Reset r0 to 0
|
||||||
|
MOVD R15, R1 // Save SVC return code
|
||||||
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
MOVD R1, rc+0(FP) // Return SVC return code
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func gettid() uint64
|
||||||
|
TEXT ·gettid(SB), NOSPLIT, $0
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get CEECAATHDID
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD 0x3D0(R9), R9
|
||||||
|
MOVD R9, ret+0(FP)
|
||||||
|
|
||||||
|
RET
|
||||||
36
vendor/golang.org/x/sys/unix/bluetooth_linux.go
generated
vendored
Normal file
36
vendor/golang.org/x/sys/unix/bluetooth_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
// Bluetooth sockets and messages
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Bluetooth Protocols
|
||||||
|
const (
|
||||||
|
BTPROTO_L2CAP = 0
|
||||||
|
BTPROTO_HCI = 1
|
||||||
|
BTPROTO_SCO = 2
|
||||||
|
BTPROTO_RFCOMM = 3
|
||||||
|
BTPROTO_BNEP = 4
|
||||||
|
BTPROTO_CMTP = 5
|
||||||
|
BTPROTO_HIDP = 6
|
||||||
|
BTPROTO_AVDTP = 7
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HCI_CHANNEL_RAW = 0
|
||||||
|
HCI_CHANNEL_USER = 1
|
||||||
|
HCI_CHANNEL_MONITOR = 2
|
||||||
|
HCI_CHANNEL_CONTROL = 3
|
||||||
|
HCI_CHANNEL_LOGGING = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Socketoption Level
|
||||||
|
const (
|
||||||
|
SOL_BLUETOOTH = 0x112
|
||||||
|
SOL_HCI = 0x0
|
||||||
|
SOL_L2CAP = 0x6
|
||||||
|
SOL_RFCOMM = 0x12
|
||||||
|
SOL_SCO = 0x11
|
||||||
|
)
|
||||||
196
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
Normal file
196
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,196 @@
|
||||||
|
// Copyright 2017 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 freebsd
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
|
||||||
|
|
||||||
|
const (
|
||||||
|
// This is the version of CapRights this package understands. See C implementation for parallels.
|
||||||
|
capRightsGoVersion = CAP_RIGHTS_VERSION_00
|
||||||
|
capArSizeMin = CAP_RIGHTS_VERSION_00 + 2
|
||||||
|
capArSizeMax = capRightsGoVersion + 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
bit2idx = []int{
|
||||||
|
-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func capidxbit(right uint64) int {
|
||||||
|
return int((right >> 57) & 0x1f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rightToIndex(right uint64) (int, error) {
|
||||||
|
idx := capidxbit(right)
|
||||||
|
if idx < 0 || idx >= len(bit2idx) {
|
||||||
|
return -2, fmt.Errorf("index for right 0x%x out of range", right)
|
||||||
|
}
|
||||||
|
return bit2idx[idx], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func caprver(right uint64) int {
|
||||||
|
return int(right >> 62)
|
||||||
|
}
|
||||||
|
|
||||||
|
func capver(rights *CapRights) int {
|
||||||
|
return caprver(rights.Rights[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func caparsize(rights *CapRights) int {
|
||||||
|
return capver(rights) + 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapRightsSet sets the permissions in setrights in rights.
|
||||||
|
func CapRightsSet(rights *CapRights, setrights []uint64) error {
|
||||||
|
// This is essentially a copy of cap_rights_vset()
|
||||||
|
if capver(rights) != CAP_RIGHTS_VERSION_00 {
|
||||||
|
return fmt.Errorf("bad rights version %d", capver(rights))
|
||||||
|
}
|
||||||
|
|
||||||
|
n := caparsize(rights)
|
||||||
|
if n < capArSizeMin || n > capArSizeMax {
|
||||||
|
return errors.New("bad rights size")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, right := range setrights {
|
||||||
|
if caprver(right) != CAP_RIGHTS_VERSION_00 {
|
||||||
|
return errors.New("bad right version")
|
||||||
|
}
|
||||||
|
i, err := rightToIndex(right)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if i >= n {
|
||||||
|
return errors.New("index overflow")
|
||||||
|
}
|
||||||
|
if capidxbit(rights.Rights[i]) != capidxbit(right) {
|
||||||
|
return errors.New("index mismatch")
|
||||||
|
}
|
||||||
|
rights.Rights[i] |= right
|
||||||
|
if capidxbit(rights.Rights[i]) != capidxbit(right) {
|
||||||
|
return errors.New("index mismatch (after assign)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapRightsClear clears the permissions in clearrights from rights.
|
||||||
|
func CapRightsClear(rights *CapRights, clearrights []uint64) error {
|
||||||
|
// This is essentially a copy of cap_rights_vclear()
|
||||||
|
if capver(rights) != CAP_RIGHTS_VERSION_00 {
|
||||||
|
return fmt.Errorf("bad rights version %d", capver(rights))
|
||||||
|
}
|
||||||
|
|
||||||
|
n := caparsize(rights)
|
||||||
|
if n < capArSizeMin || n > capArSizeMax {
|
||||||
|
return errors.New("bad rights size")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, right := range clearrights {
|
||||||
|
if caprver(right) != CAP_RIGHTS_VERSION_00 {
|
||||||
|
return errors.New("bad right version")
|
||||||
|
}
|
||||||
|
i, err := rightToIndex(right)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if i >= n {
|
||||||
|
return errors.New("index overflow")
|
||||||
|
}
|
||||||
|
if capidxbit(rights.Rights[i]) != capidxbit(right) {
|
||||||
|
return errors.New("index mismatch")
|
||||||
|
}
|
||||||
|
rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
|
||||||
|
if capidxbit(rights.Rights[i]) != capidxbit(right) {
|
||||||
|
return errors.New("index mismatch (after assign)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapRightsIsSet checks whether all the permissions in setrights are present in rights.
|
||||||
|
func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
|
||||||
|
// This is essentially a copy of cap_rights_is_vset()
|
||||||
|
if capver(rights) != CAP_RIGHTS_VERSION_00 {
|
||||||
|
return false, fmt.Errorf("bad rights version %d", capver(rights))
|
||||||
|
}
|
||||||
|
|
||||||
|
n := caparsize(rights)
|
||||||
|
if n < capArSizeMin || n > capArSizeMax {
|
||||||
|
return false, errors.New("bad rights size")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, right := range setrights {
|
||||||
|
if caprver(right) != CAP_RIGHTS_VERSION_00 {
|
||||||
|
return false, errors.New("bad right version")
|
||||||
|
}
|
||||||
|
i, err := rightToIndex(right)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if i >= n {
|
||||||
|
return false, errors.New("index overflow")
|
||||||
|
}
|
||||||
|
if capidxbit(rights.Rights[i]) != capidxbit(right) {
|
||||||
|
return false, errors.New("index mismatch")
|
||||||
|
}
|
||||||
|
if (rights.Rights[i] & right) != right {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func capright(idx uint64, bit uint64) uint64 {
|
||||||
|
return ((1 << (57 + idx)) | bit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
|
||||||
|
// See man cap_rights_init(3) and rights(4).
|
||||||
|
func CapRightsInit(rights []uint64) (*CapRights, error) {
|
||||||
|
var r CapRights
|
||||||
|
r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
|
||||||
|
r.Rights[1] = capright(1, 0)
|
||||||
|
|
||||||
|
err := CapRightsSet(&r, rights)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
|
||||||
|
// The capability rights on fd can never be increased by CapRightsLimit.
|
||||||
|
// See man cap_rights_limit(2) and rights(4).
|
||||||
|
func CapRightsLimit(fd uintptr, rights *CapRights) error {
|
||||||
|
return capRightsLimit(int(fd), rights)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CapRightsGet returns a CapRights structure containing the operations permitted on fd.
|
||||||
|
// See man cap_rights_get(3) and rights(4).
|
||||||
|
func CapRightsGet(fd uintptr) (*CapRights, error) {
|
||||||
|
r, err := CapRightsInit(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = capRightsGet(capRightsGoVersion, int(fd), r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
14
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
Normal file
14
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2015 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 aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
R_OK = 0x4
|
||||||
|
W_OK = 0x2
|
||||||
|
X_OK = 0x1
|
||||||
|
)
|
||||||
27
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
Normal file
27
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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 aix && ppc
|
||||||
|
// +build aix,ppc
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used by AIX.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a Linux device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev >> 16) & 0xffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a Linux device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32(dev & 0xffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a Linux device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
return uint64(((major) << 16) | (minor))
|
||||||
|
}
|
||||||
29
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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 aix && ppc64
|
||||||
|
// +build aix,ppc64
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used AIX.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a Linux device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev & 0x3fffffff00000000) >> 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a Linux device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32((dev & 0x00000000ffffffff) >> 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a Linux device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
var DEVNO64 uint64
|
||||||
|
DEVNO64 = 0x8000000000000000
|
||||||
|
return ((uint64(major) << 32) | (uint64(minor) & 0x00000000FFFFFFFF) | DEVNO64)
|
||||||
|
}
|
||||||
24
vendor/golang.org/x/sys/unix/dev_darwin.go
generated
vendored
Normal file
24
vendor/golang.org/x/sys/unix/dev_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used in Darwin's sys/types.h header.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a Darwin device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev >> 24) & 0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a Darwin device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32(dev & 0xffffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a Darwin device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
return (uint64(major) << 24) | uint64(minor)
|
||||||
|
}
|
||||||
30
vendor/golang.org/x/sys/unix/dev_dragonfly.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/unix/dev_dragonfly.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used in Dragonfly's sys/types.h header.
|
||||||
|
//
|
||||||
|
// The information below is extracted and adapted from sys/types.h:
|
||||||
|
//
|
||||||
|
// Minor gives a cookie instead of an index since in order to avoid changing the
|
||||||
|
// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
|
||||||
|
// devices that don't use them.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a DragonFlyBSD device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev >> 8) & 0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a DragonFlyBSD device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32(dev & 0xffff00ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a DragonFlyBSD device number generated from the given major and
|
||||||
|
// minor components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
return (uint64(major) << 8) | uint64(minor)
|
||||||
|
}
|
||||||
30
vendor/golang.org/x/sys/unix/dev_freebsd.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/unix/dev_freebsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used in FreeBSD's sys/types.h header.
|
||||||
|
//
|
||||||
|
// The information below is extracted and adapted from sys/types.h:
|
||||||
|
//
|
||||||
|
// Minor gives a cookie instead of an index since in order to avoid changing the
|
||||||
|
// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
|
||||||
|
// devices that don't use them.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a FreeBSD device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev >> 8) & 0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a FreeBSD device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32(dev & 0xffff00ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a FreeBSD device number generated from the given major and
|
||||||
|
// minor components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
return (uint64(major) << 8) | uint64(minor)
|
||||||
|
}
|
||||||
42
vendor/golang.org/x/sys/unix/dev_linux.go
generated
vendored
Normal file
42
vendor/golang.org/x/sys/unix/dev_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used by the Linux kernel and glibc.
|
||||||
|
//
|
||||||
|
// The information below is extracted and adapted from bits/sysmacros.h in the
|
||||||
|
// glibc sources:
|
||||||
|
//
|
||||||
|
// dev_t in glibc is 64-bit, with 32-bit major and minor numbers. glibc's
|
||||||
|
// default encoding is MMMM Mmmm mmmM MMmm, where M is a hex digit of the major
|
||||||
|
// number and m is a hex digit of the minor number. This is backward compatible
|
||||||
|
// with legacy systems where dev_t is 16 bits wide, encoded as MMmm. It is also
|
||||||
|
// backward compatible with the Linux kernel, which for some architectures uses
|
||||||
|
// 32-bit dev_t, encoded as mmmM MMmm.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a Linux device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
major := uint32((dev & 0x00000000000fff00) >> 8)
|
||||||
|
major |= uint32((dev & 0xfffff00000000000) >> 32)
|
||||||
|
return major
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a Linux device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
minor := uint32((dev & 0x00000000000000ff) >> 0)
|
||||||
|
minor |= uint32((dev & 0x00000ffffff00000) >> 12)
|
||||||
|
return minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a Linux device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
dev := (uint64(major) & 0x00000fff) << 8
|
||||||
|
dev |= (uint64(major) & 0xfffff000) << 32
|
||||||
|
dev |= (uint64(minor) & 0x000000ff) << 0
|
||||||
|
dev |= (uint64(minor) & 0xffffff00) << 12
|
||||||
|
return dev
|
||||||
|
}
|
||||||
29
vendor/golang.org/x/sys/unix/dev_netbsd.go
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/dev_netbsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used in NetBSD's sys/types.h header.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a NetBSD device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev & 0x000fff00) >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a NetBSD device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
minor := uint32((dev & 0x000000ff) >> 0)
|
||||||
|
minor |= uint32((dev & 0xfff00000) >> 12)
|
||||||
|
return minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a NetBSD device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
dev := (uint64(major) << 8) & 0x000fff00
|
||||||
|
dev |= (uint64(minor) << 12) & 0xfff00000
|
||||||
|
dev |= (uint64(minor) << 0) & 0x000000ff
|
||||||
|
return dev
|
||||||
|
}
|
||||||
29
vendor/golang.org/x/sys/unix/dev_openbsd.go
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/dev_openbsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used in OpenBSD's sys/types.h header.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of an OpenBSD device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev & 0x0000ff00) >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of an OpenBSD device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
minor := uint32((dev & 0x000000ff) >> 0)
|
||||||
|
minor |= uint32((dev & 0xffff0000) >> 8)
|
||||||
|
return minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns an OpenBSD device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
dev := (uint64(major) << 8) & 0x0000ff00
|
||||||
|
dev |= (uint64(minor) << 8) & 0xffff0000
|
||||||
|
dev |= (uint64(minor) << 0) & 0x000000ff
|
||||||
|
return dev
|
||||||
|
}
|
||||||
29
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2020 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 zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used by z/OS.
|
||||||
|
//
|
||||||
|
// The information below is extracted and adapted from <sys/stat.h> macros.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a z/OS device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev >> 16) & 0x0000FFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a z/OS device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32(dev & 0x0000FFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a z/OS device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
return (uint64(major) << 16) | uint64(minor)
|
||||||
|
}
|
||||||
103
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
Normal file
103
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
|
||||||
|
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
|
||||||
|
if len(b) < int(off+size) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
if isBigEndian {
|
||||||
|
return readIntBE(b[off:], size), true
|
||||||
|
}
|
||||||
|
return readIntLE(b[off:], size), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func readIntBE(b []byte, size uintptr) uint64 {
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint64(b[0])
|
||||||
|
case 2:
|
||||||
|
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[1]) | uint64(b[0])<<8
|
||||||
|
case 4:
|
||||||
|
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
|
||||||
|
case 8:
|
||||||
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||||
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||||
|
default:
|
||||||
|
panic("syscall: readInt with unsupported size")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readIntLE(b []byte, size uintptr) uint64 {
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint64(b[0])
|
||||||
|
case 2:
|
||||||
|
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8
|
||||||
|
case 4:
|
||||||
|
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
|
||||||
|
case 8:
|
||||||
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||||
|
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||||
|
default:
|
||||||
|
panic("syscall: readInt with unsupported size")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDirent parses up to max directory entries in buf,
|
||||||
|
// appending the names to names. It returns the number of
|
||||||
|
// bytes consumed from buf, the number of entries added
|
||||||
|
// to names, and the new names slice.
|
||||||
|
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||||
|
origlen := len(buf)
|
||||||
|
count = 0
|
||||||
|
for max != 0 && len(buf) > 0 {
|
||||||
|
reclen, ok := direntReclen(buf)
|
||||||
|
if !ok || reclen > uint64(len(buf)) {
|
||||||
|
return origlen, count, names
|
||||||
|
}
|
||||||
|
rec := buf[:reclen]
|
||||||
|
buf = buf[reclen:]
|
||||||
|
ino, ok := direntIno(rec)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if ino == 0 { // File absent in directory.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
|
||||||
|
namlen, ok := direntNamlen(rec)
|
||||||
|
if !ok || namoff+namlen > uint64(len(rec)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
name := rec[namoff : namoff+namlen]
|
||||||
|
for i, c := range name {
|
||||||
|
if c == 0 {
|
||||||
|
name = name[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for useless names before allocating a string.
|
||||||
|
if string(name) == "." || string(name) == ".." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
max--
|
||||||
|
count++
|
||||||
|
names = append(names, string(name))
|
||||||
|
}
|
||||||
|
return origlen - len(buf), count, names
|
||||||
|
}
|
||||||
10
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
Normal file
10
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2016 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 armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
||||||
|
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const isBigEndian = true
|
||||||
10
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
Normal file
10
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright 2016 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 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
|
||||||
|
// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const isBigEndian = false
|
||||||
32
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
Normal file
32
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2010 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 aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
|
// Unix environment variables.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func Getenv(key string) (value string, found bool) {
|
||||||
|
return syscall.Getenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
return syscall.Setenv(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clearenv() {
|
||||||
|
syscall.Clearenv()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Environ() []string {
|
||||||
|
return syscall.Environ()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
return syscall.Unsetenv(key)
|
||||||
|
}
|
||||||
221
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
Normal file
221
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
// Copyright 2020 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 zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file simulates epoll on z/OS using poll.
|
||||||
|
|
||||||
|
// Analogous to epoll_event on Linux.
|
||||||
|
// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
|
||||||
|
type EpollEvent struct {
|
||||||
|
Events uint32
|
||||||
|
Fd int32
|
||||||
|
Pad int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
EPOLLERR = 0x8
|
||||||
|
EPOLLHUP = 0x10
|
||||||
|
EPOLLIN = 0x1
|
||||||
|
EPOLLMSG = 0x400
|
||||||
|
EPOLLOUT = 0x4
|
||||||
|
EPOLLPRI = 0x2
|
||||||
|
EPOLLRDBAND = 0x80
|
||||||
|
EPOLLRDNORM = 0x40
|
||||||
|
EPOLLWRBAND = 0x200
|
||||||
|
EPOLLWRNORM = 0x100
|
||||||
|
EPOLL_CTL_ADD = 0x1
|
||||||
|
EPOLL_CTL_DEL = 0x2
|
||||||
|
EPOLL_CTL_MOD = 0x3
|
||||||
|
// The following constants are part of the epoll API, but represent
|
||||||
|
// currently unsupported functionality on z/OS.
|
||||||
|
// EPOLL_CLOEXEC = 0x80000
|
||||||
|
// EPOLLET = 0x80000000
|
||||||
|
// EPOLLONESHOT = 0x40000000
|
||||||
|
// EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
|
||||||
|
// EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
|
||||||
|
// EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
|
||||||
|
// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
|
||||||
|
|
||||||
|
// epToPollEvt converts epoll event field to poll equivalent.
|
||||||
|
// In epoll, Events is a 32-bit field, while poll uses 16 bits.
|
||||||
|
func epToPollEvt(events uint32) int16 {
|
||||||
|
var ep2p = map[uint32]int16{
|
||||||
|
EPOLLIN: POLLIN,
|
||||||
|
EPOLLOUT: POLLOUT,
|
||||||
|
EPOLLHUP: POLLHUP,
|
||||||
|
EPOLLPRI: POLLPRI,
|
||||||
|
EPOLLERR: POLLERR,
|
||||||
|
}
|
||||||
|
|
||||||
|
var pollEvts int16 = 0
|
||||||
|
for epEvt, pEvt := range ep2p {
|
||||||
|
if (events & epEvt) != 0 {
|
||||||
|
pollEvts |= pEvt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pollEvts
|
||||||
|
}
|
||||||
|
|
||||||
|
// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
|
||||||
|
func pToEpollEvt(revents int16) uint32 {
|
||||||
|
var p2ep = map[int16]uint32{
|
||||||
|
POLLIN: EPOLLIN,
|
||||||
|
POLLOUT: EPOLLOUT,
|
||||||
|
POLLHUP: EPOLLHUP,
|
||||||
|
POLLPRI: EPOLLPRI,
|
||||||
|
POLLERR: EPOLLERR,
|
||||||
|
}
|
||||||
|
|
||||||
|
var epollEvts uint32 = 0
|
||||||
|
for pEvt, epEvt := range p2ep {
|
||||||
|
if (revents & pEvt) != 0 {
|
||||||
|
epollEvts |= epEvt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return epollEvts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-process epoll implementation.
|
||||||
|
type epollImpl struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
epfd2ep map[int]*eventPoll
|
||||||
|
nextEpfd int
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
|
||||||
|
// On Linux, this is an in-kernel data structure accessed through a fd.
|
||||||
|
type eventPoll struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
fds map[int]*EpollEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
// epoll impl for this process.
|
||||||
|
var impl epollImpl = epollImpl{
|
||||||
|
epfd2ep: make(map[int]*eventPoll),
|
||||||
|
nextEpfd: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
epfd = e.nextEpfd
|
||||||
|
e.nextEpfd++
|
||||||
|
|
||||||
|
e.epfd2ep[epfd] = &eventPoll{
|
||||||
|
fds: make(map[int]*EpollEvent),
|
||||||
|
}
|
||||||
|
return epfd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
|
||||||
|
return e.epollcreate(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
|
ep, ok := e.epfd2ep[epfd]
|
||||||
|
if !ok {
|
||||||
|
|
||||||
|
return EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case EPOLL_CTL_ADD:
|
||||||
|
// TODO(neeilan): When we make epfds and fds disjoint, detect epoll
|
||||||
|
// loops here (instances watching each other) and return ELOOP.
|
||||||
|
if _, ok := ep.fds[fd]; ok {
|
||||||
|
return EEXIST
|
||||||
|
}
|
||||||
|
ep.fds[fd] = event
|
||||||
|
case EPOLL_CTL_MOD:
|
||||||
|
if _, ok := ep.fds[fd]; !ok {
|
||||||
|
return ENOENT
|
||||||
|
}
|
||||||
|
ep.fds[fd] = event
|
||||||
|
case EPOLL_CTL_DEL:
|
||||||
|
if _, ok := ep.fds[fd]; !ok {
|
||||||
|
return ENOENT
|
||||||
|
}
|
||||||
|
delete(ep.fds, fd)
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be called while holding ep.mu
|
||||||
|
func (ep *eventPoll) getFds() []int {
|
||||||
|
fds := make([]int, len(ep.fds))
|
||||||
|
for fd := range ep.fds {
|
||||||
|
fds = append(fds, fd)
|
||||||
|
}
|
||||||
|
return fds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||||
|
e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
|
||||||
|
ep, ok := e.epfd2ep[epfd]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
e.mu.Unlock()
|
||||||
|
return 0, EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
pollfds := make([]PollFd, 4)
|
||||||
|
for fd, epollevt := range ep.fds {
|
||||||
|
pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
|
||||||
|
}
|
||||||
|
e.mu.Unlock()
|
||||||
|
|
||||||
|
n, err = Poll(pollfds, msec)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, pFd := range pollfds {
|
||||||
|
if pFd.Revents != 0 {
|
||||||
|
events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCreate(size int) (fd int, err error) {
|
||||||
|
return impl.epollcreate(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCreate1(flag int) (fd int, err error) {
|
||||||
|
return impl.epollcreate1(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||||
|
return impl.epollctl(epfd, op, fd, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because EpollWait mutates events, the caller is expected to coordinate
|
||||||
|
// concurrent access if calling with the same epfd from multiple goroutines.
|
||||||
|
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||||
|
return impl.epollwait(epfd, events, msec)
|
||||||
|
}
|
||||||
37
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
Normal file
37
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2014 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 || linux || netbsd || openbsd
|
||||||
|
// +build dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux
|
||||||
|
// systems by fcntl_linux_32bit.go to be SYS_FCNTL64.
|
||||||
|
var fcntl64Syscall uintptr = SYS_FCNTL
|
||||||
|
|
||||||
|
func fcntl(fd int, cmd, arg int) (int, error) {
|
||||||
|
valptr, _, errno := Syscall(fcntl64Syscall, uintptr(fd), uintptr(cmd), uintptr(arg))
|
||||||
|
var err error
|
||||||
|
if errno != 0 {
|
||||||
|
err = errno
|
||||||
|
}
|
||||||
|
return int(valptr), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
|
||||||
|
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
|
||||||
|
return fcntl(int(fd), cmd, arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
|
||||||
|
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
|
||||||
|
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
|
||||||
|
if errno == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
||||||
24
vendor/golang.org/x/sys/unix/fcntl_darwin.go
generated
vendored
Normal file
24
vendor/golang.org/x/sys/unix/fcntl_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2019 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 "unsafe"
|
||||||
|
|
||||||
|
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
|
||||||
|
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
|
||||||
|
return fcntl(int(fd), cmd, arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
|
||||||
|
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
|
||||||
|
_, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(lk))))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FcntlFstore performs a fcntl syscall for the F_PREALLOCATE command.
|
||||||
|
func FcntlFstore(fd uintptr, cmd int, fstore *Fstore_t) error {
|
||||||
|
_, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(fstore))))
|
||||||
|
return err
|
||||||
|
}
|
||||||
14
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2014 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 (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
||||||
|
// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// On 32-bit Linux systems, the fcntl syscall that matches Go's
|
||||||
|
// Flock_t type is SYS_FCNTL64, not SYS_FCNTL.
|
||||||
|
fcntl64Syscall = SYS_FCNTL64
|
||||||
|
}
|
||||||
30
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2019 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 aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Set adds fd to the set fds.
|
||||||
|
func (fds *FdSet) Set(fd int) {
|
||||||
|
fds.Bits[fd/NFDBITS] |= (1 << (uintptr(fd) % NFDBITS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes fd from the set fds.
|
||||||
|
func (fds *FdSet) Clear(fd int) {
|
||||||
|
fds.Bits[fd/NFDBITS] &^= (1 << (uintptr(fd) % NFDBITS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns whether fd is in the set fds.
|
||||||
|
func (fds *FdSet) IsSet(fd int) bool {
|
||||||
|
return fds.Bits[fd/NFDBITS]&(1<<(uintptr(fd)%NFDBITS)) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero clears the set fds.
|
||||||
|
func (fds *FdSet) Zero() {
|
||||||
|
for i := range fds.Bits {
|
||||||
|
fds.Bits[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
164
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
Normal file
164
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
// Copyright 2020 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 zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
|
||||||
|
|
||||||
|
func Fstatfs(fd int, stat *Statfs_t) (err error) {
|
||||||
|
var stat_v Statvfs_t
|
||||||
|
err = Fstatvfs(fd, &stat_v)
|
||||||
|
if err == nil {
|
||||||
|
// populate stat
|
||||||
|
stat.Type = 0
|
||||||
|
stat.Bsize = stat_v.Bsize
|
||||||
|
stat.Blocks = stat_v.Blocks
|
||||||
|
stat.Bfree = stat_v.Bfree
|
||||||
|
stat.Bavail = stat_v.Bavail
|
||||||
|
stat.Files = stat_v.Files
|
||||||
|
stat.Ffree = stat_v.Ffree
|
||||||
|
stat.Fsid = stat_v.Fsid
|
||||||
|
stat.Namelen = stat_v.Namemax
|
||||||
|
stat.Frsize = stat_v.Frsize
|
||||||
|
stat.Flags = stat_v.Flag
|
||||||
|
for passn := 0; passn < 5; passn++ {
|
||||||
|
switch passn {
|
||||||
|
case 0:
|
||||||
|
err = tryGetmntent64(stat)
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
err = tryGetmntent128(stat)
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
err = tryGetmntent256(stat)
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
err = tryGetmntent512(stat)
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
err = tryGetmntent1024(stat)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
|
||||||
|
if err == nil || err != nil && err != ERANGE {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent64(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [64]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent128(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [128]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent256(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [256]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent512(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [512]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent1024(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [1024]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
60
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
Normal file
60
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright 2015 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 gccgo && !aix
|
||||||
|
// +build gccgo,!aix
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// We can't use the gc-syntax .s files for gccgo. On the plus side
|
||||||
|
// much of the functionality can be written directly in Go.
|
||||||
|
|
||||||
|
func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
|
||||||
|
|
||||||
|
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
|
||||||
|
|
||||||
|
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
|
||||||
|
syscall.Entersyscall()
|
||||||
|
r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
syscall.Exitsyscall()
|
||||||
|
return r, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
|
syscall.Entersyscall()
|
||||||
|
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
syscall.Exitsyscall()
|
||||||
|
return r, 0, syscall.Errno(errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
|
syscall.Entersyscall()
|
||||||
|
r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
|
||||||
|
syscall.Exitsyscall()
|
||||||
|
return r, 0, syscall.Errno(errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
|
syscall.Entersyscall()
|
||||||
|
r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||||
|
syscall.Exitsyscall()
|
||||||
|
return r, 0, syscall.Errno(errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
|
||||||
|
r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
return r, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
|
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
return r, 0, syscall.Errno(errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
|
r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
|
||||||
|
return r, 0, syscall.Errno(errno)
|
||||||
|
}
|
||||||
45
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
Normal file
45
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build gccgo
|
||||||
|
// +build !aix
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define _STRINGIFY2_(x) #x
|
||||||
|
#define _STRINGIFY_(x) _STRINGIFY2_(x)
|
||||||
|
#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
|
||||||
|
|
||||||
|
// Call syscall from C code because the gccgo support for calling from
|
||||||
|
// Go to C does not support varargs functions.
|
||||||
|
|
||||||
|
struct ret {
|
||||||
|
uintptr_t r;
|
||||||
|
uintptr_t err;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||||
|
__asm__(GOSYM_PREFIX GOPKGPATH ".realSyscall");
|
||||||
|
|
||||||
|
struct ret
|
||||||
|
gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||||
|
{
|
||||||
|
struct ret r;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
r.r = syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||||
|
r.err = errno;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||||
|
__asm__(GOSYM_PREFIX GOPKGPATH ".realSyscallNoError");
|
||||||
|
|
||||||
|
uintptr_t
|
||||||
|
gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||||
|
{
|
||||||
|
return syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||||
|
}
|
||||||
21
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
Normal file
21
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2015 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 gccgo && linux && amd64
|
||||||
|
// +build gccgo,linux,amd64
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
//extern gettimeofday
|
||||||
|
func realGettimeofday(*Timeval, *byte) int32
|
||||||
|
|
||||||
|
func gettimeofday(tv *Timeval) (err syscall.Errno) {
|
||||||
|
r := realGettimeofday(tv, nil)
|
||||||
|
if r < 0 {
|
||||||
|
return syscall.GetErrno()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
142
vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
Normal file
142
vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
// Copyright 2021 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 linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Helpers for dealing with ifreq since it contains a union and thus requires a
|
||||||
|
// lot of unsafe.Pointer casts to use properly.
|
||||||
|
|
||||||
|
// An Ifreq is a type-safe wrapper around the raw ifreq struct. An Ifreq
|
||||||
|
// contains an interface name and a union of arbitrary data which can be
|
||||||
|
// accessed using the Ifreq's methods. To create an Ifreq, use the NewIfreq
|
||||||
|
// function.
|
||||||
|
//
|
||||||
|
// Use the Name method to access the stored interface name. The union data
|
||||||
|
// fields can be get and set using the following methods:
|
||||||
|
// - Uint16/SetUint16: flags
|
||||||
|
// - Uint32/SetUint32: ifindex, metric, mtu
|
||||||
|
type Ifreq struct{ raw ifreq }
|
||||||
|
|
||||||
|
// NewIfreq creates an Ifreq with the input network interface name after
|
||||||
|
// validating the name does not exceed IFNAMSIZ-1 (trailing NULL required)
|
||||||
|
// bytes.
|
||||||
|
func NewIfreq(name string) (*Ifreq, error) {
|
||||||
|
// Leave room for terminating NULL byte.
|
||||||
|
if len(name) >= IFNAMSIZ {
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
var ifr ifreq
|
||||||
|
copy(ifr.Ifrn[:], name)
|
||||||
|
|
||||||
|
return &Ifreq{raw: ifr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdlayher): get/set methods for hardware address sockaddr, char array, etc.
|
||||||
|
|
||||||
|
// Name returns the interface name associated with the Ifreq.
|
||||||
|
func (ifr *Ifreq) Name() string {
|
||||||
|
return ByteSliceToString(ifr.raw.Ifrn[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to netdevice(7), only AF_INET addresses are returned for numerous
|
||||||
|
// sockaddr ioctls. For convenience, we expose these as Inet4Addr since the Port
|
||||||
|
// field and other data is always empty.
|
||||||
|
|
||||||
|
// Inet4Addr returns the Ifreq union data from an embedded sockaddr as a C
|
||||||
|
// in_addr/Go []byte (4-byte IPv4 address) value. If the sockaddr family is not
|
||||||
|
// AF_INET, an error is returned.
|
||||||
|
func (ifr *Ifreq) Inet4Addr() ([]byte, error) {
|
||||||
|
raw := *(*RawSockaddrInet4)(unsafe.Pointer(&ifr.raw.Ifru[:SizeofSockaddrInet4][0]))
|
||||||
|
if raw.Family != AF_INET {
|
||||||
|
// Cannot safely interpret raw.Addr bytes as an IPv4 address.
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw.Addr[:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInet4Addr sets a C in_addr/Go []byte (4-byte IPv4 address) value in an
|
||||||
|
// embedded sockaddr within the Ifreq's union data. v must be 4 bytes in length
|
||||||
|
// or an error will be returned.
|
||||||
|
func (ifr *Ifreq) SetInet4Addr(v []byte) error {
|
||||||
|
if len(v) != 4 {
|
||||||
|
return EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
var addr [4]byte
|
||||||
|
copy(addr[:], v)
|
||||||
|
|
||||||
|
ifr.clear()
|
||||||
|
*(*RawSockaddrInet4)(
|
||||||
|
unsafe.Pointer(&ifr.raw.Ifru[:SizeofSockaddrInet4][0]),
|
||||||
|
) = RawSockaddrInet4{
|
||||||
|
// Always set IP family as ioctls would require it anyway.
|
||||||
|
Family: AF_INET,
|
||||||
|
Addr: addr,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint16 returns the Ifreq union data as a C short/Go uint16 value.
|
||||||
|
func (ifr *Ifreq) Uint16() uint16 {
|
||||||
|
return *(*uint16)(unsafe.Pointer(&ifr.raw.Ifru[:2][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUint16 sets a C short/Go uint16 value as the Ifreq's union data.
|
||||||
|
func (ifr *Ifreq) SetUint16(v uint16) {
|
||||||
|
ifr.clear()
|
||||||
|
*(*uint16)(unsafe.Pointer(&ifr.raw.Ifru[:2][0])) = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint32 returns the Ifreq union data as a C int/Go uint32 value.
|
||||||
|
func (ifr *Ifreq) Uint32() uint32 {
|
||||||
|
return *(*uint32)(unsafe.Pointer(&ifr.raw.Ifru[:4][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUint32 sets a C int/Go uint32 value as the Ifreq's union data.
|
||||||
|
func (ifr *Ifreq) SetUint32(v uint32) {
|
||||||
|
ifr.clear()
|
||||||
|
*(*uint32)(unsafe.Pointer(&ifr.raw.Ifru[:4][0])) = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear zeroes the ifreq's union field to prevent trailing garbage data from
|
||||||
|
// being sent to the kernel if an ifreq is reused.
|
||||||
|
func (ifr *Ifreq) clear() {
|
||||||
|
for i := range ifr.raw.Ifru {
|
||||||
|
ifr.raw.Ifru[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as
|
||||||
|
// IoctlGetEthtoolDrvinfo which use these APIs under the hood.
|
||||||
|
|
||||||
|
// An ifreqData is an Ifreq which carries pointer data. To produce an ifreqData,
|
||||||
|
// use the Ifreq.withData method.
|
||||||
|
type ifreqData struct {
|
||||||
|
name [IFNAMSIZ]byte
|
||||||
|
// A type separate from ifreq is required in order to comply with the
|
||||||
|
// unsafe.Pointer rules since the "pointer-ness" of data would not be
|
||||||
|
// preserved if it were cast into the byte array of a raw ifreq.
|
||||||
|
data unsafe.Pointer
|
||||||
|
// Pad to the same size as ifreq.
|
||||||
|
_ [len(ifreq{}.Ifru) - SizeofPtr]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// withData produces an ifreqData with the pointer p set for ioctls which require
|
||||||
|
// arbitrary pointer data.
|
||||||
|
func (ifr Ifreq) withData(p unsafe.Pointer) ifreqData {
|
||||||
|
return ifreqData{
|
||||||
|
name: ifr.raw.Ifrn,
|
||||||
|
data: p,
|
||||||
|
}
|
||||||
|
}
|
||||||
75
vendor/golang.org/x/sys/unix/ioctl.go
generated
vendored
Normal file
75
vendor/golang.org/x/sys/unix/ioctl.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
// 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 aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetPointerInt performs an ioctl operation which sets an
|
||||||
|
// integer value on fd, using the specified request number. The ioctl
|
||||||
|
// argument is called with a pointer to the integer value, rather than
|
||||||
|
// passing the integer value directly.
|
||||||
|
func IoctlSetPointerInt(fd int, req uint, value int) error {
|
||||||
|
v := int32(value)
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||||
|
//
|
||||||
|
// To change fd's window size, the req argument should be TIOCSWINSZ.
|
||||||
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
|
// TODO: if we get the chance, remove the req parameter and
|
||||||
|
// hardcode TIOCSWINSZ.
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
runtime.KeepAlive(value)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetTermios performs an ioctl on fd with a *Termios.
|
||||||
|
//
|
||||||
|
// The req value will usually be TCSETA or TIOCSETA.
|
||||||
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
|
// TODO: if we get the chance, remove the req parameter.
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
runtime.KeepAlive(value)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
//
|
||||||
|
// A few ioctl requests use the return value as an output parameter;
|
||||||
|
// for those, IoctlRetInt should be used instead of this function.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
219
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
Normal file
219
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
// Copyright 2021 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 (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IoctlRetInt performs an ioctl operation specified by req on a device
|
||||||
|
// associated with opened file descriptor fd, and returns a non-negative
|
||||||
|
// integer that is returned by the ioctl syscall.
|
||||||
|
func IoctlRetInt(fd int, req uint) (int, error) {
|
||||||
|
ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0)
|
||||||
|
if err != 0 {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int(ret), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetUint32(fd int, req uint) (uint32, error) {
|
||||||
|
var value uint32
|
||||||
|
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetRTCTime(fd int) (*RTCTime, error) {
|
||||||
|
var value RTCTime
|
||||||
|
err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetRTCTime(fd int, value *RTCTime) error {
|
||||||
|
return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
|
||||||
|
var value RTCWkAlrm
|
||||||
|
err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
|
||||||
|
return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network
|
||||||
|
// device specified by ifname.
|
||||||
|
func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
|
||||||
|
ifr, err := NewIfreq(ifname)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO}
|
||||||
|
ifrd := ifr.withData(unsafe.Pointer(&value))
|
||||||
|
|
||||||
|
err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd)
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetWatchdogInfo fetches information about a watchdog device from the
|
||||||
|
// Linux watchdog API. For more information, see:
|
||||||
|
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||||
|
func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
|
||||||
|
var value WatchdogInfo
|
||||||
|
err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For
|
||||||
|
// more information, see:
|
||||||
|
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||||
|
func IoctlWatchdogKeepalive(fd int) error {
|
||||||
|
// arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr.
|
||||||
|
return ioctl(fd, WDIOC_KEEPALIVE, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the
|
||||||
|
// range of data conveyed in value to the file associated with the file
|
||||||
|
// descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
|
||||||
|
func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
|
||||||
|
return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file
|
||||||
|
// associated with the file description srcFd to the file associated with the
|
||||||
|
// file descriptor destFd. See the ioctl_ficlone(2) man page for details.
|
||||||
|
func IoctlFileClone(destFd, srcFd int) error {
|
||||||
|
return ioctl(destFd, FICLONE, uintptr(srcFd))
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileDedupeRange struct {
|
||||||
|
Src_offset uint64
|
||||||
|
Src_length uint64
|
||||||
|
Reserved1 uint16
|
||||||
|
Reserved2 uint32
|
||||||
|
Info []FileDedupeRangeInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileDedupeRangeInfo struct {
|
||||||
|
Dest_fd int64
|
||||||
|
Dest_offset uint64
|
||||||
|
Bytes_deduped uint64
|
||||||
|
Status int32
|
||||||
|
Reserved uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the
|
||||||
|
// range of data conveyed in value from the file associated with the file
|
||||||
|
// descriptor srcFd to the value.Info destinations. See the
|
||||||
|
// ioctl_fideduperange(2) man page for details.
|
||||||
|
func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
|
||||||
|
buf := make([]byte, SizeofRawFileDedupeRange+
|
||||||
|
len(value.Info)*SizeofRawFileDedupeRangeInfo)
|
||||||
|
rawrange := (*RawFileDedupeRange)(unsafe.Pointer(&buf[0]))
|
||||||
|
rawrange.Src_offset = value.Src_offset
|
||||||
|
rawrange.Src_length = value.Src_length
|
||||||
|
rawrange.Dest_count = uint16(len(value.Info))
|
||||||
|
rawrange.Reserved1 = value.Reserved1
|
||||||
|
rawrange.Reserved2 = value.Reserved2
|
||||||
|
|
||||||
|
for i := range value.Info {
|
||||||
|
rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer(
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) +
|
||||||
|
uintptr(i*SizeofRawFileDedupeRangeInfo)))
|
||||||
|
rawinfo.Dest_fd = value.Info[i].Dest_fd
|
||||||
|
rawinfo.Dest_offset = value.Info[i].Dest_offset
|
||||||
|
rawinfo.Bytes_deduped = value.Info[i].Bytes_deduped
|
||||||
|
rawinfo.Status = value.Info[i].Status
|
||||||
|
rawinfo.Reserved = value.Info[i].Reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0]))
|
||||||
|
|
||||||
|
// Output
|
||||||
|
for i := range value.Info {
|
||||||
|
rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer(
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) +
|
||||||
|
uintptr(i*SizeofRawFileDedupeRangeInfo)))
|
||||||
|
value.Info[i].Dest_fd = rawinfo.Dest_fd
|
||||||
|
value.Info[i].Dest_offset = rawinfo.Dest_offset
|
||||||
|
value.Info[i].Bytes_deduped = rawinfo.Bytes_deduped
|
||||||
|
value.Info[i].Status = rawinfo.Status
|
||||||
|
value.Info[i].Reserved = rawinfo.Reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error {
|
||||||
|
return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) {
|
||||||
|
var value HIDRawDevInfo
|
||||||
|
err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlHIDGetRawName(fd int) (string, error) {
|
||||||
|
var value [_HIDIOCGRAWNAME_LEN]byte
|
||||||
|
err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0]))
|
||||||
|
return ByteSliceToString(value[:]), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlHIDGetRawPhys(fd int) (string, error) {
|
||||||
|
var value [_HIDIOCGRAWPHYS_LEN]byte
|
||||||
|
err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0]))
|
||||||
|
return ByteSliceToString(value[:]), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlHIDGetRawUniq(fd int) (string, error) {
|
||||||
|
var value [_HIDIOCGRAWUNIQ_LEN]byte
|
||||||
|
err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0]))
|
||||||
|
return ByteSliceToString(value[:]), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlIfreq performs an ioctl using an Ifreq structure for input and/or
|
||||||
|
// output. See the netdevice(7) man page for details.
|
||||||
|
func IoctlIfreq(fd int, req uint, value *Ifreq) error {
|
||||||
|
// It is possible we will add more fields to *Ifreq itself later to prevent
|
||||||
|
// misuse, so pass the raw *ifreq directly.
|
||||||
|
return ioctlPtr(fd, req, unsafe.Pointer(&value.raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdlayher): export if and when IfreqData is exported.
|
||||||
|
|
||||||
|
// ioctlIfreqData performs an ioctl using an ifreqData structure for input
|
||||||
|
// and/or output. See the netdevice(7) man page for details.
|
||||||
|
func ioctlIfreqData(fd int, req uint, value *ifreqData) error {
|
||||||
|
// The memory layout of IfreqData (type-safe) and ifreq (not type-safe) are
|
||||||
|
// identical so pass *IfreqData directly.
|
||||||
|
return ioctlPtr(fd, req, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlKCMClone attaches a new file descriptor to a multiplexor by cloning an
|
||||||
|
// existing KCM socket, returning a structure containing the file descriptor of
|
||||||
|
// the new socket.
|
||||||
|
func IoctlKCMClone(fd int) (*KCMClone, error) {
|
||||||
|
var info KCMClone
|
||||||
|
if err := ioctlPtr(fd, SIOCKCMCLONE, unsafe.Pointer(&info)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlKCMAttach attaches a TCP socket and associated BPF program file
|
||||||
|
// descriptor to a multiplexor.
|
||||||
|
func IoctlKCMAttach(fd int, info KCMAttach) error {
|
||||||
|
return ioctlPtr(fd, SIOCKCMATTACH, unsafe.Pointer(&info))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlKCMUnattach unattaches a TCP socket file descriptor from a multiplexor.
|
||||||
|
func IoctlKCMUnattach(fd int, info KCMUnattach) error {
|
||||||
|
return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info))
|
||||||
|
}
|
||||||
74
vendor/golang.org/x/sys/unix/ioctl_zos.go
generated
vendored
Normal file
74
vendor/golang.org/x/sys/unix/ioctl_zos.go
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright 2020 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 zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||||
|
//
|
||||||
|
// To change fd's window size, the req argument should be TIOCSWINSZ.
|
||||||
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
|
// TODO: if we get the chance, remove the req parameter and
|
||||||
|
// hardcode TIOCSWINSZ.
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
runtime.KeepAlive(value)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetTermios performs an ioctl on fd with a *Termios.
|
||||||
|
//
|
||||||
|
// The req value is expected to be TCSETS, TCSETSW, or TCSETSF
|
||||||
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
|
if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) {
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
err := Tcsetattr(fd, int(req), value)
|
||||||
|
runtime.KeepAlive(value)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
//
|
||||||
|
// A few ioctl requests use the return value as an output parameter;
|
||||||
|
// for those, IoctlRetInt should be used instead of this function.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetTermios performs an ioctl on fd with a *Termios.
|
||||||
|
//
|
||||||
|
// The req value is expected to be TCGETS
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
if req != TCGETS {
|
||||||
|
return &value, ENOSYS
|
||||||
|
}
|
||||||
|
err := Tcgetattr(fd, &value)
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
236
vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
Normal file
236
vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
Normal file
|
|
@ -0,0 +1,236 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# This script runs or (given -n) prints suggested commands to generate files for
|
||||||
|
# the Architecture/OS specified by the GOARCH and GOOS environment variables.
|
||||||
|
# See README.md for more information about how the build system works.
|
||||||
|
|
||||||
|
GOOSARCH="${GOOS}_${GOARCH}"
|
||||||
|
|
||||||
|
# defaults
|
||||||
|
mksyscall="go run mksyscall.go"
|
||||||
|
mkerrors="./mkerrors.sh"
|
||||||
|
zerrors="zerrors_$GOOSARCH.go"
|
||||||
|
mksysctl=""
|
||||||
|
zsysctl="zsysctl_$GOOSARCH.go"
|
||||||
|
mksysnum=
|
||||||
|
mktypes=
|
||||||
|
mkasm=
|
||||||
|
run="sh"
|
||||||
|
cmd=""
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
-syscalls)
|
||||||
|
for i in zsyscall*go
|
||||||
|
do
|
||||||
|
# Run the command line that appears in the first line
|
||||||
|
# of the generated file to regenerate it.
|
||||||
|
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
|
||||||
|
rm _$i
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-n)
|
||||||
|
run="cat"
|
||||||
|
cmd="echo"
|
||||||
|
shift
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$#" in
|
||||||
|
0)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo 'usage: mkall.sh [-n]' 1>&2
|
||||||
|
exit 2
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$GOOS" = "linux" ]]; then
|
||||||
|
# Use the Docker-based build system
|
||||||
|
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
|
||||||
|
$cmd docker build --tag generate:$GOOS $GOOS
|
||||||
|
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
GOOSARCH_in=syscall_$GOOSARCH.go
|
||||||
|
case "$GOOSARCH" in
|
||||||
|
_* | *_ | _)
|
||||||
|
echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
aix_ppc)
|
||||||
|
mkerrors="$mkerrors -maix32"
|
||||||
|
mksyscall="go run mksyscall_aix_ppc.go -aix"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
aix_ppc64)
|
||||||
|
mkerrors="$mkerrors -maix64"
|
||||||
|
mksyscall="go run mksyscall_aix_ppc64.go -aix"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
darwin_amd64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
mkasm="go run mkasm_darwin.go"
|
||||||
|
;;
|
||||||
|
darwin_arm64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
mkasm="go run mkasm_darwin.go"
|
||||||
|
;;
|
||||||
|
dragonfly_amd64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -dragonfly"
|
||||||
|
mksysnum="go run mksysnum.go 'https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
freebsd_386)
|
||||||
|
mkerrors="$mkerrors -m32"
|
||||||
|
mksyscall="go run mksyscall.go -l32"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
freebsd_amd64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
freebsd_arm)
|
||||||
|
mkerrors="$mkerrors"
|
||||||
|
mksyscall="go run mksyscall.go -l32 -arm"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
freebsd_arm64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
freebsd_riscv64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
netbsd_386)
|
||||||
|
mkerrors="$mkerrors -m32"
|
||||||
|
mksyscall="go run mksyscall.go -l32 -netbsd"
|
||||||
|
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
netbsd_amd64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -netbsd"
|
||||||
|
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
netbsd_arm)
|
||||||
|
mkerrors="$mkerrors"
|
||||||
|
mksyscall="go run mksyscall.go -l32 -netbsd -arm"
|
||||||
|
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
netbsd_arm64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -netbsd"
|
||||||
|
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
openbsd_386)
|
||||||
|
mkerrors="$mkerrors -m32"
|
||||||
|
mksyscall="go run mksyscall.go -l32 -openbsd"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
openbsd_amd64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -openbsd"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
openbsd_arm)
|
||||||
|
mkerrors="$mkerrors"
|
||||||
|
mksyscall="go run mksyscall.go -l32 -openbsd -arm"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
openbsd_arm64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -openbsd"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
openbsd_mips64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -openbsd"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
solaris_amd64)
|
||||||
|
mksyscall="go run mksyscall_solaris.go"
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksysnum=
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
illumos_amd64)
|
||||||
|
mksyscall="go run mksyscall_solaris.go"
|
||||||
|
mkerrors=
|
||||||
|
mksysnum=
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
(
|
||||||
|
if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
|
||||||
|
case "$GOOS" in
|
||||||
|
*)
|
||||||
|
syscall_goos="syscall_$GOOS.go"
|
||||||
|
case "$GOOS" in
|
||||||
|
darwin | dragonfly | freebsd | netbsd | openbsd)
|
||||||
|
syscall_goos="syscall_bsd.go $syscall_goos"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ -n "$mksyscall" ]; then
|
||||||
|
if [ "$GOOSARCH" == "aix_ppc64" ]; then
|
||||||
|
# aix/ppc64 script generates files instead of writing to stdin.
|
||||||
|
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
|
||||||
|
elif [ "$GOOS" == "darwin" ]; then
|
||||||
|
# 1.12 and later, syscalls via libSystem
|
||||||
|
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
|
||||||
|
# 1.13 and later, syscalls via libSystem (including syscallPtr)
|
||||||
|
echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
|
||||||
|
elif [ "$GOOS" == "illumos" ]; then
|
||||||
|
# illumos code generation requires a --illumos switch
|
||||||
|
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
|
||||||
|
# illumos implies solaris, so solaris code generation is also required
|
||||||
|
echo "$mksyscall -tags solaris,$GOARCH syscall_solaris.go syscall_solaris_$GOARCH.go |gofmt >zsyscall_solaris_$GOARCH.go";
|
||||||
|
else
|
||||||
|
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
esac
|
||||||
|
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
||||||
|
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
|
||||||
|
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; fi
|
||||||
|
if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi
|
||||||
|
) | $run
|
||||||
774
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
Normal file
774
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
Normal file
|
|
@ -0,0 +1,774 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Generate Go code listing errors and other #defined constant
|
||||||
|
# values (ENAMETOOLONG etc.), by asking the preprocessor
|
||||||
|
# about the definitions.
|
||||||
|
|
||||||
|
unset LANG
|
||||||
|
export LC_ALL=C
|
||||||
|
export LC_CTYPE=C
|
||||||
|
|
||||||
|
if test -z "$GOARCH" -o -z "$GOOS"; then
|
||||||
|
echo 1>&2 "GOARCH or GOOS not defined in environment"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that we are using the new build system if we should
|
||||||
|
if [[ "$GOOS" = "linux" ]] && [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then
|
||||||
|
echo 1>&2 "In the Docker based build system, mkerrors should not be called directly."
|
||||||
|
echo 1>&2 "See README.md"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$GOOS" = "aix" ]]; then
|
||||||
|
CC=${CC:-gcc}
|
||||||
|
else
|
||||||
|
CC=${CC:-cc}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$GOOS" = "solaris" ]]; then
|
||||||
|
# Assumes GNU versions of utilities in PATH.
|
||||||
|
export PATH=/usr/gnu/bin:$PATH
|
||||||
|
fi
|
||||||
|
|
||||||
|
uname=$(uname)
|
||||||
|
|
||||||
|
includes_AIX='
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/netopt.h>
|
||||||
|
#include <netinet/ip_mroute.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
|
#include <sys/stropts.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/termio.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define AF_LOCAL AF_UNIX
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_Darwin='
|
||||||
|
#define _DARWIN_C_SOURCE
|
||||||
|
#define KERNEL 1
|
||||||
|
#define _DARWIN_USE_64_BIT_INODE
|
||||||
|
#define __APPLE_USE_RFC_3542
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/attr.h>
|
||||||
|
#include <sys/clonefile.h>
|
||||||
|
#include <sys/kern_control.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/sys_domain.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/xattr.h>
|
||||||
|
#include <sys/vsock.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk.
|
||||||
|
#define TIOCREMOTE 0x80047469
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_DragonFly='
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_clone.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <net/ip_mroute/ip_mroute.h>
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_FreeBSD='
|
||||||
|
#include <sys/capsicum.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/disk.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/sched.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ptrace.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip_mroute.h>
|
||||||
|
#include <sys/extattr.h>
|
||||||
|
|
||||||
|
#if __FreeBSD__ >= 10
|
||||||
|
#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10
|
||||||
|
#undef SIOCAIFADDR
|
||||||
|
#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data
|
||||||
|
#undef SIOCSIFPHYADDR
|
||||||
|
#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data
|
||||||
|
#endif
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_Linux='
|
||||||
|
#define _LARGEFILE_SOURCE
|
||||||
|
#define _LARGEFILE64_SOURCE
|
||||||
|
#ifndef __LP64__
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#endif
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
// <sys/ioctl.h> is broken on powerpc64, as it fails to include definitions of
|
||||||
|
// these structures. We just include them copied from <bits/termios.h>.
|
||||||
|
#if defined(__powerpc__)
|
||||||
|
struct sgttyb {
|
||||||
|
char sg_ispeed;
|
||||||
|
char sg_ospeed;
|
||||||
|
char sg_erase;
|
||||||
|
char sg_kill;
|
||||||
|
short sg_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tchars {
|
||||||
|
char t_intrc;
|
||||||
|
char t_quitc;
|
||||||
|
char t_startc;
|
||||||
|
char t_stopc;
|
||||||
|
char t_eofc;
|
||||||
|
char t_brkc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ltchars {
|
||||||
|
char t_suspc;
|
||||||
|
char t_dsuspc;
|
||||||
|
char t_rprntc;
|
||||||
|
char t_flushc;
|
||||||
|
char t_werasc;
|
||||||
|
char t_lnextc;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <bits/sockaddr.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/xattr.h>
|
||||||
|
#include <linux/audit.h>
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <linux/can.h>
|
||||||
|
#include <linux/can/error.h>
|
||||||
|
#include <linux/can/netlink.h>
|
||||||
|
#include <linux/can/raw.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/cryptouser.h>
|
||||||
|
#include <linux/devlink.h>
|
||||||
|
#include <linux/dm-ioctl.h>
|
||||||
|
#include <linux/errqueue.h>
|
||||||
|
#include <linux/ethtool_netlink.h>
|
||||||
|
#include <linux/falloc.h>
|
||||||
|
#include <linux/fanotify.h>
|
||||||
|
#include <linux/fib_rules.h>
|
||||||
|
#include <linux/filter.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/fscrypt.h>
|
||||||
|
#include <linux/fsverity.h>
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
#include <linux/hdreg.h>
|
||||||
|
#include <linux/hidraw.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_addr.h>
|
||||||
|
#include <linux/if_alg.h>
|
||||||
|
#include <linux/if_arp.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/if_ppp.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include <linux/if_xdp.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/kcm.h>
|
||||||
|
#include <linux/kexec.h>
|
||||||
|
#include <linux/keyctl.h>
|
||||||
|
#include <linux/landlock.h>
|
||||||
|
#include <linux/loop.h>
|
||||||
|
#include <linux/lwtunnel.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
|
#include <linux/memfd.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/net_namespace.h>
|
||||||
|
#include <linux/nfc.h>
|
||||||
|
#include <linux/nsfs.h>
|
||||||
|
#include <linux/perf_event.h>
|
||||||
|
#include <linux/pps.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/seccomp.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
#include <linux/taskstats.h>
|
||||||
|
#include <linux/tipc.h>
|
||||||
|
#include <linux/vm_sockets.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/watchdog.h>
|
||||||
|
#include <linux/wireguard.h>
|
||||||
|
|
||||||
|
#include <mtd/ubi-user.h>
|
||||||
|
#include <mtd/mtd-user.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
|
#if defined(__sparc__)
|
||||||
|
// On sparc{,64}, the kernel defines struct termios2 itself which clashes with the
|
||||||
|
// definition in glibc. As only the error constants are needed here, include the
|
||||||
|
// generic termibits.h (which is included by termbits.h on sparc).
|
||||||
|
#include <asm-generic/termbits.h>
|
||||||
|
#else
|
||||||
|
#include <asm/termbits.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MSG_FASTOPEN
|
||||||
|
#define MSG_FASTOPEN 0x20000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PTRACE_GETREGS
|
||||||
|
#define PTRACE_GETREGS 0xc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PTRACE_SETREGS
|
||||||
|
#define PTRACE_SETREGS 0xd
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SOL_NETLINK
|
||||||
|
#define SOL_NETLINK 270
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SOL_BLUETOOTH
|
||||||
|
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
||||||
|
// but it is already in bluetooth_linux.go
|
||||||
|
#undef SOL_BLUETOOTH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Certain constants are missing from the fs/crypto UAPI
|
||||||
|
#define FS_KEY_DESC_PREFIX "fscrypt:"
|
||||||
|
#define FS_KEY_DESC_PREFIX_SIZE 8
|
||||||
|
#define FS_MAX_KEY_SIZE 64
|
||||||
|
|
||||||
|
// The code generator produces -0x1 for (~0), but an unsigned value is necessary
|
||||||
|
// for the tipc_subscr timeout __u32 field.
|
||||||
|
#undef TIPC_WAIT_FOREVER
|
||||||
|
#define TIPC_WAIT_FOREVER 0xffffffff
|
||||||
|
|
||||||
|
// Copied from linux/l2tp.h
|
||||||
|
// Including linux/l2tp.h here causes conflicts between linux/in.h
|
||||||
|
// and netinet/in.h included via net/route.h above.
|
||||||
|
#define IPPROTO_L2TP 115
|
||||||
|
|
||||||
|
// Copied from linux/hid.h.
|
||||||
|
// Keep in sync with the size of the referenced fields.
|
||||||
|
#define _HIDIOCGRAWNAME_LEN 128 // sizeof_field(struct hid_device, name)
|
||||||
|
#define _HIDIOCGRAWPHYS_LEN 64 // sizeof_field(struct hid_device, phys)
|
||||||
|
#define _HIDIOCGRAWUNIQ_LEN 64 // sizeof_field(struct hid_device, uniq)
|
||||||
|
|
||||||
|
#define _HIDIOCGRAWNAME HIDIOCGRAWNAME(_HIDIOCGRAWNAME_LEN)
|
||||||
|
#define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN)
|
||||||
|
#define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN)
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_NetBSD='
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/extattr.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/sched.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/termios.h>
|
||||||
|
#include <sys/ttycom.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/in_systm.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip_mroute.h>
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
|
||||||
|
// Needed since <sys/param.h> refers to it...
|
||||||
|
#define schedppq 1
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_OpenBSD='
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/sched.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/termios.h>
|
||||||
|
#include <sys/ttycom.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/if_var.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/in_systm.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip_mroute.h>
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
#include <net/if_bridge.h>
|
||||||
|
|
||||||
|
// We keep some constants not supported in OpenBSD 5.5 and beyond for
|
||||||
|
// the promise of compatibility.
|
||||||
|
#define EMUL_ENABLED 0x1
|
||||||
|
#define EMUL_NATIVE 0x2
|
||||||
|
#define IPV6_FAITH 0x1d
|
||||||
|
#define IPV6_OPTIONS 0x1
|
||||||
|
#define IPV6_RTHDR_STRICT 0x1
|
||||||
|
#define IPV6_SOCKOPT_RESERVED1 0x3
|
||||||
|
#define SIOCGIFGENERIC 0xc020693a
|
||||||
|
#define SIOCSIFGENERIC 0x80206939
|
||||||
|
#define WALTSIG 0x4
|
||||||
|
'
|
||||||
|
|
||||||
|
includes_SunOS='
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/stream.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mkdev.h>
|
||||||
|
#include <net/bpf.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_arp.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip_mroute.h>
|
||||||
|
#include <termios.h>
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
includes='
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <time.h>
|
||||||
|
'
|
||||||
|
ccflags="$@"
|
||||||
|
|
||||||
|
# Write go tool cgo -godefs input.
|
||||||
|
(
|
||||||
|
echo package unix
|
||||||
|
echo
|
||||||
|
echo '/*'
|
||||||
|
indirect="includes_$(uname)"
|
||||||
|
echo "${!indirect} $includes"
|
||||||
|
echo '*/'
|
||||||
|
echo 'import "C"'
|
||||||
|
echo 'import "syscall"'
|
||||||
|
echo
|
||||||
|
echo 'const ('
|
||||||
|
|
||||||
|
# The gcc command line prints all the #defines
|
||||||
|
# it encounters while processing the input
|
||||||
|
echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '
|
||||||
|
$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
|
||||||
|
|
||||||
|
$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
|
||||||
|
$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
|
||||||
|
$2 ~ /^(SCM_SRCRT)$/ {next}
|
||||||
|
$2 ~ /^(MAP_FAILED)$/ {next}
|
||||||
|
$2 ~ /^ELF_.*$/ {next}# <asm/elf.h> contains ELF_ARCH, etc.
|
||||||
|
|
||||||
|
$2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
|
||||||
|
$2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}
|
||||||
|
|
||||||
|
$2 !~ /^ECCAPBITS/ &&
|
||||||
|
$2 !~ /^ETH_/ &&
|
||||||
|
$2 !~ /^EPROC_/ &&
|
||||||
|
$2 !~ /^EQUIV_/ &&
|
||||||
|
$2 !~ /^EXPR_/ &&
|
||||||
|
$2 !~ /^EVIOC/ &&
|
||||||
|
$2 ~ /^E[A-Z0-9_]+$/ ||
|
||||||
|
$2 ~ /^B[0-9_]+$/ ||
|
||||||
|
$2 ~ /^(OLD|NEW)DEV$/ ||
|
||||||
|
$2 == "BOTHER" ||
|
||||||
|
$2 ~ /^CI?BAUD(EX)?$/ ||
|
||||||
|
$2 == "IBSHIFT" ||
|
||||||
|
$2 ~ /^V[A-Z0-9]+$/ ||
|
||||||
|
$2 ~ /^CS[A-Z0-9]/ ||
|
||||||
|
$2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
|
||||||
|
$2 ~ /^IGN/ ||
|
||||||
|
$2 ~ /^IX(ON|ANY|OFF)$/ ||
|
||||||
|
$2 ~ /^IN(LCR|PCK)$/ ||
|
||||||
|
$2 !~ "X86_CR3_PCID_NOFLUSH" &&
|
||||||
|
$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
|
||||||
|
$2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
|
||||||
|
$2 == "BRKINT" ||
|
||||||
|
$2 == "HUPCL" ||
|
||||||
|
$2 == "PENDIN" ||
|
||||||
|
$2 == "TOSTOP" ||
|
||||||
|
$2 == "XCASE" ||
|
||||||
|
$2 == "ALTWERASE" ||
|
||||||
|
$2 == "NOKERNINFO" ||
|
||||||
|
$2 == "NFDBITS" ||
|
||||||
|
$2 ~ /^PAR/ ||
|
||||||
|
$2 ~ /^SIG[^_]/ ||
|
||||||
|
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
|
||||||
|
$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
|
||||||
|
$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
|
||||||
|
$2 ~ /^O?XTABS$/ ||
|
||||||
|
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
||||||
|
$2 ~ /^IN_/ ||
|
||||||
|
$2 ~ /^KCM/ ||
|
||||||
|
$2 ~ /^LANDLOCK_/ ||
|
||||||
|
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||||
|
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
|
||||||
|
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
|
||||||
|
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT)_/ ||
|
||||||
|
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
||||||
|
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
||||||
|
$2 ~ /^RAW_PAYLOAD_/ ||
|
||||||
|
$2 ~ /^TP_STATUS_/ ||
|
||||||
|
$2 ~ /^FALLOC_/ ||
|
||||||
|
$2 ~ /^ICMPV?6?_(FILTER|SEC)/ ||
|
||||||
|
$2 == "SOMAXCONN" ||
|
||||||
|
$2 == "NAME_MAX" ||
|
||||||
|
$2 == "IFNAMSIZ" ||
|
||||||
|
$2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
|
||||||
|
$2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
|
||||||
|
$2 ~ /^HW_MACHINE$/ ||
|
||||||
|
$2 ~ /^SYSCTL_VERS/ ||
|
||||||
|
$2 !~ "MNT_BITS" &&
|
||||||
|
$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
|
||||||
|
$2 ~ /^NS_GET_/ ||
|
||||||
|
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||||
|
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|PIOD|TFD)_/ ||
|
||||||
|
$2 ~ /^KEXEC_/ ||
|
||||||
|
$2 ~ /^LINUX_REBOOT_CMD_/ ||
|
||||||
|
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
|
||||||
|
$2 ~ /^MODULE_INIT_/ ||
|
||||||
|
$2 !~ "NLA_TYPE_MASK" &&
|
||||||
|
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
|
||||||
|
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
||||||
|
$2 ~ /^FIORDCHK$/ ||
|
||||||
|
$2 ~ /^SIOC/ ||
|
||||||
|
$2 ~ /^TIOC/ ||
|
||||||
|
$2 ~ /^TCGET/ ||
|
||||||
|
$2 ~ /^TCSET/ ||
|
||||||
|
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
|
||||||
|
$2 !~ "RTF_BITS" &&
|
||||||
|
$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
|
||||||
|
$2 ~ /^BIOC/ ||
|
||||||
|
$2 ~ /^DIOC/ ||
|
||||||
|
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
|
||||||
|
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||||
|
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||||
|
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||||
|
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
|
||||||
|
$2 ~ /^(BPF|DLT)_/ ||
|
||||||
|
$2 ~ /^AUDIT_/ ||
|
||||||
|
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||||
|
$2 ~ /^CAN_/ ||
|
||||||
|
$2 ~ /^CAP_/ ||
|
||||||
|
$2 ~ /^CP_/ ||
|
||||||
|
$2 ~ /^CPUSTATES$/ ||
|
||||||
|
$2 ~ /^CTLIOCGINFO$/ ||
|
||||||
|
$2 ~ /^ALG_/ ||
|
||||||
|
$2 ~ /^FI(CLONE|DEDUPERANGE)/ ||
|
||||||
|
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
|
||||||
|
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
|
||||||
|
$2 ~ /^FS_VERITY_/ ||
|
||||||
|
$2 ~ /^FSCRYPT_/ ||
|
||||||
|
$2 ~ /^DM_/ ||
|
||||||
|
$2 ~ /^GRND_/ ||
|
||||||
|
$2 ~ /^RND/ ||
|
||||||
|
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
||||||
|
$2 ~ /^KEYCTL_/ ||
|
||||||
|
$2 ~ /^PERF_/ ||
|
||||||
|
$2 ~ /^SECCOMP_MODE_/ ||
|
||||||
|
$2 ~ /^SEEK_/ ||
|
||||||
|
$2 ~ /^SPLICE_/ ||
|
||||||
|
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||||
|
$2 !~ /IOC_MAGIC/ &&
|
||||||
|
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
|
||||||
|
$2 ~ /^(VM|VMADDR)_/ ||
|
||||||
|
$2 ~ /^IOCTL_VM_SOCKETS_/ ||
|
||||||
|
$2 ~ /^(TASKSTATS|TS)_/ ||
|
||||||
|
$2 ~ /^CGROUPSTATS_/ ||
|
||||||
|
$2 ~ /^GENL_/ ||
|
||||||
|
$2 ~ /^STATX_/ ||
|
||||||
|
$2 ~ /^RENAME/ ||
|
||||||
|
$2 ~ /^UBI_IOC[A-Z]/ ||
|
||||||
|
$2 ~ /^UTIME_/ ||
|
||||||
|
$2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
|
||||||
|
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
|
||||||
|
$2 ~ /^FSOPT_/ ||
|
||||||
|
$2 ~ /^WDIO[CFS]_/ ||
|
||||||
|
$2 ~ /^NFN/ ||
|
||||||
|
$2 ~ /^XDP_/ ||
|
||||||
|
$2 ~ /^RWF_/ ||
|
||||||
|
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||||
|
$2 ~ /^CRYPTO_/ ||
|
||||||
|
$2 ~ /^TIPC_/ ||
|
||||||
|
$2 !~ "DEVLINK_RELOAD_LIMITS_VALID_MASK" &&
|
||||||
|
$2 ~ /^DEVLINK_/ ||
|
||||||
|
$2 ~ /^ETHTOOL_/ ||
|
||||||
|
$2 ~ /^LWTUNNEL_IP/ ||
|
||||||
|
$2 ~ /^ITIMER_/ ||
|
||||||
|
$2 !~ "WMESGLEN" &&
|
||||||
|
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||||
|
$2 ~ /^P_/ ||
|
||||||
|
$2 ~/^PPPIOC/ ||
|
||||||
|
$2 ~ /^FAN_|FANOTIFY_/ ||
|
||||||
|
$2 == "HID_MAX_DESCRIPTOR_SIZE" ||
|
||||||
|
$2 ~ /^_?HIDIOC/ ||
|
||||||
|
$2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ ||
|
||||||
|
$2 ~ /^MTD/ ||
|
||||||
|
$2 ~ /^OTP/ ||
|
||||||
|
$2 ~ /^MEM/ ||
|
||||||
|
$2 ~ /^WG/ ||
|
||||||
|
$2 ~ /^FIB_RULE_/ ||
|
||||||
|
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
|
||||||
|
$2 ~ /^__WCOREFLAG$/ {next}
|
||||||
|
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
|
||||||
|
|
||||||
|
{next}
|
||||||
|
' | sort
|
||||||
|
|
||||||
|
echo ')'
|
||||||
|
) >_const.go
|
||||||
|
|
||||||
|
# Pull out the error names for later.
|
||||||
|
errors=$(
|
||||||
|
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
|
||||||
|
sort
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull out the signal names for later.
|
||||||
|
signals=$(
|
||||||
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
||||||
|
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||||
|
sort
|
||||||
|
)
|
||||||
|
|
||||||
|
# Again, writing regexps to a file.
|
||||||
|
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||||
|
sort >_error.grep
|
||||||
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||||
|
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||||
|
sort >_signal.grep
|
||||||
|
|
||||||
|
echo '// mkerrors.sh' "$@"
|
||||||
|
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
||||||
|
echo
|
||||||
|
echo "//go:build ${GOARCH} && ${GOOS}"
|
||||||
|
echo "// +build ${GOARCH},${GOOS}"
|
||||||
|
echo
|
||||||
|
go tool cgo -godefs -- "$@" _const.go >_error.out
|
||||||
|
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
||||||
|
echo
|
||||||
|
echo '// Errors'
|
||||||
|
echo 'const ('
|
||||||
|
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/'
|
||||||
|
echo ')'
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '// Signals'
|
||||||
|
echo 'const ('
|
||||||
|
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/'
|
||||||
|
echo ')'
|
||||||
|
|
||||||
|
# Run C program to print error and syscall strings.
|
||||||
|
(
|
||||||
|
echo -E "
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
|
||||||
|
|
||||||
|
struct tuple {
|
||||||
|
int num;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tuple errors[] = {
|
||||||
|
"
|
||||||
|
for i in $errors
|
||||||
|
do
|
||||||
|
echo -E ' {'$i', "'$i'" },'
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -E "
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tuple signals[] = {
|
||||||
|
"
|
||||||
|
for i in $signals
|
||||||
|
do
|
||||||
|
echo -E ' {'$i', "'$i'" },'
|
||||||
|
done
|
||||||
|
|
||||||
|
# Use -E because on some systems bash builtin interprets \n itself.
|
||||||
|
echo -E '
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
tuplecmp(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return ((struct tuple *)a)->num - ((struct tuple *)b)->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
int i, e;
|
||||||
|
char buf[1024], *p;
|
||||||
|
|
||||||
|
printf("\n\n// Error table\n");
|
||||||
|
printf("var errorList = [...]struct {\n");
|
||||||
|
printf("\tnum syscall.Errno\n");
|
||||||
|
printf("\tname string\n");
|
||||||
|
printf("\tdesc string\n");
|
||||||
|
printf("} {\n");
|
||||||
|
qsort(errors, nelem(errors), sizeof errors[0], tuplecmp);
|
||||||
|
for(i=0; i<nelem(errors); i++) {
|
||||||
|
e = errors[i].num;
|
||||||
|
if(i > 0 && errors[i-1].num == e)
|
||||||
|
continue;
|
||||||
|
strcpy(buf, strerror(e));
|
||||||
|
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||||
|
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
|
||||||
|
buf[0] += a - A;
|
||||||
|
printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf);
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
|
||||||
|
printf("\n\n// Signal table\n");
|
||||||
|
printf("var signalList = [...]struct {\n");
|
||||||
|
printf("\tnum syscall.Signal\n");
|
||||||
|
printf("\tname string\n");
|
||||||
|
printf("\tdesc string\n");
|
||||||
|
printf("} {\n");
|
||||||
|
qsort(signals, nelem(signals), sizeof signals[0], tuplecmp);
|
||||||
|
for(i=0; i<nelem(signals); i++) {
|
||||||
|
e = signals[i].num;
|
||||||
|
if(i > 0 && signals[i-1].num == e)
|
||||||
|
continue;
|
||||||
|
strcpy(buf, strsignal(e));
|
||||||
|
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||||
|
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
|
||||||
|
buf[0] += a - A;
|
||||||
|
// cut trailing : number.
|
||||||
|
p = strrchr(buf, ":"[0]);
|
||||||
|
if(p)
|
||||||
|
*p = '\0';
|
||||||
|
printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf);
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
'
|
||||||
|
) >_errors.c
|
||||||
|
|
||||||
|
$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
|
||||||
16
vendor/golang.org/x/sys/unix/pagesize_unix.go
generated
vendored
Normal file
16
vendor/golang.org/x/sys/unix/pagesize_unix.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2017 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 aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
// For Unix, get the pagesize from the runtime.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func Getpagesize() int {
|
||||||
|
return syscall.Getpagesize()
|
||||||
|
}
|
||||||
163
vendor/golang.org/x/sys/unix/pledge_openbsd.go
generated
vendored
Normal file
163
vendor/golang.org/x/sys/unix/pledge_openbsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
// Copyright 2016 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 (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pledge implements the pledge syscall.
|
||||||
|
//
|
||||||
|
// The pledge syscall does not accept execpromises on OpenBSD releases
|
||||||
|
// before 6.3.
|
||||||
|
//
|
||||||
|
// execpromises must be empty when Pledge is called on OpenBSD
|
||||||
|
// releases predating 6.3, otherwise an error will be returned.
|
||||||
|
//
|
||||||
|
// For more information see pledge(2).
|
||||||
|
func Pledge(promises, execpromises string) error {
|
||||||
|
maj, min, err := majmin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pledgeAvailable(maj, min, execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pptr, err := syscall.BytePtrFromString(promises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable will hold either a nil unsafe.Pointer or
|
||||||
|
// an unsafe.Pointer to a string (execpromises).
|
||||||
|
var expr unsafe.Pointer
|
||||||
|
|
||||||
|
// If we're running on OpenBSD > 6.2, pass execpromises to the syscall.
|
||||||
|
if maj > 6 || (maj == 6 && min > 2) {
|
||||||
|
exptr, err := syscall.BytePtrFromString(execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expr = unsafe.Pointer(exptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PledgePromises implements the pledge syscall.
|
||||||
|
//
|
||||||
|
// This changes the promises and leaves the execpromises untouched.
|
||||||
|
//
|
||||||
|
// For more information see pledge(2).
|
||||||
|
func PledgePromises(promises string) error {
|
||||||
|
maj, min, err := majmin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pledgeAvailable(maj, min, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable holds the execpromises and is always nil.
|
||||||
|
var expr unsafe.Pointer
|
||||||
|
|
||||||
|
pptr, err := syscall.BytePtrFromString(promises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PledgeExecpromises implements the pledge syscall.
|
||||||
|
//
|
||||||
|
// This changes the execpromises and leaves the promises untouched.
|
||||||
|
//
|
||||||
|
// For more information see pledge(2).
|
||||||
|
func PledgeExecpromises(execpromises string) error {
|
||||||
|
maj, min, err := majmin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pledgeAvailable(maj, min, execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable holds the promises and is always nil.
|
||||||
|
var pptr unsafe.Pointer
|
||||||
|
|
||||||
|
exptr, err := syscall.BytePtrFromString(execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// majmin returns major and minor version number for an OpenBSD system.
|
||||||
|
func majmin() (major int, minor int, err error) {
|
||||||
|
var v Utsname
|
||||||
|
err = Uname(&v)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
major, err = strconv.Atoi(string(v.Release[0]))
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("cannot parse major version number returned by uname")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
minor, err = strconv.Atoi(string(v.Release[2]))
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("cannot parse minor version number returned by uname")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// pledgeAvailable checks for availability of the pledge(2) syscall
|
||||||
|
// based on the running OpenBSD version.
|
||||||
|
func pledgeAvailable(maj, min int, execpromises string) error {
|
||||||
|
// If OpenBSD <= 5.9, pledge is not available.
|
||||||
|
if (maj == 5 && min != 9) || maj < 5 {
|
||||||
|
return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If OpenBSD <= 6.2 and execpromises is not empty,
|
||||||
|
// return an error - execpromises is not available before 6.3
|
||||||
|
if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" {
|
||||||
|
return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
12
vendor/golang.org/x/sys/unix/ptrace_darwin.go
generated
vendored
Normal file
12
vendor/golang.org/x/sys/unix/ptrace_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2020 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 darwin && !ios
|
||||||
|
// +build darwin,!ios
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||||
|
return ptrace1(request, pid, addr, data)
|
||||||
|
}
|
||||||
12
vendor/golang.org/x/sys/unix/ptrace_ios.go
generated
vendored
Normal file
12
vendor/golang.org/x/sys/unix/ptrace_ios.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2020 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 ios
|
||||||
|
// +build ios
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
||||||
|
return ENOTSUP
|
||||||
|
}
|
||||||
31
vendor/golang.org/x/sys/unix/race.go
generated
vendored
Normal file
31
vendor/golang.org/x/sys/unix/race.go
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2012 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 (darwin && race) || (linux && race) || (freebsd && race)
|
||||||
|
// +build darwin,race linux,race freebsd,race
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const raceenabled = true
|
||||||
|
|
||||||
|
func raceAcquire(addr unsafe.Pointer) {
|
||||||
|
runtime.RaceAcquire(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||||
|
runtime.RaceReleaseMerge(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||||
|
runtime.RaceReadRange(addr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||||
|
runtime.RaceWriteRange(addr, len)
|
||||||
|
}
|
||||||
26
vendor/golang.org/x/sys/unix/race0.go
generated
vendored
Normal file
26
vendor/golang.org/x/sys/unix/race0.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2012 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 aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos
|
||||||
|
// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly zos
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const raceenabled = false
|
||||||
|
|
||||||
|
func raceAcquire(addr unsafe.Pointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReleaseMerge(addr unsafe.Pointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceReadRange(addr unsafe.Pointer, len int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func raceWriteRange(addr unsafe.Pointer, len int) {
|
||||||
|
}
|
||||||
13
vendor/golang.org/x/sys/unix/readdirent_getdents.go
generated
vendored
Normal file
13
vendor/golang.org/x/sys/unix/readdirent_getdents.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2019 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 aix || dragonfly || freebsd || linux || netbsd || openbsd
|
||||||
|
// +build aix dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// ReadDirent reads directory entries from fd and writes them into buf.
|
||||||
|
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
|
return Getdents(fd, buf)
|
||||||
|
}
|
||||||
20
vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
generated
vendored
Normal file
20
vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2019 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 darwin
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// ReadDirent reads directory entries from fd and writes them into buf.
|
||||||
|
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
|
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
||||||
|
// 64 bits should be enough. (32 bits isn't even on 386). Since the
|
||||||
|
// actual system call is getdirentries64, 64 is a good guess.
|
||||||
|
// TODO(rsc): Can we use a single global basep for all calls?
|
||||||
|
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
|
||||||
|
return Getdirentries(fd, buf, base)
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue