use go 1.13 (#8088)
* use go 1.13 * use go 1.13 in gomod file * Update Makefile * update swagger depstokarchuk/v1.17
parent
d0ad47bd5d
commit
3f5cdfe359
@ -1,219 +0,0 @@ |
|||||||
// Copyright (c) 2015 Couchbase, Inc.
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
|
||||||
// except in compliance with the License. You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
// Unless required by applicable law or agreed to in writing, software distributed under the
|
|
||||||
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
||||||
// either express or implied. See the License for the specific language governing permissions
|
|
||||||
// and limitations under the License.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"bytes" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"io" |
|
||||||
"log" |
|
||||||
"net/http" |
|
||||||
"os" |
|
||||||
"os/exec" |
|
||||||
"strconv" |
|
||||||
"strings" |
|
||||||
"unicode" |
|
||||||
) |
|
||||||
|
|
||||||
var url = flag.String("url", |
|
||||||
"http://www.unicode.org/Public/"+unicode.Version+"/ucd/auxiliary/", |
|
||||||
"URL of Unicode database directory") |
|
||||||
var verbose = flag.Bool("verbose", |
|
||||||
false, |
|
||||||
"write data to stdout as it is parsed") |
|
||||||
var localFiles = flag.Bool("local", |
|
||||||
false, |
|
||||||
"data files have been copied to the current directory; for debugging only") |
|
||||||
|
|
||||||
var outputFile = flag.String("output", |
|
||||||
"", |
|
||||||
"output file for generated tables; default stdout") |
|
||||||
|
|
||||||
var output *bufio.Writer |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Parse() |
|
||||||
setupOutput() |
|
||||||
|
|
||||||
graphemeTests := make([]test, 0) |
|
||||||
graphemeComments := make([]string, 0) |
|
||||||
graphemeTests, graphemeComments = loadUnicodeData("GraphemeBreakTest.txt", graphemeTests, graphemeComments) |
|
||||||
wordTests := make([]test, 0) |
|
||||||
wordComments := make([]string, 0) |
|
||||||
wordTests, wordComments = loadUnicodeData("WordBreakTest.txt", wordTests, wordComments) |
|
||||||
sentenceTests := make([]test, 0) |
|
||||||
sentenceComments := make([]string, 0) |
|
||||||
sentenceTests, sentenceComments = loadUnicodeData("SentenceBreakTest.txt", sentenceTests, sentenceComments) |
|
||||||
|
|
||||||
fmt.Fprintf(output, fileHeader, *url) |
|
||||||
generateTestTables("Grapheme", graphemeTests, graphemeComments) |
|
||||||
generateTestTables("Word", wordTests, wordComments) |
|
||||||
generateTestTables("Sentence", sentenceTests, sentenceComments) |
|
||||||
|
|
||||||
flushOutput() |
|
||||||
} |
|
||||||
|
|
||||||
// WordBreakProperty.txt has the form:
|
|
||||||
// 05F0..05F2 ; Hebrew_Letter # Lo [3] HEBREW LIGATURE YIDDISH DOUBLE VAV..HEBREW LIGATURE YIDDISH DOUBLE YOD
|
|
||||||
// FB1D ; Hebrew_Letter # Lo HEBREW LETTER YOD WITH HIRIQ
|
|
||||||
func openReader(file string) (input io.ReadCloser) { |
|
||||||
if *localFiles { |
|
||||||
f, err := os.Open(file) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
input = f |
|
||||||
} else { |
|
||||||
path := *url + file |
|
||||||
resp, err := http.Get(path) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
if resp.StatusCode != 200 { |
|
||||||
log.Fatal("bad GET status for "+file, resp.Status) |
|
||||||
} |
|
||||||
input = resp.Body |
|
||||||
} |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
func loadUnicodeData(filename string, tests []test, comments []string) ([]test, []string) { |
|
||||||
f := openReader(filename) |
|
||||||
defer f.Close() |
|
||||||
bufioReader := bufio.NewReader(f) |
|
||||||
line, err := bufioReader.ReadString('\n') |
|
||||||
for err == nil { |
|
||||||
tests, comments = parseLine(line, tests, comments) |
|
||||||
line, err = bufioReader.ReadString('\n') |
|
||||||
} |
|
||||||
// if the err was EOF still need to process last value
|
|
||||||
if err == io.EOF { |
|
||||||
tests, comments = parseLine(line, tests, comments) |
|
||||||
} |
|
||||||
return tests, comments |
|
||||||
} |
|
||||||
|
|
||||||
const comment = "#" |
|
||||||
const brk = "÷" |
|
||||||
const nbrk = "×" |
|
||||||
|
|
||||||
type test [][]byte |
|
||||||
|
|
||||||
func parseLine(line string, tests []test, comments []string) ([]test, []string) { |
|
||||||
if strings.HasPrefix(line, comment) { |
|
||||||
return tests, comments |
|
||||||
} |
|
||||||
line = strings.TrimSpace(line) |
|
||||||
if len(line) == 0 { |
|
||||||
return tests, comments |
|
||||||
} |
|
||||||
commentStart := strings.Index(line, comment) |
|
||||||
comment := strings.TrimSpace(line[commentStart+1:]) |
|
||||||
if commentStart > 0 { |
|
||||||
line = line[0:commentStart] |
|
||||||
} |
|
||||||
pieces := strings.Split(line, brk) |
|
||||||
t := make(test, 0) |
|
||||||
for _, piece := range pieces { |
|
||||||
piece = strings.TrimSpace(piece) |
|
||||||
if len(piece) > 0 { |
|
||||||
codePoints := strings.Split(piece, nbrk) |
|
||||||
word := "" |
|
||||||
for _, codePoint := range codePoints { |
|
||||||
codePoint = strings.TrimSpace(codePoint) |
|
||||||
r, err := strconv.ParseInt(codePoint, 16, 64) |
|
||||||
if err != nil { |
|
||||||
log.Printf("err: %v for '%s'", err, string(r)) |
|
||||||
return tests, comments |
|
||||||
} |
|
||||||
|
|
||||||
word += string(r) |
|
||||||
} |
|
||||||
t = append(t, []byte(word)) |
|
||||||
} |
|
||||||
} |
|
||||||
tests = append(tests, t) |
|
||||||
comments = append(comments, comment) |
|
||||||
return tests, comments |
|
||||||
} |
|
||||||
|
|
||||||
func generateTestTables(prefix string, tests []test, comments []string) { |
|
||||||
fmt.Fprintf(output, testHeader, prefix) |
|
||||||
for i, t := range tests { |
|
||||||
fmt.Fprintf(output, "\t\t{\n") |
|
||||||
fmt.Fprintf(output, "\t\t\tinput: %#v,\n", bytes.Join(t, []byte{})) |
|
||||||
fmt.Fprintf(output, "\t\t\toutput: %s,\n", generateTest(t)) |
|
||||||
fmt.Fprintf(output, "\t\t\tcomment: `%s`,\n", comments[i]) |
|
||||||
fmt.Fprintf(output, "\t\t},\n") |
|
||||||
} |
|
||||||
fmt.Fprintf(output, "}\n") |
|
||||||
} |
|
||||||
|
|
||||||
func generateTest(t test) string { |
|
||||||
rv := "[][]byte{" |
|
||||||
for _, te := range t { |
|
||||||
rv += fmt.Sprintf("%#v,", te) |
|
||||||
} |
|
||||||
rv += "}" |
|
||||||
return rv |
|
||||||
} |
|
||||||
|
|
||||||
const fileHeader = `// Generated by running
|
|
||||||
// maketesttables --url=%s
|
|
||||||
// DO NOT EDIT
|
|
||||||
|
|
||||||
package segment |
|
||||||
` |
|
||||||
|
|
||||||
const testHeader = `var unicode%sTests = []struct { |
|
||||||
input []byte |
|
||||||
output [][]byte |
|
||||||
comment string |
|
||||||
}{ |
|
||||||
` |
|
||||||
|
|
||||||
func setupOutput() { |
|
||||||
output = bufio.NewWriter(startGofmt()) |
|
||||||
} |
|
||||||
|
|
||||||
// startGofmt connects output to a gofmt process if -output is set.
|
|
||||||
func startGofmt() io.Writer { |
|
||||||
if *outputFile == "" { |
|
||||||
return os.Stdout |
|
||||||
} |
|
||||||
stdout, err := os.Create(*outputFile) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
// Pipe output to gofmt.
|
|
||||||
gofmt := exec.Command("gofmt") |
|
||||||
fd, err := gofmt.StdinPipe() |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
gofmt.Stdout = stdout |
|
||||||
gofmt.Stderr = os.Stderr |
|
||||||
err = gofmt.Start() |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
return fd |
|
||||||
} |
|
||||||
|
|
||||||
func flushOutput() { |
|
||||||
err := output.Flush() |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
} |
|
@ -1,13 +1,13 @@ |
|||||||
module github.com/go-openapi/analysis |
module github.com/go-openapi/analysis |
||||||
|
|
||||||
require ( |
require ( |
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect |
github.com/go-openapi/jsonpointer v0.19.3 |
||||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 // indirect |
|
||||||
github.com/go-openapi/errors v0.19.2 // indirect |
|
||||||
github.com/go-openapi/jsonpointer v0.19.2 |
|
||||||
github.com/go-openapi/loads v0.19.0 |
github.com/go-openapi/loads v0.19.0 |
||||||
github.com/go-openapi/spec v0.19.2 |
github.com/go-openapi/spec v0.19.3 |
||||||
github.com/go-openapi/strfmt v0.19.0 |
github.com/go-openapi/strfmt v0.19.3 |
||||||
github.com/go-openapi/swag v0.19.2 |
github.com/go-openapi/swag v0.19.5 |
||||||
github.com/stretchr/testify v1.3.0 |
github.com/stretchr/testify v1.3.0 |
||||||
|
go.mongodb.org/mongo-driver v1.1.1 // indirect |
||||||
) |
) |
||||||
|
|
||||||
|
go 1.13 |
||||||
|
@ -1,6 +1,9 @@ |
|||||||
module github.com/go-openapi/jsonpointer |
module github.com/go-openapi/jsonpointer |
||||||
|
|
||||||
require ( |
require ( |
||||||
github.com/go-openapi/swag v0.19.2 |
github.com/go-openapi/swag v0.19.5 |
||||||
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect |
||||||
github.com/stretchr/testify v1.3.0 |
github.com/stretchr/testify v1.3.0 |
||||||
) |
) |
||||||
|
|
||||||
|
go 1.13 |
||||||
|
@ -1,9 +1,11 @@ |
|||||||
module github.com/go-openapi/loads |
module github.com/go-openapi/loads |
||||||
|
|
||||||
require ( |
require ( |
||||||
github.com/go-openapi/analysis v0.19.2 |
github.com/go-openapi/analysis v0.19.5 |
||||||
github.com/go-openapi/spec v0.19.2 |
github.com/go-openapi/spec v0.19.3 |
||||||
github.com/go-openapi/swag v0.19.2 |
github.com/go-openapi/swag v0.19.5 |
||||||
github.com/stretchr/testify v1.3.0 |
github.com/stretchr/testify v1.3.0 |
||||||
gopkg.in/yaml.v2 v2.2.2 |
gopkg.in/yaml.v2 v2.2.2 |
||||||
) |
) |
||||||
|
|
||||||
|
go 1.13 |
||||||
|
@ -1,14 +1,17 @@ |
|||||||
module github.com/go-openapi/spec |
module github.com/go-openapi/spec |
||||||
|
|
||||||
require ( |
require ( |
||||||
github.com/go-openapi/jsonpointer v0.19.2 |
github.com/go-openapi/jsonpointer v0.19.3 |
||||||
github.com/go-openapi/jsonreference v0.19.2 |
github.com/go-openapi/jsonreference v0.19.2 |
||||||
github.com/go-openapi/swag v0.19.2 |
github.com/go-openapi/swag v0.19.5 |
||||||
github.com/kr/pty v1.1.5 // indirect |
github.com/kr/pty v1.1.5 // indirect |
||||||
github.com/stretchr/objx v0.2.0 // indirect |
github.com/stretchr/objx v0.2.0 // indirect |
||||||
github.com/stretchr/testify v1.3.0 |
github.com/stretchr/testify v1.3.0 |
||||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 // indirect |
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 // indirect |
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect |
||||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect |
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect |
||||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 // indirect |
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 // indirect |
||||||
gopkg.in/yaml.v2 v2.2.2 |
gopkg.in/yaml.v2 v2.2.2 |
||||||
) |
) |
||||||
|
|
||||||
|
go 1.13 |
||||||
|
@ -1,14 +1,17 @@ |
|||||||
module github.com/go-openapi/validate |
module github.com/go-openapi/validate |
||||||
|
|
||||||
require ( |
require ( |
||||||
github.com/go-openapi/analysis v0.19.2 |
github.com/go-openapi/analysis v0.19.4 |
||||||
github.com/go-openapi/errors v0.19.2 |
github.com/go-openapi/errors v0.19.2 |
||||||
github.com/go-openapi/jsonpointer v0.19.2 |
github.com/go-openapi/jsonpointer v0.19.3 |
||||||
github.com/go-openapi/loads v0.19.2 |
github.com/go-openapi/loads v0.19.2 |
||||||
github.com/go-openapi/runtime v0.19.0 |
github.com/go-openapi/runtime v0.19.4 |
||||||
github.com/go-openapi/spec v0.19.2 |
github.com/go-openapi/spec v0.19.3 |
||||||
github.com/go-openapi/strfmt v0.19.0 |
github.com/go-openapi/strfmt v0.19.2 |
||||||
github.com/go-openapi/swag v0.19.2 |
github.com/go-openapi/swag v0.19.5 |
||||||
github.com/stretchr/testify v1.3.0 |
github.com/stretchr/testify v1.4.0 |
||||||
|
go.mongodb.org/mongo-driver v1.1.1 // indirect |
||||||
gopkg.in/yaml.v2 v2.2.2 |
gopkg.in/yaml.v2 v2.2.2 |
||||||
) |
) |
||||||
|
|
||||||
|
go 1.13 |
||||||
|
@ -1,332 +0,0 @@ |
|||||||
// Copyright 2017 The go-github 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 ignore
|
|
||||||
|
|
||||||
// gen-accessors generates accessor methods for structs with pointer fields.
|
|
||||||
//
|
|
||||||
// It is meant to be used by the go-github authors in conjunction with the
|
|
||||||
// go generate tool before sending a commit to GitHub.
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"go/ast" |
|
||||||
"go/format" |
|
||||||
"go/parser" |
|
||||||
"go/token" |
|
||||||
"io/ioutil" |
|
||||||
"log" |
|
||||||
"os" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
"text/template" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
fileSuffix = "-accessors.go" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
verbose = flag.Bool("v", false, "Print verbose log messages") |
|
||||||
|
|
||||||
sourceTmpl = template.Must(template.New("source").Parse(source)) |
|
||||||
|
|
||||||
// blacklistStructMethod lists "struct.method" combos to skip.
|
|
||||||
blacklistStructMethod = map[string]bool{ |
|
||||||
"RepositoryContent.GetContent": true, |
|
||||||
"Client.GetBaseURL": true, |
|
||||||
"Client.GetUploadURL": true, |
|
||||||
"ErrorResponse.GetResponse": true, |
|
||||||
"RateLimitError.GetResponse": true, |
|
||||||
"AbuseRateLimitError.GetResponse": true, |
|
||||||
} |
|
||||||
// blacklistStruct lists structs to skip.
|
|
||||||
blacklistStruct = map[string]bool{ |
|
||||||
"Client": true, |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
func logf(fmt string, args ...interface{}) { |
|
||||||
if *verbose { |
|
||||||
log.Printf(fmt, args...) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Parse() |
|
||||||
fset := token.NewFileSet() |
|
||||||
|
|
||||||
pkgs, err := parser.ParseDir(fset, ".", sourceFilter, 0) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
for pkgName, pkg := range pkgs { |
|
||||||
t := &templateData{ |
|
||||||
filename: pkgName + fileSuffix, |
|
||||||
Year: 2017, |
|
||||||
Package: pkgName, |
|
||||||
Imports: map[string]string{}, |
|
||||||
} |
|
||||||
for filename, f := range pkg.Files { |
|
||||||
logf("Processing %v...", filename) |
|
||||||
if err := t.processAST(f); err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
} |
|
||||||
if err := t.dump(); err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
} |
|
||||||
logf("Done.") |
|
||||||
} |
|
||||||
|
|
||||||
func (t *templateData) processAST(f *ast.File) error { |
|
||||||
for _, decl := range f.Decls { |
|
||||||
gd, ok := decl.(*ast.GenDecl) |
|
||||||
if !ok { |
|
||||||
continue |
|
||||||
} |
|
||||||
for _, spec := range gd.Specs { |
|
||||||
ts, ok := spec.(*ast.TypeSpec) |
|
||||||
if !ok { |
|
||||||
continue |
|
||||||
} |
|
||||||
// Skip unexported identifiers.
|
|
||||||
if !ts.Name.IsExported() { |
|
||||||
logf("Struct %v is unexported; skipping.", ts.Name) |
|
||||||
continue |
|
||||||
} |
|
||||||
// Check if the struct is blacklisted.
|
|
||||||
if blacklistStruct[ts.Name.Name] { |
|
||||||
logf("Struct %v is blacklisted; skipping.", ts.Name) |
|
||||||
continue |
|
||||||
} |
|
||||||
st, ok := ts.Type.(*ast.StructType) |
|
||||||
if !ok { |
|
||||||
continue |
|
||||||
} |
|
||||||
for _, field := range st.Fields.List { |
|
||||||
se, ok := field.Type.(*ast.StarExpr) |
|
||||||
if len(field.Names) == 0 || !ok { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
fieldName := field.Names[0] |
|
||||||
// Skip unexported identifiers.
|
|
||||||
if !fieldName.IsExported() { |
|
||||||
logf("Field %v is unexported; skipping.", fieldName) |
|
||||||
continue |
|
||||||
} |
|
||||||
// Check if "struct.method" is blacklisted.
|
|
||||||
if key := fmt.Sprintf("%v.Get%v", ts.Name, fieldName); blacklistStructMethod[key] { |
|
||||||
logf("Method %v is blacklisted; skipping.", key) |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
switch x := se.X.(type) { |
|
||||||
case *ast.ArrayType: |
|
||||||
t.addArrayType(x, ts.Name.String(), fieldName.String()) |
|
||||||
case *ast.Ident: |
|
||||||
t.addIdent(x, ts.Name.String(), fieldName.String()) |
|
||||||
case *ast.MapType: |
|
||||||
t.addMapType(x, ts.Name.String(), fieldName.String()) |
|
||||||
case *ast.SelectorExpr: |
|
||||||
t.addSelectorExpr(x, ts.Name.String(), fieldName.String()) |
|
||||||
default: |
|
||||||
logf("processAST: type %q, field %q, unknown %T: %+v", ts.Name, fieldName, x, x) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func sourceFilter(fi os.FileInfo) bool { |
|
||||||
return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasSuffix(fi.Name(), fileSuffix) |
|
||||||
} |
|
||||||
|
|
||||||
func (t *templateData) dump() error { |
|
||||||
if len(t.Getters) == 0 { |
|
||||||
logf("No getters for %v; skipping.", t.filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
// Sort getters by ReceiverType.FieldName.
|
|
||||||
sort.Sort(byName(t.Getters)) |
|
||||||
|
|
||||||
var buf bytes.Buffer |
|
||||||
if err := sourceTmpl.Execute(&buf, t); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
clean, err := format.Source(buf.Bytes()) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
|
|
||||||
logf("Writing %v...", t.filename) |
|
||||||
return ioutil.WriteFile(t.filename, clean, 0644) |
|
||||||
} |
|
||||||
|
|
||||||
func newGetter(receiverType, fieldName, fieldType, zeroValue string, namedStruct bool) *getter { |
|
||||||
return &getter{ |
|
||||||
sortVal: strings.ToLower(receiverType) + "." + strings.ToLower(fieldName), |
|
||||||
ReceiverVar: strings.ToLower(receiverType[:1]), |
|
||||||
ReceiverType: receiverType, |
|
||||||
FieldName: fieldName, |
|
||||||
FieldType: fieldType, |
|
||||||
ZeroValue: zeroValue, |
|
||||||
NamedStruct: namedStruct, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (t *templateData) addArrayType(x *ast.ArrayType, receiverType, fieldName string) { |
|
||||||
var eltType string |
|
||||||
switch elt := x.Elt.(type) { |
|
||||||
case *ast.Ident: |
|
||||||
eltType = elt.String() |
|
||||||
default: |
|
||||||
logf("addArrayType: type %q, field %q: unknown elt type: %T %+v; skipping.", receiverType, fieldName, elt, elt) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
t.Getters = append(t.Getters, newGetter(receiverType, fieldName, "[]"+eltType, "nil", false)) |
|
||||||
} |
|
||||||
|
|
||||||
func (t *templateData) addIdent(x *ast.Ident, receiverType, fieldName string) { |
|
||||||
var zeroValue string |
|
||||||
var namedStruct = false |
|
||||||
switch x.String() { |
|
||||||
case "int", "int64": |
|
||||||
zeroValue = "0" |
|
||||||
case "string": |
|
||||||
zeroValue = `""` |
|
||||||
case "bool": |
|
||||||
zeroValue = "false" |
|
||||||
case "Timestamp": |
|
||||||
zeroValue = "Timestamp{}" |
|
||||||
default: |
|
||||||
zeroValue = "nil" |
|
||||||
namedStruct = true |
|
||||||
} |
|
||||||
|
|
||||||
t.Getters = append(t.Getters, newGetter(receiverType, fieldName, x.String(), zeroValue, namedStruct)) |
|
||||||
} |
|
||||||
|
|
||||||
func (t *templateData) addMapType(x *ast.MapType, receiverType, fieldName string) { |
|
||||||
var keyType string |
|
||||||
switch key := x.Key.(type) { |
|
||||||
case *ast.Ident: |
|
||||||
keyType = key.String() |
|
||||||
default: |
|
||||||
logf("addMapType: type %q, field %q: unknown key type: %T %+v; skipping.", receiverType, fieldName, key, key) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
var valueType string |
|
||||||
switch value := x.Value.(type) { |
|
||||||
case *ast.Ident: |
|
||||||
valueType = value.String() |
|
||||||
default: |
|
||||||
logf("addMapType: type %q, field %q: unknown value type: %T %+v; skipping.", receiverType, fieldName, value, value) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
fieldType := fmt.Sprintf("map[%v]%v", keyType, valueType) |
|
||||||
zeroValue := fmt.Sprintf("map[%v]%v{}", keyType, valueType) |
|
||||||
t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false)) |
|
||||||
} |
|
||||||
|
|
||||||
func (t *templateData) addSelectorExpr(x *ast.SelectorExpr, receiverType, fieldName string) { |
|
||||||
if strings.ToLower(fieldName[:1]) == fieldName[:1] { // Non-exported field.
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
var xX string |
|
||||||
if xx, ok := x.X.(*ast.Ident); ok { |
|
||||||
xX = xx.String() |
|
||||||
} |
|
||||||
|
|
||||||
switch xX { |
|
||||||
case "time", "json": |
|
||||||
if xX == "json" { |
|
||||||
t.Imports["encoding/json"] = "encoding/json" |
|
||||||
} else { |
|
||||||
t.Imports[xX] = xX |
|
||||||
} |
|
||||||
fieldType := fmt.Sprintf("%v.%v", xX, x.Sel.Name) |
|
||||||
zeroValue := fmt.Sprintf("%v.%v{}", xX, x.Sel.Name) |
|
||||||
if xX == "time" && x.Sel.Name == "Duration" { |
|
||||||
zeroValue = "0" |
|
||||||
} |
|
||||||
t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false)) |
|
||||||
default: |
|
||||||
logf("addSelectorExpr: xX %q, type %q, field %q: unknown x=%+v; skipping.", xX, receiverType, fieldName, x) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
type templateData struct { |
|
||||||
filename string |
|
||||||
Year int |
|
||||||
Package string |
|
||||||
Imports map[string]string |
|
||||||
Getters []*getter |
|
||||||
} |
|
||||||
|
|
||||||
type getter struct { |
|
||||||
sortVal string // Lower-case version of "ReceiverType.FieldName".
|
|
||||||
ReceiverVar string // The one-letter variable name to match the ReceiverType.
|
|
||||||
ReceiverType string |
|
||||||
FieldName string |
|
||||||
FieldType string |
|
||||||
ZeroValue string |
|
||||||
NamedStruct bool // Getter for named struct.
|
|
||||||
} |
|
||||||
|
|
||||||
type byName []*getter |
|
||||||
|
|
||||||
func (b byName) Len() int { return len(b) } |
|
||||||
func (b byName) Less(i, j int) bool { return b[i].sortVal < b[j].sortVal } |
|
||||||
func (b byName) Swap(i, j int) { b[i], b[j] = b[j], b[i] } |
|
||||||
|
|
||||||
const source = `// Copyright {{.Year}} The go-github AUTHORS. All rights reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Code generated by gen-accessors; DO NOT EDIT.
|
|
||||||
|
|
||||||
package {{.Package}} |
|
||||||
{{with .Imports}} |
|
||||||
import ( |
|
||||||
{{- range . -}} |
|
||||||
"{{.}}" |
|
||||||
{{end -}} |
|
||||||
) |
|
||||||
{{end}} |
|
||||||
{{range .Getters}} |
|
||||||
{{if .NamedStruct}} |
|
||||||
// Get{{.FieldName}} returns the {{.FieldName}} field.
|
|
||||||
func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() *{{.FieldType}} { |
|
||||||
if {{.ReceiverVar}} == nil { |
|
||||||
return {{.ZeroValue}} |
|
||||||
} |
|
||||||
return {{.ReceiverVar}}.{{.FieldName}} |
|
||||||
} |
|
||||||
{{else}} |
|
||||||
// Get{{.FieldName}} returns the {{.FieldName}} field if it's non-nil, zero value otherwise.
|
|
||||||
func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() {{.FieldType}} { |
|
||||||
if {{.ReceiverVar}} == nil || {{.ReceiverVar}}.{{.FieldName}} == nil { |
|
||||||
return {{.ZeroValue}} |
|
||||||
} |
|
||||||
return *{{.ReceiverVar}}.{{.FieldName}} |
|
||||||
} |
|
||||||
{{end}} |
|
||||||
{{end}} |
|
||||||
` |
|
@ -1,265 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// This program generates fixedhuff.go
|
|
||||||
// Invoke as
|
|
||||||
//
|
|
||||||
// go run gen.go -output fixedhuff.go
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"go/format" |
|
||||||
"io/ioutil" |
|
||||||
"log" |
|
||||||
) |
|
||||||
|
|
||||||
var filename = flag.String("output", "fixedhuff.go", "output file name") |
|
||||||
|
|
||||||
const maxCodeLen = 16 |
|
||||||
|
|
||||||
// Note: the definition of the huffmanDecoder struct is copied from
|
|
||||||
// inflate.go, as it is private to the implementation.
|
|
||||||
|
|
||||||
// chunk & 15 is number of bits
|
|
||||||
// chunk >> 4 is value, including table link
|
|
||||||
|
|
||||||
const ( |
|
||||||
huffmanChunkBits = 9 |
|
||||||
huffmanNumChunks = 1 << huffmanChunkBits |
|
||||||
huffmanCountMask = 15 |
|
||||||
huffmanValueShift = 4 |
|
||||||
) |
|
||||||
|
|
||||||
type huffmanDecoder struct { |
|
||||||
min int // the minimum code length
|
|
||||||
chunks [huffmanNumChunks]uint32 // chunks as described above
|
|
||||||
links [][]uint32 // overflow links
|
|
||||||
linkMask uint32 // mask the width of the link table
|
|
||||||
} |
|
||||||
|
|
||||||
// Initialize Huffman decoding tables from array of code lengths.
|
|
||||||
// Following this function, h is guaranteed to be initialized into a complete
|
|
||||||
// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a
|
|
||||||
// degenerate case where the tree has only a single symbol with length 1. Empty
|
|
||||||
// trees are permitted.
|
|
||||||
func (h *huffmanDecoder) init(bits []int) bool { |
|
||||||
// Sanity enables additional runtime tests during Huffman
|
|
||||||
// table construction. It's intended to be used during
|
|
||||||
// development to supplement the currently ad-hoc unit tests.
|
|
||||||
const sanity = false |
|
||||||
|
|
||||||
if h.min != 0 { |
|
||||||
*h = huffmanDecoder{} |
|
||||||
} |
|
||||||
|
|
||||||
// Count number of codes of each length,
|
|
||||||
// compute min and max length.
|
|
||||||
var count [maxCodeLen]int |
|
||||||
var min, max int |
|
||||||
for _, n := range bits { |
|
||||||
if n == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
if min == 0 || n < min { |
|
||||||
min = n |
|
||||||
} |
|
||||||
if n > max { |
|
||||||
max = n |
|
||||||
} |
|
||||||
count[n]++ |
|
||||||
} |
|
||||||
|
|
||||||
// Empty tree. The decompressor.huffSym function will fail later if the tree
|
|
||||||
// is used. Technically, an empty tree is only valid for the HDIST tree and
|
|
||||||
// not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree
|
|
||||||
// is guaranteed to fail since it will attempt to use the tree to decode the
|
|
||||||
// codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is
|
|
||||||
// guaranteed to fail later since the compressed data section must be
|
|
||||||
// composed of at least one symbol (the end-of-block marker).
|
|
||||||
if max == 0 { |
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
code := 0 |
|
||||||
var nextcode [maxCodeLen]int |
|
||||||
for i := min; i <= max; i++ { |
|
||||||
code <<= 1 |
|
||||||
nextcode[i] = code |
|
||||||
code += count[i] |
|
||||||
} |
|
||||||
|
|
||||||
// Check that the coding is complete (i.e., that we've
|
|
||||||
// assigned all 2-to-the-max possible bit sequences).
|
|
||||||
// Exception: To be compatible with zlib, we also need to
|
|
||||||
// accept degenerate single-code codings. See also
|
|
||||||
// TestDegenerateHuffmanCoding.
|
|
||||||
if code != 1<<uint(max) && !(code == 1 && max == 1) { |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
h.min = min |
|
||||||
if max > huffmanChunkBits { |
|
||||||
numLinks := 1 << (uint(max) - huffmanChunkBits) |
|
||||||
h.linkMask = uint32(numLinks - 1) |
|
||||||
|
|
||||||
// create link tables
|
|
||||||
link := nextcode[huffmanChunkBits+1] >> 1 |
|
||||||
h.links = make([][]uint32, huffmanNumChunks-link) |
|
||||||
for j := uint(link); j < huffmanNumChunks; j++ { |
|
||||||
reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8 |
|
||||||
reverse >>= uint(16 - huffmanChunkBits) |
|
||||||
off := j - uint(link) |
|
||||||
if sanity && h.chunks[reverse] != 0 { |
|
||||||
panic("impossible: overwriting existing chunk") |
|
||||||
} |
|
||||||
h.chunks[reverse] = uint32(off<<huffmanValueShift | (huffmanChunkBits + 1)) |
|
||||||
h.links[off] = make([]uint32, numLinks) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
for i, n := range bits { |
|
||||||
if n == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
code := nextcode[n] |
|
||||||
nextcode[n]++ |
|
||||||
chunk := uint32(i<<huffmanValueShift | n) |
|
||||||
reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8 |
|
||||||
reverse >>= uint(16 - n) |
|
||||||
if n <= huffmanChunkBits { |
|
||||||
for off := reverse; off < len(h.chunks); off += 1 << uint(n) { |
|
||||||
// We should never need to overwrite
|
|
||||||
// an existing chunk. Also, 0 is
|
|
||||||
// never a valid chunk, because the
|
|
||||||
// lower 4 "count" bits should be
|
|
||||||
// between 1 and 15.
|
|
||||||
if sanity && h.chunks[off] != 0 { |
|
||||||
panic("impossible: overwriting existing chunk") |
|
||||||
} |
|
||||||
h.chunks[off] = chunk |
|
||||||
} |
|
||||||
} else { |
|
||||||
j := reverse & (huffmanNumChunks - 1) |
|
||||||
if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 { |
|
||||||
// Longer codes should have been
|
|
||||||
// associated with a link table above.
|
|
||||||
panic("impossible: not an indirect chunk") |
|
||||||
} |
|
||||||
value := h.chunks[j] >> huffmanValueShift |
|
||||||
linktab := h.links[value] |
|
||||||
reverse >>= huffmanChunkBits |
|
||||||
for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) { |
|
||||||
if sanity && linktab[off] != 0 { |
|
||||||
panic("impossible: overwriting existing chunk") |
|
||||||
} |
|
||||||
linktab[off] = chunk |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if sanity { |
|
||||||
// Above we've sanity checked that we never overwrote
|
|
||||||
// an existing entry. Here we additionally check that
|
|
||||||
// we filled the tables completely.
|
|
||||||
for i, chunk := range h.chunks { |
|
||||||
if chunk == 0 { |
|
||||||
// As an exception, in the degenerate
|
|
||||||
// single-code case, we allow odd
|
|
||||||
// chunks to be missing.
|
|
||||||
if code == 1 && i%2 == 1 { |
|
||||||
continue |
|
||||||
} |
|
||||||
panic("impossible: missing chunk") |
|
||||||
} |
|
||||||
} |
|
||||||
for _, linktab := range h.links { |
|
||||||
for _, chunk := range linktab { |
|
||||||
if chunk == 0 { |
|
||||||
panic("impossible: missing chunk") |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Parse() |
|
||||||
|
|
||||||
var h huffmanDecoder |
|
||||||
var bits [288]int |
|
||||||
initReverseByte() |
|
||||||
for i := 0; i < 144; i++ { |
|
||||||
bits[i] = 8 |
|
||||||
} |
|
||||||
for i := 144; i < 256; i++ { |
|
||||||
bits[i] = 9 |
|
||||||
} |
|
||||||
for i := 256; i < 280; i++ { |
|
||||||
bits[i] = 7 |
|
||||||
} |
|
||||||
for i := 280; i < 288; i++ { |
|
||||||
bits[i] = 8 |
|
||||||
} |
|
||||||
h.init(bits[:]) |
|
||||||
if h.links != nil { |
|
||||||
log.Fatal("Unexpected links table in fixed Huffman decoder") |
|
||||||
} |
|
||||||
|
|
||||||
var buf bytes.Buffer |
|
||||||
|
|
||||||
fmt.Fprintf(&buf, `// Copyright 2013 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.`+"\n\n")
|
|
||||||
|
|
||||||
fmt.Fprintln(&buf, "package flate") |
|
||||||
fmt.Fprintln(&buf) |
|
||||||
fmt.Fprintln(&buf, "// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT") |
|
||||||
fmt.Fprintln(&buf) |
|
||||||
fmt.Fprintln(&buf, "var fixedHuffmanDecoder = huffmanDecoder{") |
|
||||||
fmt.Fprintf(&buf, "\t%d,\n", h.min) |
|
||||||
fmt.Fprintln(&buf, "\t[huffmanNumChunks]uint32{") |
|
||||||
for i := 0; i < huffmanNumChunks; i++ { |
|
||||||
if i&7 == 0 { |
|
||||||
fmt.Fprintf(&buf, "\t\t") |
|
||||||
} else { |
|
||||||
fmt.Fprintf(&buf, " ") |
|
||||||
} |
|
||||||
fmt.Fprintf(&buf, "0x%04x,", h.chunks[i]) |
|
||||||
if i&7 == 7 { |
|
||||||
fmt.Fprintln(&buf) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Fprintln(&buf, "\t},") |
|
||||||
fmt.Fprintln(&buf, "\tnil, 0,") |
|
||||||
fmt.Fprintln(&buf, "}") |
|
||||||
|
|
||||||
data, err := format.Source(buf.Bytes()) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
err = ioutil.WriteFile(*filename, data, 0644) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
var reverseByte [256]byte |
|
||||||
|
|
||||||
func initReverseByte() { |
|
||||||
for x := 0; x < 256; x++ { |
|
||||||
var result byte |
|
||||||
for i := uint(0); i < 8; i++ { |
|
||||||
result |= byte(((x >> i) & 1) << (7 - i)) |
|
||||||
} |
|
||||||
reverseByte[x] = result |
|
||||||
} |
|
||||||
} |
|
@ -1,476 +0,0 @@ |
|||||||
// +build ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"fmt" |
|
||||||
"go/ast" |
|
||||||
"go/parser" |
|
||||||
"go/printer" |
|
||||||
"go/token" |
|
||||||
"io" |
|
||||||
"io/ioutil" |
|
||||||
"log" |
|
||||||
"os" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
"unicode" |
|
||||||
"unicode/utf8" |
|
||||||
) |
|
||||||
|
|
||||||
var inFiles = []string{"cpuid.go", "cpuid_test.go"} |
|
||||||
var copyFiles = []string{"cpuid_amd64.s", "cpuid_386.s", "detect_ref.go", "detect_intel.go"} |
|
||||||
var fileSet = token.NewFileSet() |
|
||||||
var reWrites = []rewrite{ |
|
||||||
initRewrite("CPUInfo -> cpuInfo"), |
|
||||||
initRewrite("Vendor -> vendor"), |
|
||||||
initRewrite("Flags -> flags"), |
|
||||||
initRewrite("Detect -> detect"), |
|
||||||
initRewrite("CPU -> cpu"), |
|
||||||
} |
|
||||||
var excludeNames = map[string]bool{"string": true, "join": true, "trim": true, |
|
||||||
// cpuid_test.go
|
|
||||||
"t": true, "println": true, "logf": true, "log": true, "fatalf": true, "fatal": true, |
|
||||||
} |
|
||||||
|
|
||||||
var excludePrefixes = []string{"test", "benchmark"} |
|
||||||
|
|
||||||
func main() { |
|
||||||
Package := "private" |
|
||||||
parserMode := parser.ParseComments |
|
||||||
exported := make(map[string]rewrite) |
|
||||||
for _, file := range inFiles { |
|
||||||
in, err := os.Open(file) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("opening input", err) |
|
||||||
} |
|
||||||
|
|
||||||
src, err := ioutil.ReadAll(in) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("reading input", err) |
|
||||||
} |
|
||||||
|
|
||||||
astfile, err := parser.ParseFile(fileSet, file, src, parserMode) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("parsing input", err) |
|
||||||
} |
|
||||||
|
|
||||||
for _, rw := range reWrites { |
|
||||||
astfile = rw(astfile) |
|
||||||
} |
|
||||||
|
|
||||||
// Inspect the AST and print all identifiers and literals.
|
|
||||||
var startDecl token.Pos |
|
||||||
var endDecl token.Pos |
|
||||||
ast.Inspect(astfile, func(n ast.Node) bool { |
|
||||||
var s string |
|
||||||
switch x := n.(type) { |
|
||||||
case *ast.Ident: |
|
||||||
if x.IsExported() { |
|
||||||
t := strings.ToLower(x.Name) |
|
||||||
for _, pre := range excludePrefixes { |
|
||||||
if strings.HasPrefix(t, pre) { |
|
||||||
return true |
|
||||||
} |
|
||||||
} |
|
||||||
if excludeNames[t] != true { |
|
||||||
//if x.Pos() > startDecl && x.Pos() < endDecl {
|
|
||||||
exported[x.Name] = initRewrite(x.Name + " -> " + t) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
case *ast.GenDecl: |
|
||||||
if x.Tok == token.CONST && x.Lparen > 0 { |
|
||||||
startDecl = x.Lparen |
|
||||||
endDecl = x.Rparen |
|
||||||
// fmt.Printf("Decl:%s -> %s\n", fileSet.Position(startDecl), fileSet.Position(endDecl))
|
|
||||||
} |
|
||||||
} |
|
||||||
if s != "" { |
|
||||||
fmt.Printf("%s:\t%s\n", fileSet.Position(n.Pos()), s) |
|
||||||
} |
|
||||||
return true |
|
||||||
}) |
|
||||||
|
|
||||||
for _, rw := range exported { |
|
||||||
astfile = rw(astfile) |
|
||||||
} |
|
||||||
|
|
||||||
var buf bytes.Buffer |
|
||||||
|
|
||||||
printer.Fprint(&buf, fileSet, astfile) |
|
||||||
|
|
||||||
// Remove package documentation and insert information
|
|
||||||
s := buf.String() |
|
||||||
ind := strings.Index(buf.String(), "\npackage cpuid") |
|
||||||
s = s[ind:] |
|
||||||
s = "// Generated, DO NOT EDIT,\n" + |
|
||||||
"// but copy it to your own project and rename the package.\n" + |
|
||||||
"// See more at http://github.com/klauspost/cpuid\n" + |
|
||||||
s |
|
||||||
|
|
||||||
outputName := Package + string(os.PathSeparator) + file |
|
||||||
|
|
||||||
err = ioutil.WriteFile(outputName, []byte(s), 0644) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("writing output: %s", err) |
|
||||||
} |
|
||||||
log.Println("Generated", outputName) |
|
||||||
} |
|
||||||
|
|
||||||
for _, file := range copyFiles { |
|
||||||
dst := "" |
|
||||||
if strings.HasPrefix(file, "cpuid") { |
|
||||||
dst = Package + string(os.PathSeparator) + file |
|
||||||
} else { |
|
||||||
dst = Package + string(os.PathSeparator) + "cpuid_" + file |
|
||||||
} |
|
||||||
err := copyFile(file, dst) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("copying file: %s", err) |
|
||||||
} |
|
||||||
log.Println("Copied", dst) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// CopyFile copies a file from src to dst. If src and dst files exist, and are
|
|
||||||
// the same, then return success. Copy the file contents from src to dst.
|
|
||||||
func copyFile(src, dst string) (err error) { |
|
||||||
sfi, err := os.Stat(src) |
|
||||||
if err != nil { |
|
||||||
return |
|
||||||
} |
|
||||||
if !sfi.Mode().IsRegular() { |
|
||||||
// cannot copy non-regular files (e.g., directories,
|
|
||||||
// symlinks, devices, etc.)
|
|
||||||
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String()) |
|
||||||
} |
|
||||||
dfi, err := os.Stat(dst) |
|
||||||
if err != nil { |
|
||||||
if !os.IsNotExist(err) { |
|
||||||
return |
|
||||||
} |
|
||||||
} else { |
|
||||||
if !(dfi.Mode().IsRegular()) { |
|
||||||
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String()) |
|
||||||
} |
|
||||||
if os.SameFile(sfi, dfi) { |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
err = copyFileContents(src, dst) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// copyFileContents copies the contents of the file named src to the file named
|
|
||||||
// by dst. The file will be created if it does not already exist. If the
|
|
||||||
// destination file exists, all it's contents will be replaced by the contents
|
|
||||||
// of the source file.
|
|
||||||
func copyFileContents(src, dst string) (err error) { |
|
||||||
in, err := os.Open(src) |
|
||||||
if err != nil { |
|
||||||
return |
|
||||||
} |
|
||||||
defer in.Close() |
|
||||||
out, err := os.Create(dst) |
|
||||||
if err != nil { |
|
||||||
return |
|
||||||
} |
|
||||||
defer func() { |
|
||||||
cerr := out.Close() |
|
||||||
if err == nil { |
|
||||||
err = cerr |
|
||||||
} |
|
||||||
}() |
|
||||||
if _, err = io.Copy(out, in); err != nil { |
|
||||||
return |
|
||||||
} |
|
||||||
err = out.Sync() |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
type rewrite func(*ast.File) *ast.File |
|
||||||
|
|
||||||
// Mostly copied from gofmt
|
|
||||||
func initRewrite(rewriteRule string) rewrite { |
|
||||||
f := strings.Split(rewriteRule, "->") |
|
||||||
if len(f) != 2 { |
|
||||||
fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n") |
|
||||||
os.Exit(2) |
|
||||||
} |
|
||||||
pattern := parseExpr(f[0], "pattern") |
|
||||||
replace := parseExpr(f[1], "replacement") |
|
||||||
return func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) } |
|
||||||
} |
|
||||||
|
|
||||||
// parseExpr parses s as an expression.
|
|
||||||
// It might make sense to expand this to allow statement patterns,
|
|
||||||
// but there are problems with preserving formatting and also
|
|
||||||
// with what a wildcard for a statement looks like.
|
|
||||||
func parseExpr(s, what string) ast.Expr { |
|
||||||
x, err := parser.ParseExpr(s) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err) |
|
||||||
os.Exit(2) |
|
||||||
} |
|
||||||
return x |
|
||||||
} |
|
||||||
|
|
||||||
// Keep this function for debugging.
|
|
||||||
/* |
|
||||||
func dump(msg string, val reflect.Value) { |
|
||||||
fmt.Printf("%s:\n", msg) |
|
||||||
ast.Print(fileSet, val.Interface()) |
|
||||||
fmt.Println() |
|
||||||
} |
|
||||||
*/ |
|
||||||
|
|
||||||
// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
|
|
||||||
func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File { |
|
||||||
cmap := ast.NewCommentMap(fileSet, p, p.Comments) |
|
||||||
m := make(map[string]reflect.Value) |
|
||||||
pat := reflect.ValueOf(pattern) |
|
||||||
repl := reflect.ValueOf(replace) |
|
||||||
|
|
||||||
var rewriteVal func(val reflect.Value) reflect.Value |
|
||||||
rewriteVal = func(val reflect.Value) reflect.Value { |
|
||||||
// don't bother if val is invalid to start with
|
|
||||||
if !val.IsValid() { |
|
||||||
return reflect.Value{} |
|
||||||
} |
|
||||||
for k := range m { |
|
||||||
delete(m, k) |
|
||||||
} |
|
||||||
val = apply(rewriteVal, val) |
|
||||||
if match(m, pat, val) { |
|
||||||
val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos())) |
|
||||||
} |
|
||||||
return val |
|
||||||
} |
|
||||||
|
|
||||||
r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File) |
|
||||||
r.Comments = cmap.Filter(r).Comments() // recreate comments list
|
|
||||||
return r |
|
||||||
} |
|
||||||
|
|
||||||
// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y.
|
|
||||||
func set(x, y reflect.Value) { |
|
||||||
// don't bother if x cannot be set or y is invalid
|
|
||||||
if !x.CanSet() || !y.IsValid() { |
|
||||||
return |
|
||||||
} |
|
||||||
defer func() { |
|
||||||
if x := recover(); x != nil { |
|
||||||
if s, ok := x.(string); ok && |
|
||||||
(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) { |
|
||||||
// x cannot be set to y - ignore this rewrite
|
|
||||||
return |
|
||||||
} |
|
||||||
panic(x) |
|
||||||
} |
|
||||||
}() |
|
||||||
x.Set(y) |
|
||||||
} |
|
||||||
|
|
||||||
// Values/types for special cases.
|
|
||||||
var ( |
|
||||||
objectPtrNil = reflect.ValueOf((*ast.Object)(nil)) |
|
||||||
scopePtrNil = reflect.ValueOf((*ast.Scope)(nil)) |
|
||||||
|
|
||||||
identType = reflect.TypeOf((*ast.Ident)(nil)) |
|
||||||
objectPtrType = reflect.TypeOf((*ast.Object)(nil)) |
|
||||||
positionType = reflect.TypeOf(token.NoPos) |
|
||||||
callExprType = reflect.TypeOf((*ast.CallExpr)(nil)) |
|
||||||
scopePtrType = reflect.TypeOf((*ast.Scope)(nil)) |
|
||||||
) |
|
||||||
|
|
||||||
// apply replaces each AST field x in val with f(x), returning val.
|
|
||||||
// To avoid extra conversions, f operates on the reflect.Value form.
|
|
||||||
func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value { |
|
||||||
if !val.IsValid() { |
|
||||||
return reflect.Value{} |
|
||||||
} |
|
||||||
|
|
||||||
// *ast.Objects introduce cycles and are likely incorrect after
|
|
||||||
// rewrite; don't follow them but replace with nil instead
|
|
||||||
if val.Type() == objectPtrType { |
|
||||||
return objectPtrNil |
|
||||||
} |
|
||||||
|
|
||||||
// similarly for scopes: they are likely incorrect after a rewrite;
|
|
||||||
// replace them with nil
|
|
||||||
if val.Type() == scopePtrType { |
|
||||||
return scopePtrNil |
|
||||||
} |
|
||||||
|
|
||||||
switch v := reflect.Indirect(val); v.Kind() { |
|
||||||
case reflect.Slice: |
|
||||||
for i := 0; i < v.Len(); i++ { |
|
||||||
e := v.Index(i) |
|
||||||
set(e, f(e)) |
|
||||||
} |
|
||||||
case reflect.Struct: |
|
||||||
for i := 0; i < v.NumField(); i++ { |
|
||||||
e := v.Field(i) |
|
||||||
set(e, f(e)) |
|
||||||
} |
|
||||||
case reflect.Interface: |
|
||||||
e := v.Elem() |
|
||||||
set(v, f(e)) |
|
||||||
} |
|
||||||
return val |
|
||||||
} |
|
||||||
|
|
||||||
func isWildcard(s string) bool { |
|
||||||
rune, size := utf8.DecodeRuneInString(s) |
|
||||||
return size == len(s) && unicode.IsLower(rune) |
|
||||||
} |
|
||||||
|
|
||||||
// match returns true if pattern matches val,
|
|
||||||
// recording wildcard submatches in m.
|
|
||||||
// If m == nil, match checks whether pattern == val.
|
|
||||||
func match(m map[string]reflect.Value, pattern, val reflect.Value) bool { |
|
||||||
// Wildcard matches any expression. If it appears multiple
|
|
||||||
// times in the pattern, it must match the same expression
|
|
||||||
// each time.
|
|
||||||
if m != nil && pattern.IsValid() && pattern.Type() == identType { |
|
||||||
name := pattern.Interface().(*ast.Ident).Name |
|
||||||
if isWildcard(name) && val.IsValid() { |
|
||||||
// wildcards only match valid (non-nil) expressions.
|
|
||||||
if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() { |
|
||||||
if old, ok := m[name]; ok { |
|
||||||
return match(nil, old, val) |
|
||||||
} |
|
||||||
m[name] = val |
|
||||||
return true |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Otherwise, pattern and val must match recursively.
|
|
||||||
if !pattern.IsValid() || !val.IsValid() { |
|
||||||
return !pattern.IsValid() && !val.IsValid() |
|
||||||
} |
|
||||||
if pattern.Type() != val.Type() { |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
// Special cases.
|
|
||||||
switch pattern.Type() { |
|
||||||
case identType: |
|
||||||
// For identifiers, only the names need to match
|
|
||||||
// (and none of the other *ast.Object information).
|
|
||||||
// This is a common case, handle it all here instead
|
|
||||||
// of recursing down any further via reflection.
|
|
||||||
p := pattern.Interface().(*ast.Ident) |
|
||||||
v := val.Interface().(*ast.Ident) |
|
||||||
return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name |
|
||||||
case objectPtrType, positionType: |
|
||||||
// object pointers and token positions always match
|
|
||||||
return true |
|
||||||
case callExprType: |
|
||||||
// For calls, the Ellipsis fields (token.Position) must
|
|
||||||
// match since that is how f(x) and f(x...) are different.
|
|
||||||
// Check them here but fall through for the remaining fields.
|
|
||||||
p := pattern.Interface().(*ast.CallExpr) |
|
||||||
v := val.Interface().(*ast.CallExpr) |
|
||||||
if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() { |
|
||||||
return false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
p := reflect.Indirect(pattern) |
|
||||||
v := reflect.Indirect(val) |
|
||||||
if !p.IsValid() || !v.IsValid() { |
|
||||||
return !p.IsValid() && !v.IsValid() |
|
||||||
} |
|
||||||
|
|
||||||
switch p.Kind() { |
|
||||||
case reflect.Slice: |
|
||||||
if p.Len() != v.Len() { |
|
||||||
return false |
|
||||||
} |
|
||||||
for i := 0; i < p.Len(); i++ { |
|
||||||
if !match(m, p.Index(i), v.Index(i)) { |
|
||||||
return false |
|
||||||
} |
|
||||||
} |
|
||||||
return true |
|
||||||
|
|
||||||
case reflect.Struct: |
|
||||||
for i := 0; i < p.NumField(); i++ { |
|
||||||
if !match(m, p.Field(i), v.Field(i)) { |
|
||||||
return false |
|
||||||
} |
|
||||||
} |
|
||||||
return true |
|
||||||
|
|
||||||
case reflect.Interface: |
|
||||||
return match(m, p.Elem(), v.Elem()) |
|
||||||
} |
|
||||||
|
|
||||||
// Handle token integers, etc.
|
|
||||||
return p.Interface() == v.Interface() |
|
||||||
} |
|
||||||
|
|
||||||
// subst returns a copy of pattern with values from m substituted in place
|
|
||||||
// of wildcards and pos used as the position of tokens from the pattern.
|
|
||||||
// if m == nil, subst returns a copy of pattern and doesn't change the line
|
|
||||||
// number information.
|
|
||||||
func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value { |
|
||||||
if !pattern.IsValid() { |
|
||||||
return reflect.Value{} |
|
||||||
} |
|
||||||
|
|
||||||
// Wildcard gets replaced with map value.
|
|
||||||
if m != nil && pattern.Type() == identType { |
|
||||||
name := pattern.Interface().(*ast.Ident).Name |
|
||||||
if isWildcard(name) { |
|
||||||
if old, ok := m[name]; ok { |
|
||||||
return subst(nil, old, reflect.Value{}) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if pos.IsValid() && pattern.Type() == positionType { |
|
||||||
// use new position only if old position was valid in the first place
|
|
||||||
if old := pattern.Interface().(token.Pos); !old.IsValid() { |
|
||||||
return pattern |
|
||||||
} |
|
||||||
return pos |
|
||||||
} |
|
||||||
|
|
||||||
// Otherwise copy.
|
|
||||||
switch p := pattern; p.Kind() { |
|
||||||
case reflect.Slice: |
|
||||||
v := reflect.MakeSlice(p.Type(), p.Len(), p.Len()) |
|
||||||
for i := 0; i < p.Len(); i++ { |
|
||||||
v.Index(i).Set(subst(m, p.Index(i), pos)) |
|
||||||
} |
|
||||||
return v |
|
||||||
|
|
||||||
case reflect.Struct: |
|
||||||
v := reflect.New(p.Type()).Elem() |
|
||||||
for i := 0; i < p.NumField(); i++ { |
|
||||||
v.Field(i).Set(subst(m, p.Field(i), pos)) |
|
||||||
} |
|
||||||
return v |
|
||||||
|
|
||||||
case reflect.Ptr: |
|
||||||
v := reflect.New(p.Type()).Elem() |
|
||||||
if elem := p.Elem(); elem.IsValid() { |
|
||||||
v.Set(subst(m, elem, pos).Addr()) |
|
||||||
} |
|
||||||
return v |
|
||||||
|
|
||||||
case reflect.Interface: |
|
||||||
v := reflect.New(p.Type()).Elem() |
|
||||||
if elem := p.Elem(); elem.IsValid() { |
|
||||||
v.Set(subst(m, elem, pos)) |
|
||||||
} |
|
||||||
return v |
|
||||||
} |
|
||||||
|
|
||||||
return pattern |
|
||||||
} |
|
@ -1,93 +0,0 @@ |
|||||||
// +build ignore
|
|
||||||
|
|
||||||
// Generate the table of OID values
|
|
||||||
// Run with 'go run gen.go'.
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"database/sql" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"os" |
|
||||||
"os/exec" |
|
||||||
"strings" |
|
||||||
|
|
||||||
_ "github.com/lib/pq" |
|
||||||
) |
|
||||||
|
|
||||||
// OID represent a postgres Object Identifier Type.
|
|
||||||
type OID struct { |
|
||||||
ID int |
|
||||||
Type string |
|
||||||
} |
|
||||||
|
|
||||||
// Name returns an upper case version of the oid type.
|
|
||||||
func (o OID) Name() string { |
|
||||||
return strings.ToUpper(o.Type) |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
datname := os.Getenv("PGDATABASE") |
|
||||||
sslmode := os.Getenv("PGSSLMODE") |
|
||||||
|
|
||||||
if datname == "" { |
|
||||||
os.Setenv("PGDATABASE", "pqgotest") |
|
||||||
} |
|
||||||
|
|
||||||
if sslmode == "" { |
|
||||||
os.Setenv("PGSSLMODE", "disable") |
|
||||||
} |
|
||||||
|
|
||||||
db, err := sql.Open("postgres", "") |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
rows, err := db.Query(` |
|
||||||
SELECT typname, oid |
|
||||||
FROM pg_type WHERE oid < 10000 |
|
||||||
ORDER BY oid; |
|
||||||
`) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
oids := make([]*OID, 0) |
|
||||||
for rows.Next() { |
|
||||||
var oid OID |
|
||||||
if err = rows.Scan(&oid.Type, &oid.ID); err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
oids = append(oids, &oid) |
|
||||||
} |
|
||||||
if err = rows.Err(); err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
cmd := exec.Command("gofmt") |
|
||||||
cmd.Stderr = os.Stderr |
|
||||||
w, err := cmd.StdinPipe() |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
f, err := os.Create("types.go") |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
cmd.Stdout = f |
|
||||||
err = cmd.Start() |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.") |
|
||||||
fmt.Fprintln(w, "\npackage oid") |
|
||||||
fmt.Fprintln(w, "const (") |
|
||||||
for _, oid := range oids { |
|
||||||
fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID) |
|
||||||
} |
|
||||||
fmt.Fprintln(w, ")") |
|
||||||
fmt.Fprintln(w, "var TypeName = map[Oid]string{") |
|
||||||
for _, oid := range oids { |
|
||||||
fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name()) |
|
||||||
} |
|
||||||
fmt.Fprintln(w, "}") |
|
||||||
w.Close() |
|
||||||
cmd.Wait() |
|
||||||
} |
|
@ -1,712 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
//go:generate go run gen.go -test
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"go/format" |
|
||||||
"io/ioutil" |
|
||||||
"math/rand" |
|
||||||
"os" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
// identifier converts s to a Go exported identifier.
|
|
||||||
// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
|
|
||||||
func identifier(s string) string { |
|
||||||
b := make([]byte, 0, len(s)) |
|
||||||
cap := true |
|
||||||
for _, c := range s { |
|
||||||
if c == '-' { |
|
||||||
cap = true |
|
||||||
continue |
|
||||||
} |
|
||||||
if cap && 'a' <= c && c <= 'z' { |
|
||||||
c -= 'a' - 'A' |
|
||||||
} |
|
||||||
cap = false |
|
||||||
b = append(b, byte(c)) |
|
||||||
} |
|
||||||
return string(b) |
|
||||||
} |
|
||||||
|
|
||||||
var test = flag.Bool("test", false, "generate table_test.go") |
|
||||||
|
|
||||||
func genFile(name string, buf *bytes.Buffer) { |
|
||||||
b, err := format.Source(buf.Bytes()) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintln(os.Stderr, err) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
if err := ioutil.WriteFile(name, b, 0644); err != nil { |
|
||||||
fmt.Fprintln(os.Stderr, err) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Parse() |
|
||||||
|
|
||||||
var all []string |
|
||||||
all = append(all, elements...) |
|
||||||
all = append(all, attributes...) |
|
||||||
all = append(all, eventHandlers...) |
|
||||||
all = append(all, extra...) |
|
||||||
sort.Strings(all) |
|
||||||
|
|
||||||
// uniq - lists have dups
|
|
||||||
w := 0 |
|
||||||
for _, s := range all { |
|
||||||
if w == 0 || all[w-1] != s { |
|
||||||
all[w] = s |
|
||||||
w++ |
|
||||||
} |
|
||||||
} |
|
||||||
all = all[:w] |
|
||||||
|
|
||||||
if *test { |
|
||||||
var buf bytes.Buffer |
|
||||||
fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") |
|
||||||
fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") |
|
||||||
fmt.Fprintln(&buf, "package atom\n") |
|
||||||
fmt.Fprintln(&buf, "var testAtomList = []string{") |
|
||||||
for _, s := range all { |
|
||||||
fmt.Fprintf(&buf, "\t%q,\n", s) |
|
||||||
} |
|
||||||
fmt.Fprintln(&buf, "}") |
|
||||||
|
|
||||||
genFile("table_test.go", &buf) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// Find hash that minimizes table size.
|
|
||||||
var best *table |
|
||||||
for i := 0; i < 1000000; i++ { |
|
||||||
if best != nil && 1<<(best.k-1) < len(all) { |
|
||||||
break |
|
||||||
} |
|
||||||
h := rand.Uint32() |
|
||||||
for k := uint(0); k <= 16; k++ { |
|
||||||
if best != nil && k >= best.k { |
|
||||||
break |
|
||||||
} |
|
||||||
var t table |
|
||||||
if t.init(h, k, all) { |
|
||||||
best = &t |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if best == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "failed to construct string table\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// Lay out strings, using overlaps when possible.
|
|
||||||
layout := append([]string{}, all...) |
|
||||||
|
|
||||||
// Remove strings that are substrings of other strings
|
|
||||||
for changed := true; changed; { |
|
||||||
changed = false |
|
||||||
for i, s := range layout { |
|
||||||
if s == "" { |
|
||||||
continue |
|
||||||
} |
|
||||||
for j, t := range layout { |
|
||||||
if i != j && t != "" && strings.Contains(s, t) { |
|
||||||
changed = true |
|
||||||
layout[j] = "" |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Join strings where one suffix matches another prefix.
|
|
||||||
for { |
|
||||||
// Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
|
|
||||||
// maximizing overlap length k.
|
|
||||||
besti := -1 |
|
||||||
bestj := -1 |
|
||||||
bestk := 0 |
|
||||||
for i, s := range layout { |
|
||||||
if s == "" { |
|
||||||
continue |
|
||||||
} |
|
||||||
for j, t := range layout { |
|
||||||
if i == j { |
|
||||||
continue |
|
||||||
} |
|
||||||
for k := bestk + 1; k <= len(s) && k <= len(t); k++ { |
|
||||||
if s[len(s)-k:] == t[:k] { |
|
||||||
besti = i |
|
||||||
bestj = j |
|
||||||
bestk = k |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if bestk > 0 { |
|
||||||
layout[besti] += layout[bestj][bestk:] |
|
||||||
layout[bestj] = "" |
|
||||||
continue |
|
||||||
} |
|
||||||
break |
|
||||||
} |
|
||||||
|
|
||||||
text := strings.Join(layout, "") |
|
||||||
|
|
||||||
atom := map[string]uint32{} |
|
||||||
for _, s := range all { |
|
||||||
off := strings.Index(text, s) |
|
||||||
if off < 0 { |
|
||||||
panic("lost string " + s) |
|
||||||
} |
|
||||||
atom[s] = uint32(off<<8 | len(s)) |
|
||||||
} |
|
||||||
|
|
||||||
var buf bytes.Buffer |
|
||||||
// Generate the Go code.
|
|
||||||
fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") |
|
||||||
fmt.Fprintln(&buf, "//go:generate go run gen.go\n") |
|
||||||
fmt.Fprintln(&buf, "package atom\n\nconst (") |
|
||||||
|
|
||||||
// compute max len
|
|
||||||
maxLen := 0 |
|
||||||
for _, s := range all { |
|
||||||
if maxLen < len(s) { |
|
||||||
maxLen = len(s) |
|
||||||
} |
|
||||||
fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) |
|
||||||
} |
|
||||||
fmt.Fprintln(&buf, ")\n") |
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) |
|
||||||
fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) |
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) |
|
||||||
for i, s := range best.tab { |
|
||||||
if s == "" { |
|
||||||
continue |
|
||||||
} |
|
||||||
fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) |
|
||||||
} |
|
||||||
fmt.Fprintf(&buf, "}\n") |
|
||||||
datasize := (1 << best.k) * 4 |
|
||||||
|
|
||||||
fmt.Fprintln(&buf, "const atomText =") |
|
||||||
textsize := len(text) |
|
||||||
for len(text) > 60 { |
|
||||||
fmt.Fprintf(&buf, "\t%q +\n", text[:60]) |
|
||||||
text = text[60:] |
|
||||||
} |
|
||||||
fmt.Fprintf(&buf, "\t%q\n\n", text) |
|
||||||
|
|
||||||
genFile("table.go", &buf) |
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) |
|
||||||
} |
|
||||||
|
|
||||||
type byLen []string |
|
||||||
|
|
||||||
func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } |
|
||||||
func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } |
|
||||||
func (x byLen) Len() int { return len(x) } |
|
||||||
|
|
||||||
// fnv computes the FNV hash with an arbitrary starting value h.
|
|
||||||
func fnv(h uint32, s string) uint32 { |
|
||||||
for i := 0; i < len(s); i++ { |
|
||||||
h ^= uint32(s[i]) |
|
||||||
h *= 16777619 |
|
||||||
} |
|
||||||
return h |
|
||||||
} |
|
||||||
|
|
||||||
// A table represents an attempt at constructing the lookup table.
|
|
||||||
// The lookup table uses cuckoo hashing, meaning that each string
|
|
||||||
// can be found in one of two positions.
|
|
||||||
type table struct { |
|
||||||
h0 uint32 |
|
||||||
k uint |
|
||||||
mask uint32 |
|
||||||
tab []string |
|
||||||
} |
|
||||||
|
|
||||||
// hash returns the two hashes for s.
|
|
||||||
func (t *table) hash(s string) (h1, h2 uint32) { |
|
||||||
h := fnv(t.h0, s) |
|
||||||
h1 = h & t.mask |
|
||||||
h2 = (h >> 16) & t.mask |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// init initializes the table with the given parameters.
|
|
||||||
// h0 is the initial hash value,
|
|
||||||
// k is the number of bits of hash value to use, and
|
|
||||||
// x is the list of strings to store in the table.
|
|
||||||
// init returns false if the table cannot be constructed.
|
|
||||||
func (t *table) init(h0 uint32, k uint, x []string) bool { |
|
||||||
t.h0 = h0 |
|
||||||
t.k = k |
|
||||||
t.tab = make([]string, 1<<k) |
|
||||||
t.mask = 1<<k - 1 |
|
||||||
for _, s := range x { |
|
||||||
if !t.insert(s) { |
|
||||||
return false |
|
||||||
} |
|
||||||
} |
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
// insert inserts s in the table.
|
|
||||||
func (t *table) insert(s string) bool { |
|
||||||
h1, h2 := t.hash(s) |
|
||||||
if t.tab[h1] == "" { |
|
||||||
t.tab[h1] = s |
|
||||||
return true |
|
||||||
} |
|
||||||
if t.tab[h2] == "" { |
|
||||||
t.tab[h2] = s |
|
||||||
return true |
|
||||||
} |
|
||||||
if t.push(h1, 0) { |
|
||||||
t.tab[h1] = s |
|
||||||
return true |
|
||||||
} |
|
||||||
if t.push(h2, 0) { |
|
||||||
t.tab[h2] = s |
|
||||||
return true |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
// push attempts to push aside the entry in slot i.
|
|
||||||
func (t *table) push(i uint32, depth int) bool { |
|
||||||
if depth > len(t.tab) { |
|
||||||
return false |
|
||||||
} |
|
||||||
s := t.tab[i] |
|
||||||
h1, h2 := t.hash(s) |
|
||||||
j := h1 + h2 - i |
|
||||||
if t.tab[j] != "" && !t.push(j, depth+1) { |
|
||||||
return false |
|
||||||
} |
|
||||||
t.tab[j] = s |
|
||||||
return true |
|
||||||
} |
|
||||||
|
|
||||||
// The lists of element names and attribute keys were taken from
|
|
||||||
// https://html.spec.whatwg.org/multipage/indices.html#index
|
|
||||||
// as of the "HTML Living Standard - Last Updated 16 April 2018" version.
|
|
||||||
|
|
||||||
// "command", "keygen" and "menuitem" have been removed from the spec,
|
|
||||||
// but are kept here for backwards compatibility.
|
|
||||||
var elements = []string{ |
|
||||||
"a", |
|
||||||
"abbr", |
|
||||||
"address", |
|
||||||
"area", |
|
||||||
"article", |
|
||||||
"aside", |
|
||||||
"audio", |
|
||||||
"b", |
|
||||||
"base", |
|
||||||
"bdi", |
|
||||||
"bdo", |
|
||||||
"blockquote", |
|
||||||
"body", |
|
||||||
"br", |
|
||||||
"button", |
|
||||||
"canvas", |
|
||||||
"caption", |
|
||||||
"cite", |
|
||||||
"code", |
|
||||||
"col", |
|
||||||
"colgroup", |
|
||||||
"command", |
|
||||||
"data", |
|
||||||
"datalist", |
|
||||||
"dd", |
|
||||||
"del", |
|
||||||
"details", |
|
||||||
"dfn", |
|
||||||
"dialog", |
|
||||||
"div", |
|
||||||
"dl", |
|
||||||
"dt", |
|
||||||
"em", |
|
||||||
"embed", |
|
||||||
"fieldset", |
|
||||||
"figcaption", |
|
||||||
"figure", |
|
||||||
"footer", |
|
||||||
"form", |
|
||||||
"h1", |
|
||||||
"h2", |
|
||||||
"h3", |
|
||||||
"h4", |
|
||||||
"h5", |
|
||||||
"h6", |
|
||||||
"head", |
|
||||||
"header", |
|
||||||
"hgroup", |
|
||||||
"hr", |
|
||||||
"html", |
|
||||||
"i", |
|
||||||
"iframe", |
|
||||||
"img", |
|
||||||
"input", |
|
||||||
"ins", |
|
||||||
"kbd", |
|
||||||
"keygen", |
|
||||||
"label", |
|
||||||
"legend", |
|
||||||
"li", |
|
||||||
"link", |
|
||||||
"main", |
|
||||||
"map", |
|
||||||
"mark", |
|
||||||
"menu", |
|
||||||
"menuitem", |
|
||||||
"meta", |
|
||||||
"meter", |
|
||||||
"nav", |
|
||||||
"noscript", |
|
||||||
"object", |
|
||||||
"ol", |
|
||||||
"optgroup", |
|
||||||
"option", |
|
||||||
"output", |
|
||||||
"p", |
|
||||||
"param", |
|
||||||
"picture", |
|
||||||
"pre", |
|
||||||
"progress", |
|
||||||
"q", |
|
||||||
"rp", |
|
||||||
"rt", |
|
||||||
"ruby", |
|
||||||
"s", |
|
||||||
"samp", |
|
||||||
"script", |
|
||||||
"section", |
|
||||||
"select", |
|
||||||
"slot", |
|
||||||
"small", |
|
||||||
"source", |
|
||||||
"span", |
|
||||||
"strong", |
|
||||||
"style", |
|
||||||
"sub", |
|
||||||
"summary", |
|
||||||
"sup", |
|
||||||
"table", |
|
||||||
"tbody", |
|
||||||
"td", |
|
||||||
"template", |
|
||||||
"textarea", |
|
||||||
"tfoot", |
|
||||||
"th", |
|
||||||
"thead", |
|
||||||
"time", |
|
||||||
"title", |
|
||||||
"tr", |
|
||||||
"track", |
|
||||||
"u", |
|
||||||
"ul", |
|
||||||
"var", |
|
||||||
"video", |
|
||||||
"wbr", |
|
||||||
} |
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
|
|
||||||
//
|
|
||||||
// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
|
|
||||||
// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
|
|
||||||
// but are kept here for backwards compatibility.
|
|
||||||
var attributes = []string{ |
|
||||||
"abbr", |
|
||||||
"accept", |
|
||||||
"accept-charset", |
|
||||||
"accesskey", |
|
||||||
"action", |
|
||||||
"allowfullscreen", |
|
||||||
"allowpaymentrequest", |
|
||||||
"allowusermedia", |
|
||||||
"alt", |
|
||||||
"as", |
|
||||||
"async", |
|
||||||
"autocomplete", |
|
||||||
"autofocus", |
|
||||||
"autoplay", |
|
||||||
"challenge", |
|
||||||
"charset", |
|
||||||
"checked", |
|
||||||
"cite", |
|
||||||
"class", |
|
||||||
"color", |
|
||||||
"cols", |
|
||||||
"colspan", |
|
||||||
"command", |
|
||||||
"content", |
|
||||||
"contenteditable", |
|
||||||
"contextmenu", |
|
||||||
"controls", |
|
||||||
"coords", |
|
||||||
"crossorigin", |
|
||||||
"data", |
|
||||||
"datetime", |
|
||||||
"default", |
|
||||||
"defer", |
|
||||||
"dir", |
|
||||||
"dirname", |
|
||||||
"disabled", |
|
||||||
"download", |
|
||||||
"draggable", |
|
||||||
"dropzone", |
|
||||||
"enctype", |
|
||||||
"for", |
|
||||||
"form", |
|
||||||
"formaction", |
|
||||||
"formenctype", |
|
||||||
"formmethod", |
|
||||||
"formnovalidate", |
|
||||||
"formtarget", |
|
||||||
"headers", |
|
||||||
"height", |
|
||||||
"hidden", |
|
||||||
"high", |
|
||||||
"href", |
|
||||||
"hreflang", |
|
||||||
"http-equiv", |
|
||||||
"icon", |
|
||||||
"id", |
|
||||||
"inputmode", |
|
||||||
"integrity", |
|
||||||
"is", |
|
||||||
"ismap", |
|
||||||
"itemid", |
|
||||||
"itemprop", |
|
||||||
"itemref", |
|
||||||
"itemscope", |
|
||||||
"itemtype", |
|
||||||
"keytype", |
|
||||||
"kind", |
|
||||||
"label", |
|
||||||
"lang", |
|
||||||
"list", |
|
||||||
"loop", |
|
||||||
"low", |
|
||||||
"manifest", |
|
||||||
"max", |
|
||||||
"maxlength", |
|
||||||
"media", |
|
||||||
"mediagroup", |
|
||||||
"method", |
|
||||||
"min", |
|
||||||
"minlength", |
|
||||||
"multiple", |
|
||||||
"muted", |
|
||||||
"name", |
|
||||||
"nomodule", |
|
||||||
"nonce", |
|
||||||
"novalidate", |
|
||||||
"open", |
|
||||||
"optimum", |
|
||||||
"pattern", |
|
||||||
"ping", |
|
||||||
"placeholder", |
|
||||||
"playsinline", |
|
||||||
"poster", |
|
||||||
"preload", |
|
||||||
"radiogroup", |
|
||||||
"readonly", |
|
||||||
"referrerpolicy", |
|
||||||
"rel", |
|
||||||
"required", |
|
||||||
"reversed", |
|
||||||
"rows", |
|
||||||
"rowspan", |
|
||||||
"sandbox", |
|
||||||
"spellcheck", |
|
||||||
"scope", |
|
||||||
"scoped", |
|
||||||
"seamless", |
|
||||||
"selected", |
|
||||||
"shape", |
|
||||||
"size", |
|
||||||
"sizes", |
|
||||||
"sortable", |
|
||||||
"sorted", |
|
||||||
"slot", |
|
||||||
"span", |
|
||||||
"spellcheck", |
|
||||||
"src", |
|
||||||
"srcdoc", |
|
||||||
"srclang", |
|
||||||
"srcset", |
|
||||||
"start", |
|
||||||
"step", |
|
||||||
"style", |
|
||||||
"tabindex", |
|
||||||
"target", |
|
||||||
"title", |
|
||||||
"translate", |
|
||||||
"type", |
|
||||||
"typemustmatch", |
|
||||||
"updateviacache", |
|
||||||
"usemap", |
|
||||||
"value", |
|
||||||
"width", |
|
||||||
"workertype", |
|
||||||
"wrap", |
|
||||||
} |
|
||||||
|
|
||||||
// "onautocomplete", "onautocompleteerror", "onmousewheel",
|
|
||||||
// "onshow" and "onsort" have been removed from the spec,
|
|
||||||
// but are kept here for backwards compatibility.
|
|
||||||
var eventHandlers = []string{ |
|
||||||
"onabort", |
|
||||||
"onautocomplete", |
|
||||||
"onautocompleteerror", |
|
||||||
"onauxclick", |
|
||||||
"onafterprint", |
|
||||||
"onbeforeprint", |
|
||||||
"onbeforeunload", |
|
||||||
"onblur", |
|
||||||
"oncancel", |
|
||||||
"oncanplay", |
|
||||||
"oncanplaythrough", |
|
||||||
"onchange", |
|
||||||
"onclick", |
|
||||||
"onclose", |
|
||||||
"oncontextmenu", |
|
||||||
"oncopy", |
|
||||||
"oncuechange", |
|
||||||
"oncut", |
|
||||||
"ondblclick", |
|
||||||
"ondrag", |
|
||||||
"ondragend", |
|
||||||
"ondragenter", |
|
||||||
"ondragexit", |
|
||||||
"ondragleave", |
|
||||||
"ondragover", |
|
||||||
"ondragstart", |
|
||||||
"ondrop", |
|
||||||
"ondurationchange", |
|
||||||
"onemptied", |
|
||||||
"onended", |
|
||||||
"onerror", |
|
||||||
"onfocus", |
|
||||||
"onhashchange", |
|
||||||
"oninput", |
|
||||||
"oninvalid", |
|
||||||
"onkeydown", |
|
||||||
"onkeypress", |
|
||||||
"onkeyup", |
|
||||||
"onlanguagechange", |
|
||||||
"onload", |
|
||||||
"onloadeddata", |
|
||||||
"onloadedmetadata", |
|
||||||
"onloadend", |
|
||||||
"onloadstart", |
|
||||||
"onmessage", |
|
||||||
"onmessageerror", |
|
||||||
"onmousedown", |
|
||||||
"onmouseenter", |
|
||||||
"onmouseleave", |
|
||||||
"onmousemove", |
|
||||||
"onmouseout", |
|
||||||
"onmouseover", |
|
||||||
"onmouseup", |
|
||||||
"onmousewheel", |
|
||||||
"onwheel", |
|
||||||
"onoffline", |
|
||||||
"ononline", |
|
||||||
"onpagehide", |
|
||||||
"onpageshow", |
|
||||||
"onpaste", |
|
||||||
"onpause", |
|
||||||
"onplay", |
|
||||||
"onplaying", |
|
||||||
"onpopstate", |
|
||||||
"onprogress", |
|
||||||
"onratechange", |
|
||||||
"onreset", |
|
||||||
"onresize", |
|
||||||
"onrejectionhandled", |
|
||||||
"onscroll", |
|
||||||
"onsecuritypolicyviolation", |
|
||||||
"onseeked", |
|
||||||
"onseeking", |
|
||||||
"onselect", |
|
||||||
"onshow", |
|
||||||
"onsort", |
|
||||||
"onstalled", |
|
||||||
"onstorage", |
|
||||||
"onsubmit", |
|
||||||
"onsuspend", |
|
||||||
"ontimeupdate", |
|
||||||
"ontoggle", |
|
||||||
"onunhandledrejection", |
|
||||||
"onunload", |
|
||||||
"onvolumechange", |
|
||||||
"onwaiting", |
|
||||||
} |
|
||||||
|
|
||||||
// extra are ad-hoc values not covered by any of the lists above.
|
|
||||||
var extra = []string{ |
|
||||||
"acronym", |
|
||||||
"align", |
|
||||||
"annotation", |
|
||||||
"annotation-xml", |
|
||||||
"applet", |
|
||||||
"basefont", |
|
||||||
"bgsound", |
|
||||||
"big", |
|
||||||
"blink", |
|
||||||
"center", |
|
||||||
"color", |
|
||||||
"desc", |
|
||||||
"face", |
|
||||||
"font", |
|
||||||
"foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
|
|
||||||
"foreignobject", |
|
||||||
"frame", |
|
||||||
"frameset", |
|
||||||
"image", |
|
||||||
"isindex", |
|
||||||
"listing", |
|
||||||
"malignmark", |
|
||||||
"marquee", |
|
||||||
"math", |
|
||||||
"mglyph", |
|
||||||
"mi", |
|
||||||
"mn", |
|
||||||
"mo", |
|
||||||
"ms", |
|
||||||
"mtext", |
|
||||||
"nobr", |
|
||||||
"noembed", |
|
||||||
"noframes", |
|
||||||
"plaintext", |
|
||||||
"prompt", |
|
||||||
"public", |
|
||||||
"rb", |
|
||||||
"rtc", |
|
||||||
"spacer", |
|
||||||
"strike", |
|
||||||
"svg", |
|
||||||
"system", |
|
||||||
"tt", |
|
||||||
"xmp", |
|
||||||
} |
|
@ -1,61 +0,0 @@ |
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
|
||||||
//This program must be run after mksyscall.go.
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"fmt" |
|
||||||
"io/ioutil" |
|
||||||
"log" |
|
||||||
"os" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
func main() { |
|
||||||
in1, err := ioutil.ReadFile("syscall_darwin.go") |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("can't open syscall_darwin.go: %s", err) |
|
||||||
} |
|
||||||
arch := os.Args[1] |
|
||||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch)) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err) |
|
||||||
} |
|
||||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch)) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err) |
|
||||||
} |
|
||||||
in := string(in1) + string(in2) + string(in3) |
|
||||||
|
|
||||||
trampolines := map[string]bool{} |
|
||||||
|
|
||||||
var out bytes.Buffer |
|
||||||
|
|
||||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " ")) |
|
||||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n") |
|
||||||
fmt.Fprintf(&out, "\n") |
|
||||||
fmt.Fprintf(&out, "// +build go1.12\n") |
|
||||||
fmt.Fprintf(&out, "\n") |
|
||||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n") |
|
||||||
for _, line := range strings.Split(in, "\n") { |
|
||||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") { |
|
||||||
continue |
|
||||||
} |
|
||||||
fn := line[5 : len(line)-13] |
|
||||||
if !trampolines[fn] { |
|
||||||
trampolines[fn] = true |
|
||||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn) |
|
||||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn) |
|
||||||
} |
|
||||||
} |
|
||||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err) |
|
||||||
} |
|
||||||
} |
|
@ -1,122 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkpost processes the output of cgo -godefs to
|
|
||||||
// modify the generated types. It is used to clean up
|
|
||||||
// the sys API in an architecture specific manner.
|
|
||||||
//
|
|
||||||
// mkpost is run after cgo -godefs; see README.md.
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"fmt" |
|
||||||
"go/format" |
|
||||||
"io/ioutil" |
|
||||||
"log" |
|
||||||
"os" |
|
||||||
"regexp" |
|
||||||
) |
|
||||||
|
|
||||||
func main() { |
|
||||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goos := os.Getenv("GOOS") |
|
||||||
goarch := os.Getenv("GOARCH_TARGET") |
|
||||||
if goarch == "" { |
|
||||||
goarch = os.Getenv("GOARCH") |
|
||||||
} |
|
||||||
// Check that we are using the Docker-based build system if we should be.
|
|
||||||
if goos == "linux" { |
|
||||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" { |
|
||||||
os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n") |
|
||||||
os.Stderr.WriteString("See README.md\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(os.Stdin) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
|
|
||||||
if goos == "aix" { |
|
||||||
// Replace type of Atim, Mtim and Ctim by Timespec in Stat_t
|
|
||||||
// to avoid having both StTimespec and Timespec.
|
|
||||||
sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`) |
|
||||||
b = sttimespec.ReplaceAll(b, []byte("Timespec")) |
|
||||||
} |
|
||||||
|
|
||||||
// Intentionally export __val fields in Fsid and Sigset_t
|
|
||||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`) |
|
||||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}")) |
|
||||||
|
|
||||||
// Intentionally export __fds_bits field in FdSet
|
|
||||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`) |
|
||||||
b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}")) |
|
||||||
|
|
||||||
// If we have empty Ptrace structs, we should delete them. Only s390x emits
|
|
||||||
// nonempty Ptrace structs.
|
|
||||||
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`) |
|
||||||
b = ptraceRexexp.ReplaceAll(b, nil) |
|
||||||
|
|
||||||
// Replace the control_regs union with a blank identifier for now.
|
|
||||||
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`) |
|
||||||
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64")) |
|
||||||
|
|
||||||
// Remove fields that are added by glibc
|
|
||||||
// Note that this is unstable as the identifers are private.
|
|
||||||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`) |
|
||||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_")) |
|
||||||
|
|
||||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
|
||||||
// conversion to string; see golang.org/issue/20753
|
|
||||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`) |
|
||||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte")) |
|
||||||
|
|
||||||
// Convert [1024]int8 to [1024]byte in Ptmget members
|
|
||||||
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`) |
|
||||||
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte")) |
|
||||||
|
|
||||||
// Remove spare fields (e.g. in Statx_t)
|
|
||||||
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`) |
|
||||||
b = spareFieldsRegex.ReplaceAll(b, []byte("_")) |
|
||||||
|
|
||||||
// Remove cgo padding fields
|
|
||||||
removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`) |
|
||||||
b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_")) |
|
||||||
|
|
||||||
// Remove padding, hidden, or unused fields
|
|
||||||
removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`) |
|
||||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_")) |
|
||||||
|
|
||||||
// Remove the first line of warning from cgo
|
|
||||||
b = b[bytes.IndexByte(b, '\n')+1:] |
|
||||||
// Modify the command in the header to include:
|
|
||||||
// mkpost, our own warning, and a build tag.
|
|
||||||
replacement := fmt.Sprintf(`$1 | go run mkpost.go |
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s,%s`, goarch, goos)
|
|
||||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`) |
|
||||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement)) |
|
||||||
|
|
||||||
// Rename Stat_t time fields
|
|
||||||
if goos == "freebsd" && goarch == "386" { |
|
||||||
// Hide Stat_t.[AMCB]tim_ext fields
|
|
||||||
renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`) |
|
||||||
b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_")) |
|
||||||
} |
|
||||||
renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`) |
|
||||||
b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}")) |
|
||||||
|
|
||||||
// gofmt
|
|
||||||
b, err = format.Source(b) |
|
||||||
if err != nil { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
|
|
||||||
os.Stdout.Write(b) |
|
||||||
} |
|
@ -1,407 +0,0 @@ |
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
This program reads a file containing function prototypes |
|
||||||
(like syscall_darwin.go) and generates system call bodies. |
|
||||||
The prototypes are marked by lines beginning with "//sys" |
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument. |
|
||||||
This includes return parameters. |
|
||||||
* The parameter lists must give a type for each argument: |
|
||||||
the (x, y, z int) shorthand is not allowed. |
|
||||||
* If the return parameter is an error number, it must be named errno. |
|
||||||
|
|
||||||
A line beginning with //sysnb is like //sys, except that the
|
|
||||||
goroutine will not be suspended during the execution of the system |
|
||||||
call. This must only be used for system calls which can never |
|
||||||
block, as otherwise the system call could cause all goroutines to |
|
||||||
hang. |
|
||||||
*/ |
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"regexp" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian") |
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian") |
|
||||||
plan9 = flag.Bool("plan9", false, "plan9") |
|
||||||
openbsd = flag.Bool("openbsd", false, "openbsd") |
|
||||||
netbsd = flag.Bool("netbsd", false, "netbsd") |
|
||||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly") |
|
||||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
|
||||||
tags = flag.String("tags", "", "build tags") |
|
||||||
filename = flag.String("output", "", "output file name (standard output if omitted)") |
|
||||||
) |
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string { |
|
||||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ") |
|
||||||
} |
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string { |
|
||||||
return *tags |
|
||||||
} |
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct { |
|
||||||
Name string |
|
||||||
Type string |
|
||||||
} |
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() { |
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string { |
|
||||||
list = strings.TrimSpace(list) |
|
||||||
if list == "" { |
|
||||||
return []string{} |
|
||||||
} |
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param { |
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) |
|
||||||
if ps == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
return Param{ps[1], ps[2]} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goos := os.Getenv("GOOS") |
|
||||||
if goos == "" { |
|
||||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
goarch := os.Getenv("GOARCH_TARGET") |
|
||||||
if goarch == "" { |
|
||||||
goarch = os.Getenv("GOARCH") |
|
||||||
} |
|
||||||
|
|
||||||
// Check that we are using the Docker-based build system if we should
|
|
||||||
if goos == "linux" { |
|
||||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" { |
|
||||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n") |
|
||||||
fmt.Fprintf(os.Stderr, "See README.md\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
flag.Usage = usage |
|
||||||
flag.Parse() |
|
||||||
if len(flag.Args()) <= 0 { |
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n") |
|
||||||
usage() |
|
||||||
} |
|
||||||
|
|
||||||
endianness := "" |
|
||||||
if *b32 { |
|
||||||
endianness = "big-endian" |
|
||||||
} else if *l32 { |
|
||||||
endianness = "little-endian" |
|
||||||
} |
|
||||||
|
|
||||||
libc := false |
|
||||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") { |
|
||||||
libc = true |
|
||||||
} |
|
||||||
trampolines := map[string]bool{} |
|
||||||
|
|
||||||
text := "" |
|
||||||
for _, path := range flag.Args() { |
|
||||||
file, err := os.Open(path) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
s := bufio.NewScanner(file) |
|
||||||
for s.Scan() { |
|
||||||
t := s.Text() |
|
||||||
t = strings.TrimSpace(t) |
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) |
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) |
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t) |
|
||||||
if f == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5] |
|
||||||
|
|
||||||
// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
|
|
||||||
if goos == "darwin" && !libc && funct == "ClockGettime" { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps) |
|
||||||
out := parseParamList(outps) |
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" |
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
outDecl := "" |
|
||||||
if len(out) > 0 { |
|
||||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", ")) |
|
||||||
} |
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl) |
|
||||||
|
|
||||||
// Check if err return available
|
|
||||||
errvar := "" |
|
||||||
for _, param := range out { |
|
||||||
p := parseParam(param) |
|
||||||
if p.Type == "error" { |
|
||||||
errvar = p.Name |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string |
|
||||||
n := 0 |
|
||||||
for _, param := range in { |
|
||||||
p := parseParam(param) |
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { |
|
||||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") |
|
||||||
} else if p.Type == "string" && errvar != "" { |
|
||||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n) |
|
||||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name) |
|
||||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "string" { |
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") |
|
||||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n) |
|
||||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) |
|
||||||
n++ |
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { |
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass dummy pointer in that case.
|
|
||||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
|
||||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n) |
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name) |
|
||||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "int64" && (*openbsd || *netbsd) { |
|
||||||
args = append(args, "0") |
|
||||||
if endianness == "big-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} else if endianness == "little-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} |
|
||||||
} else if p.Type == "int64" && *dragonfly { |
|
||||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil { |
|
||||||
args = append(args, "0") |
|
||||||
} |
|
||||||
if endianness == "big-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} else if endianness == "little-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} |
|
||||||
} else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" { |
|
||||||
if len(args)%2 == 1 && *arm { |
|
||||||
// arm abi specifies 64-bit argument uses
|
|
||||||
// (even, odd) pair
|
|
||||||
args = append(args, "0") |
|
||||||
} |
|
||||||
if endianness == "big-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) |
|
||||||
} |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Determine which form to use; pad args with zeros.
|
|
||||||
asm := "Syscall" |
|
||||||
if nonblock != nil { |
|
||||||
if errvar == "" && goos == "linux" { |
|
||||||
asm = "RawSyscallNoError" |
|
||||||
} else { |
|
||||||
asm = "RawSyscall" |
|
||||||
} |
|
||||||
} else { |
|
||||||
if errvar == "" && goos == "linux" { |
|
||||||
asm = "SyscallNoError" |
|
||||||
} |
|
||||||
} |
|
||||||
if len(args) <= 3 { |
|
||||||
for len(args) < 3 { |
|
||||||
args = append(args, "0") |
|
||||||
} |
|
||||||
} else if len(args) <= 6 { |
|
||||||
asm += "6" |
|
||||||
for len(args) < 6 { |
|
||||||
args = append(args, "0") |
|
||||||
} |
|
||||||
} else if len(args) <= 9 { |
|
||||||
asm += "9" |
|
||||||
for len(args) < 9 { |
|
||||||
args = append(args, "0") |
|
||||||
} |
|
||||||
} else { |
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct) |
|
||||||
} |
|
||||||
|
|
||||||
// System call number.
|
|
||||||
if sysname == "" { |
|
||||||
sysname = "SYS_" + funct |
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) |
|
||||||
sysname = strings.ToUpper(sysname) |
|
||||||
} |
|
||||||
|
|
||||||
var libcFn string |
|
||||||
if libc { |
|
||||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
|
||||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
|
||||||
sysname = strings.ToLower(sysname) // lowercase
|
|
||||||
if sysname == "getdirentries64" { |
|
||||||
// Special case - libSystem name and
|
|
||||||
// raw syscall name don't match.
|
|
||||||
sysname = "__getdirentries64" |
|
||||||
} |
|
||||||
libcFn = sysname |
|
||||||
sysname = "funcPC(libc_" + sysname + "_trampoline)" |
|
||||||
} |
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ") |
|
||||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist) |
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := "" |
|
||||||
ret := []string{"_", "_", "_"} |
|
||||||
doErrno := false |
|
||||||
for i := 0; i < len(out); i++ { |
|
||||||
p := parseParam(out[i]) |
|
||||||
reg := "" |
|
||||||
if p.Name == "err" && !*plan9 { |
|
||||||
reg = "e1" |
|
||||||
ret[2] = reg |
|
||||||
doErrno = true |
|
||||||
} else if p.Name == "err" && *plan9 { |
|
||||||
ret[0] = "r0" |
|
||||||
ret[2] = "e1" |
|
||||||
break |
|
||||||
} else { |
|
||||||
reg = fmt.Sprintf("r%d", i) |
|
||||||
ret[i] = reg |
|
||||||
} |
|
||||||
if p.Type == "bool" { |
|
||||||
reg = fmt.Sprintf("%s != 0", reg) |
|
||||||
} |
|
||||||
if p.Type == "int64" && endianness != "" { |
|
||||||
// 64-bit number in r1:r0 or r0:r1.
|
|
||||||
if i+2 > len(out) { |
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct) |
|
||||||
} |
|
||||||
if endianness == "big-endian" { |
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) |
|
||||||
} else { |
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) |
|
||||||
} |
|
||||||
ret[i] = fmt.Sprintf("r%d", i) |
|
||||||
ret[i+1] = fmt.Sprintf("r%d", i+1) |
|
||||||
} |
|
||||||
if reg != "e1" || *plan9 { |
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) |
|
||||||
} |
|
||||||
} |
|
||||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { |
|
||||||
text += fmt.Sprintf("\t%s\n", call) |
|
||||||
} else { |
|
||||||
if errvar == "" && goos == "linux" { |
|
||||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
|
||||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call) |
|
||||||
} else { |
|
||||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) |
|
||||||
} |
|
||||||
} |
|
||||||
text += body |
|
||||||
|
|
||||||
if *plan9 && ret[2] == "e1" { |
|
||||||
text += "\tif int32(r0) == -1 {\n" |
|
||||||
text += "\t\terr = e1\n" |
|
||||||
text += "\t}\n" |
|
||||||
} else if doErrno { |
|
||||||
text += "\tif e1 != 0 {\n" |
|
||||||
text += "\t\terr = errnoErr(e1)\n" |
|
||||||
text += "\t}\n" |
|
||||||
} |
|
||||||
text += "\treturn\n" |
|
||||||
text += "}\n\n" |
|
||||||
|
|
||||||
if libc && !trampolines[libcFn] { |
|
||||||
// some system calls share a trampoline, like read and readlen.
|
|
||||||
trampolines[libcFn] = true |
|
||||||
// Declare assembly trampoline.
|
|
||||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn) |
|
||||||
// Assembly trampoline calls the libc_* function, which this magic
|
|
||||||
// redirects to use the function from libSystem.
|
|
||||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn) |
|
||||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn) |
|
||||||
text += "\n" |
|
||||||
} |
|
||||||
} |
|
||||||
if err := s.Err(); err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
file.Close() |
|
||||||
} |
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) |
|
||||||
} |
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
import ( |
|
||||||
"syscall" |
|
||||||
"unsafe" |
|
||||||
) |
|
||||||
|
|
||||||
var _ syscall.Errno |
|
||||||
|
|
||||||
%s |
|
||||||
` |
|
@ -1,415 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
This program reads a file containing function prototypes |
|
||||||
(like syscall_aix.go) and generates system call bodies. |
|
||||||
The prototypes are marked by lines beginning with "//sys" |
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument. |
|
||||||
This includes return parameters. |
|
||||||
* The parameter lists must give a type for each argument: |
|
||||||
the (x, y, z int) shorthand is not allowed. |
|
||||||
* If the return parameter is an error number, it must be named err. |
|
||||||
* If go func name needs to be different than its libc name, |
|
||||||
* or the function is not in libc, name could be specified |
|
||||||
* at the end, after "=" sign, like |
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
*/ |
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"regexp" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian") |
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian") |
|
||||||
aix = flag.Bool("aix", false, "aix") |
|
||||||
tags = flag.String("tags", "", "build tags") |
|
||||||
) |
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string { |
|
||||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ") |
|
||||||
} |
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string { |
|
||||||
return *tags |
|
||||||
} |
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct { |
|
||||||
Name string |
|
||||||
Type string |
|
||||||
} |
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() { |
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string { |
|
||||||
list = strings.TrimSpace(list) |
|
||||||
if list == "" { |
|
||||||
return []string{} |
|
||||||
} |
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param { |
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) |
|
||||||
if ps == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
return Param{ps[1], ps[2]} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Usage = usage |
|
||||||
flag.Parse() |
|
||||||
if len(flag.Args()) <= 0 { |
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n") |
|
||||||
usage() |
|
||||||
} |
|
||||||
|
|
||||||
endianness := "" |
|
||||||
if *b32 { |
|
||||||
endianness = "big-endian" |
|
||||||
} else if *l32 { |
|
||||||
endianness = "little-endian" |
|
||||||
} |
|
||||||
|
|
||||||
pack := "" |
|
||||||
text := "" |
|
||||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n" |
|
||||||
for _, path := range flag.Args() { |
|
||||||
file, err := os.Open(path) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
s := bufio.NewScanner(file) |
|
||||||
for s.Scan() { |
|
||||||
t := s.Text() |
|
||||||
t = strings.TrimSpace(t) |
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) |
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { |
|
||||||
pack = p[1] |
|
||||||
} |
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) |
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) |
|
||||||
if f == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] |
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps) |
|
||||||
out := parseParamList(outps) |
|
||||||
|
|
||||||
inps = strings.Join(in, ", ") |
|
||||||
outps = strings.Join(out, ", ") |
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" |
|
||||||
|
|
||||||
// Check if value return, err return available
|
|
||||||
errvar := "" |
|
||||||
retvar := "" |
|
||||||
rettype := "" |
|
||||||
for _, param := range out { |
|
||||||
p := parseParam(param) |
|
||||||
if p.Type == "error" { |
|
||||||
errvar = p.Name |
|
||||||
} else { |
|
||||||
retvar = p.Name |
|
||||||
rettype = p.Type |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// System call name.
|
|
||||||
if sysname == "" { |
|
||||||
sysname = funct |
|
||||||
} |
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) |
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
cRettype := "" |
|
||||||
if rettype == "unsafe.Pointer" { |
|
||||||
cRettype = "uintptr_t" |
|
||||||
} else if rettype == "uintptr" { |
|
||||||
cRettype = "uintptr_t" |
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { |
|
||||||
cRettype = "uintptr_t" |
|
||||||
} else if rettype == "int" { |
|
||||||
cRettype = "int" |
|
||||||
} else if rettype == "int32" { |
|
||||||
cRettype = "int" |
|
||||||
} else if rettype == "int64" { |
|
||||||
cRettype = "long long" |
|
||||||
} else if rettype == "uint32" { |
|
||||||
cRettype = "unsigned int" |
|
||||||
} else if rettype == "uint64" { |
|
||||||
cRettype = "unsigned long long" |
|
||||||
} else { |
|
||||||
cRettype = "int" |
|
||||||
} |
|
||||||
if sysname == "exit" { |
|
||||||
cRettype = "void" |
|
||||||
} |
|
||||||
|
|
||||||
// Change p.Types to c
|
|
||||||
var cIn []string |
|
||||||
for _, param := range in { |
|
||||||
p := parseParam(param) |
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if p.Type == "string" { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { |
|
||||||
cIn = append(cIn, "uintptr_t", "size_t") |
|
||||||
} else if p.Type == "unsafe.Pointer" { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if p.Type == "uintptr" { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if p.Type == "int" { |
|
||||||
cIn = append(cIn, "int") |
|
||||||
} else if p.Type == "int32" { |
|
||||||
cIn = append(cIn, "int") |
|
||||||
} else if p.Type == "int64" { |
|
||||||
cIn = append(cIn, "long long") |
|
||||||
} else if p.Type == "uint32" { |
|
||||||
cIn = append(cIn, "unsigned int") |
|
||||||
} else if p.Type == "uint64" { |
|
||||||
cIn = append(cIn, "unsigned long long") |
|
||||||
} else { |
|
||||||
cIn = append(cIn, "int") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" { |
|
||||||
if sysname == "select" { |
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
cExtern += "#define c_select select\n" |
|
||||||
} |
|
||||||
// Imports of system calls from libc
|
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname) |
|
||||||
cIn := strings.Join(cIn, ", ") |
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn) |
|
||||||
} |
|
||||||
|
|
||||||
// So file name.
|
|
||||||
if *aix { |
|
||||||
if modname == "" { |
|
||||||
modname = "libc.a/shr_64.o" |
|
||||||
} else { |
|
||||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
strconvfunc := "C.CString" |
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
if outps != "" { |
|
||||||
outps = fmt.Sprintf(" (%s)", outps) |
|
||||||
} |
|
||||||
if text != "" { |
|
||||||
text += "\n" |
|
||||||
} |
|
||||||
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) |
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string |
|
||||||
n := 0 |
|
||||||
argN := 0 |
|
||||||
for _, param := range in { |
|
||||||
p := parseParam(param) |
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { |
|
||||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))") |
|
||||||
} else if p.Type == "string" && errvar != "" { |
|
||||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "string" { |
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") |
|
||||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) |
|
||||||
n++ |
|
||||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { |
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) |
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n)) |
|
||||||
n++ |
|
||||||
text += fmt.Sprintf("\tvar _p%d int\n", n) |
|
||||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "int64" && endianness != "" { |
|
||||||
if endianness == "big-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) |
|
||||||
} |
|
||||||
n++ |
|
||||||
} else if p.Type == "bool" { |
|
||||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n) |
|
||||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) |
|
||||||
args = append(args, fmt.Sprintf("_p%d", n)) |
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) |
|
||||||
} else if p.Type == "unsafe.Pointer" { |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) |
|
||||||
} else if p.Type == "int" { |
|
||||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) { |
|
||||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name)) |
|
||||||
} else if argN == 0 && funct == "fcntl" { |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) { |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) |
|
||||||
} |
|
||||||
} else if p.Type == "int32" { |
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) |
|
||||||
} else if p.Type == "int64" { |
|
||||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name)) |
|
||||||
} else if p.Type == "uint32" { |
|
||||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name)) |
|
||||||
} else if p.Type == "uint64" { |
|
||||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name)) |
|
||||||
} else if p.Type == "uintptr" { |
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) |
|
||||||
} |
|
||||||
argN++ |
|
||||||
} |
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ") |
|
||||||
call := "" |
|
||||||
if sysname == "exit" { |
|
||||||
if errvar != "" { |
|
||||||
call += "er :=" |
|
||||||
} else { |
|
||||||
call += "" |
|
||||||
} |
|
||||||
} else if errvar != "" { |
|
||||||
call += "r0,er :=" |
|
||||||
} else if retvar != "" { |
|
||||||
call += "r0,_ :=" |
|
||||||
} else { |
|
||||||
call += "" |
|
||||||
} |
|
||||||
if sysname == "select" { |
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist) |
|
||||||
} else { |
|
||||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist) |
|
||||||
} |
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := "" |
|
||||||
for i := 0; i < len(out); i++ { |
|
||||||
p := parseParam(out[i]) |
|
||||||
reg := "" |
|
||||||
if p.Name == "err" { |
|
||||||
reg = "e1" |
|
||||||
} else { |
|
||||||
reg = "r0" |
|
||||||
} |
|
||||||
if reg != "e1" { |
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// verify return
|
|
||||||
if sysname != "exit" && errvar != "" { |
|
||||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil { |
|
||||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n" |
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar) |
|
||||||
body += "\t}\n" |
|
||||||
} else { |
|
||||||
body += "\tif (r0 ==-1 && er != nil) {\n" |
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar) |
|
||||||
body += "\t}\n" |
|
||||||
} |
|
||||||
} else if errvar != "" { |
|
||||||
body += "\tif (er != nil) {\n" |
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar) |
|
||||||
body += "\t}\n" |
|
||||||
} |
|
||||||
|
|
||||||
text += fmt.Sprintf("\t%s\n", call) |
|
||||||
text += body |
|
||||||
|
|
||||||
text += "\treturn\n" |
|
||||||
text += "}\n" |
|
||||||
} |
|
||||||
if err := s.Err(); err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
file.Close() |
|
||||||
} |
|
||||||
imp := "" |
|
||||||
if pack != "unix" { |
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n" |
|
||||||
|
|
||||||
} |
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text) |
|
||||||
} |
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s |
|
||||||
|
|
||||||
|
|
||||||
%s |
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
import ( |
|
||||||
"unsafe" |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
%s |
|
||||||
|
|
||||||
%s |
|
||||||
` |
|
@ -1,614 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
This program reads a file containing function prototypes |
|
||||||
(like syscall_aix.go) and generates system call bodies. |
|
||||||
The prototypes are marked by lines beginning with "//sys" |
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument. |
|
||||||
This includes return parameters. |
|
||||||
* The parameter lists must give a type for each argument: |
|
||||||
the (x, y, z int) shorthand is not allowed. |
|
||||||
* If the return parameter is an error number, it must be named err. |
|
||||||
* If go func name needs to be different than its libc name, |
|
||||||
* or the function is not in libc, name could be specified |
|
||||||
* at the end, after "=" sign, like |
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
|
|
||||||
|
|
||||||
This program will generate three files and handle both gc and gccgo implementation: |
|
||||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) |
|
||||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
|
||||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. |
|
||||||
|
|
||||||
The generated code looks like this |
|
||||||
|
|
||||||
zsyscall_aix_ppc64.go |
|
||||||
func asyscall(...) (n int, err error) { |
|
||||||
// Pointer Creation
|
|
||||||
r1, e1 := callasyscall(...) |
|
||||||
// Type Conversion
|
|
||||||
// Error Handler
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
zsyscall_aix_ppc64_gc.go |
|
||||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
|
||||||
//go:linkname libc_asyscall libc_asyscall
|
|
||||||
var asyscall syscallFunc |
|
||||||
|
|
||||||
func callasyscall(...) (r1 uintptr, e1 Errno) { |
|
||||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
zsyscall_aix_ppc64_ggcgo.go |
|
||||||
|
|
||||||
// int asyscall(...)
|
|
||||||
|
|
||||||
import "C" |
|
||||||
|
|
||||||
func callasyscall(...) (r1 uintptr, e1 Errno) { |
|
||||||
r1 = uintptr(C.asyscall(...)) |
|
||||||
e1 = syscall.GetErrno() |
|
||||||
return |
|
||||||
} |
|
||||||
*/ |
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"io/ioutil" |
|
||||||
"os" |
|
||||||
"regexp" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian") |
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian") |
|
||||||
aix = flag.Bool("aix", false, "aix") |
|
||||||
tags = flag.String("tags", "", "build tags") |
|
||||||
) |
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string { |
|
||||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ") |
|
||||||
} |
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string { |
|
||||||
return *tags |
|
||||||
} |
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct { |
|
||||||
Name string |
|
||||||
Type string |
|
||||||
} |
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() { |
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string { |
|
||||||
list = strings.TrimSpace(list) |
|
||||||
if list == "" { |
|
||||||
return []string{} |
|
||||||
} |
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param { |
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) |
|
||||||
if ps == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
return Param{ps[1], ps[2]} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Usage = usage |
|
||||||
flag.Parse() |
|
||||||
if len(flag.Args()) <= 0 { |
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n") |
|
||||||
usage() |
|
||||||
} |
|
||||||
|
|
||||||
endianness := "" |
|
||||||
if *b32 { |
|
||||||
endianness = "big-endian" |
|
||||||
} else if *l32 { |
|
||||||
endianness = "little-endian" |
|
||||||
} |
|
||||||
|
|
||||||
pack := "" |
|
||||||
// GCCGO
|
|
||||||
textgccgo := "" |
|
||||||
cExtern := "/*\n#include <stdint.h>\n" |
|
||||||
// GC
|
|
||||||
textgc := "" |
|
||||||
dynimports := "" |
|
||||||
linknames := "" |
|
||||||
var vars []string |
|
||||||
// COMMON
|
|
||||||
textcommon := "" |
|
||||||
for _, path := range flag.Args() { |
|
||||||
file, err := os.Open(path) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
s := bufio.NewScanner(file) |
|
||||||
for s.Scan() { |
|
||||||
t := s.Text() |
|
||||||
t = strings.TrimSpace(t) |
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) |
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { |
|
||||||
pack = p[1] |
|
||||||
} |
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) |
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) |
|
||||||
if f == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] |
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps) |
|
||||||
out := parseParamList(outps) |
|
||||||
|
|
||||||
inps = strings.Join(in, ", ") |
|
||||||
outps = strings.Join(out, ", ") |
|
||||||
|
|
||||||
if sysname == "" { |
|
||||||
sysname = funct |
|
||||||
} |
|
||||||
|
|
||||||
onlyCommon := false |
|
||||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" { |
|
||||||
// This function call another syscall which is already implemented.
|
|
||||||
// Therefore, the gc and gccgo part must not be generated.
|
|
||||||
onlyCommon = true |
|
||||||
} |
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
|
|
||||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" |
|
||||||
if !onlyCommon { |
|
||||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" |
|
||||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" |
|
||||||
} |
|
||||||
|
|
||||||
// Check if value return, err return available
|
|
||||||
errvar := "" |
|
||||||
rettype := "" |
|
||||||
for _, param := range out { |
|
||||||
p := parseParam(param) |
|
||||||
if p.Type == "error" { |
|
||||||
errvar = p.Name |
|
||||||
} else { |
|
||||||
rettype = p.Type |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) |
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
// GCCGO Prototype return type
|
|
||||||
cRettype := "" |
|
||||||
if rettype == "unsafe.Pointer" { |
|
||||||
cRettype = "uintptr_t" |
|
||||||
} else if rettype == "uintptr" { |
|
||||||
cRettype = "uintptr_t" |
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { |
|
||||||
cRettype = "uintptr_t" |
|
||||||
} else if rettype == "int" { |
|
||||||
cRettype = "int" |
|
||||||
} else if rettype == "int32" { |
|
||||||
cRettype = "int" |
|
||||||
} else if rettype == "int64" { |
|
||||||
cRettype = "long long" |
|
||||||
} else if rettype == "uint32" { |
|
||||||
cRettype = "unsigned int" |
|
||||||
} else if rettype == "uint64" { |
|
||||||
cRettype = "unsigned long long" |
|
||||||
} else { |
|
||||||
cRettype = "int" |
|
||||||
} |
|
||||||
if sysname == "exit" { |
|
||||||
cRettype = "void" |
|
||||||
} |
|
||||||
|
|
||||||
// GCCGO Prototype arguments type
|
|
||||||
var cIn []string |
|
||||||
for i, param := range in { |
|
||||||
p := parseParam(param) |
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if p.Type == "string" { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { |
|
||||||
cIn = append(cIn, "uintptr_t", "size_t") |
|
||||||
} else if p.Type == "unsafe.Pointer" { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if p.Type == "uintptr" { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { |
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else if p.Type == "int" { |
|
||||||
if (i == 0 || i == 2) && funct == "fcntl" { |
|
||||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
|
||||||
cIn = append(cIn, "uintptr_t") |
|
||||||
} else { |
|
||||||
cIn = append(cIn, "int") |
|
||||||
} |
|
||||||
|
|
||||||
} else if p.Type == "int32" { |
|
||||||
cIn = append(cIn, "int") |
|
||||||
} else if p.Type == "int64" { |
|
||||||
cIn = append(cIn, "long long") |
|
||||||
} else if p.Type == "uint32" { |
|
||||||
cIn = append(cIn, "unsigned int") |
|
||||||
} else if p.Type == "uint64" { |
|
||||||
cIn = append(cIn, "unsigned long long") |
|
||||||
} else { |
|
||||||
cIn = append(cIn, "int") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if !onlyCommon { |
|
||||||
// GCCGO Prototype Generation
|
|
||||||
// Imports of system calls from libc
|
|
||||||
if sysname == "select" { |
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
cExtern += "#define c_select select\n" |
|
||||||
} |
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname) |
|
||||||
cIn := strings.Join(cIn, ", ") |
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn) |
|
||||||
} |
|
||||||
// GC Library name
|
|
||||||
if modname == "" { |
|
||||||
modname = "libc.a/shr_64.o" |
|
||||||
} else { |
|
||||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
sysvarname := fmt.Sprintf("libc_%s", sysname) |
|
||||||
|
|
||||||
if !onlyCommon { |
|
||||||
// GC Runtime import of function to allow cross-platform builds.
|
|
||||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname) |
|
||||||
// GC Link symbol to proc address variable.
|
|
||||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname) |
|
||||||
// GC Library proc address variable.
|
|
||||||
vars = append(vars, sysvarname) |
|
||||||
} |
|
||||||
|
|
||||||
strconvfunc := "BytePtrFromString" |
|
||||||
strconvtype := "*byte" |
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
if outps != "" { |
|
||||||
outps = fmt.Sprintf(" (%s)", outps) |
|
||||||
} |
|
||||||
if textcommon != "" { |
|
||||||
textcommon += "\n" |
|
||||||
} |
|
||||||
|
|
||||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) |
|
||||||
|
|
||||||
// Prepare arguments tocall.
|
|
||||||
var argscommon []string // Arguments in the common part
|
|
||||||
var argscall []string // Arguments for call prototype
|
|
||||||
var argsgc []string // Arguments for gc call (with syscall6)
|
|
||||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
|
||||||
n := 0 |
|
||||||
argN := 0 |
|
||||||
for _, param := range in { |
|
||||||
p := parseParam(param) |
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { |
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) |
|
||||||
argsgc = append(argsgc, p.Name) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
} else if p.Type == "string" && errvar != "" { |
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) |
|
||||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) |
|
||||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) |
|
||||||
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "string" { |
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") |
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) |
|
||||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) |
|
||||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) |
|
||||||
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) |
|
||||||
n++ |
|
||||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { |
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) |
|
||||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) |
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "int64" && endianness != "" { |
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n") |
|
||||||
} else if p.Type == "bool" { |
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n") |
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" { |
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) |
|
||||||
argsgc = append(argsgc, p.Name) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
} else if p.Type == "int" { |
|
||||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) { |
|
||||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) |
|
||||||
argsgc = append(argsgc, p.Name) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
|
|
||||||
} else { |
|
||||||
argscommon = append(argscommon, p.Name) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) |
|
||||||
} |
|
||||||
} else if p.Type == "int32" { |
|
||||||
argscommon = append(argscommon, p.Name) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) |
|
||||||
} else if p.Type == "int64" { |
|
||||||
argscommon = append(argscommon, p.Name) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name)) |
|
||||||
} else if p.Type == "uint32" { |
|
||||||
argscommon = append(argscommon, p.Name) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name)) |
|
||||||
} else if p.Type == "uint64" { |
|
||||||
argscommon = append(argscommon, p.Name) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name)) |
|
||||||
} else if p.Type == "uintptr" { |
|
||||||
argscommon = append(argscommon, p.Name) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) |
|
||||||
argsgc = append(argsgc, p.Name) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) |
|
||||||
} else { |
|
||||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name)) |
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) |
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) |
|
||||||
} |
|
||||||
argN++ |
|
||||||
} |
|
||||||
nargs := len(argsgc) |
|
||||||
|
|
||||||
// COMMON function generation
|
|
||||||
argscommonlist := strings.Join(argscommon, ", ") |
|
||||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist) |
|
||||||
ret := []string{"_", "_"} |
|
||||||
body := "" |
|
||||||
doErrno := false |
|
||||||
for i := 0; i < len(out); i++ { |
|
||||||
p := parseParam(out[i]) |
|
||||||
reg := "" |
|
||||||
if p.Name == "err" { |
|
||||||
reg = "e1" |
|
||||||
ret[1] = reg |
|
||||||
doErrno = true |
|
||||||
} else { |
|
||||||
reg = "r0" |
|
||||||
ret[0] = reg |
|
||||||
} |
|
||||||
if p.Type == "bool" { |
|
||||||
reg = fmt.Sprintf("%s != 0", reg) |
|
||||||
} |
|
||||||
if reg != "e1" { |
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) |
|
||||||
} |
|
||||||
} |
|
||||||
if ret[0] == "_" && ret[1] == "_" { |
|
||||||
textcommon += fmt.Sprintf("\t%s\n", callcommon) |
|
||||||
} else { |
|
||||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon) |
|
||||||
} |
|
||||||
textcommon += body |
|
||||||
|
|
||||||
if doErrno { |
|
||||||
textcommon += "\tif e1 != 0 {\n" |
|
||||||
textcommon += "\t\terr = errnoErr(e1)\n" |
|
||||||
textcommon += "\t}\n" |
|
||||||
} |
|
||||||
textcommon += "\treturn\n" |
|
||||||
textcommon += "}\n" |
|
||||||
|
|
||||||
if onlyCommon { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// CALL Prototype
|
|
||||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", ")) |
|
||||||
|
|
||||||
// GC function generation
|
|
||||||
asm := "syscall6" |
|
||||||
if nonblock != nil { |
|
||||||
asm = "rawSyscall6" |
|
||||||
} |
|
||||||
|
|
||||||
if len(argsgc) <= 6 { |
|
||||||
for len(argsgc) < 6 { |
|
||||||
argsgc = append(argsgc, "0") |
|
||||||
} |
|
||||||
} else { |
|
||||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
argsgclist := strings.Join(argsgc, ", ") |
|
||||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist) |
|
||||||
|
|
||||||
textgc += callProto |
|
||||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc) |
|
||||||
textgc += "\treturn\n}\n" |
|
||||||
|
|
||||||
// GCCGO function generation
|
|
||||||
argsgccgolist := strings.Join(argsgccgo, ", ") |
|
||||||
var callgccgo string |
|
||||||
if sysname == "select" { |
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist) |
|
||||||
} else { |
|
||||||
callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist) |
|
||||||
} |
|
||||||
textgccgo += callProto |
|
||||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo) |
|
||||||
textgccgo += "\te1 = syscall.GetErrno()\n" |
|
||||||
textgccgo += "\treturn\n}\n" |
|
||||||
} |
|
||||||
if err := s.Err(); err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
file.Close() |
|
||||||
} |
|
||||||
imp := "" |
|
||||||
if pack != "unix" { |
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n" |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64.go
|
|
||||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go", |
|
||||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)), |
|
||||||
0644) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64_gc.go
|
|
||||||
vardecls := "\t" + strings.Join(vars, ",\n\t") |
|
||||||
vardecls += " syscallFunc" |
|
||||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go", |
|
||||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)), |
|
||||||
0644) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64_gccgo.go
|
|
||||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go", |
|
||||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)), |
|
||||||
0644) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const srcTemplate1 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s |
|
||||||
|
|
||||||
import ( |
|
||||||
"unsafe" |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
%s |
|
||||||
|
|
||||||
%s |
|
||||||
` |
|
||||||
const srcTemplate2 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
// +build !gccgo
|
|
||||||
|
|
||||||
package %s |
|
||||||
|
|
||||||
import ( |
|
||||||
"unsafe" |
|
||||||
) |
|
||||||
%s |
|
||||||
%s |
|
||||||
%s |
|
||||||
type syscallFunc uintptr |
|
||||||
|
|
||||||
var ( |
|
||||||
%s |
|
||||||
) |
|
||||||
|
|
||||||
// Implemented in runtime/syscall_aix.go.
|
|
||||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) |
|
||||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) |
|
||||||
|
|
||||||
%s |
|
||||||
` |
|
||||||
const srcTemplate3 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
// +build gccgo
|
|
||||||
|
|
||||||
package %s |
|
||||||
|
|
||||||
%s |
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
import ( |
|
||||||
"syscall" |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
%s |
|
||||||
|
|
||||||
%s |
|
||||||
` |
|
@ -1,335 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
This program reads a file containing function prototypes |
|
||||||
(like syscall_solaris.go) and generates system call bodies. |
|
||||||
The prototypes are marked by lines beginning with "//sys" |
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument. |
|
||||||
This includes return parameters. |
|
||||||
* The parameter lists must give a type for each argument: |
|
||||||
the (x, y, z int) shorthand is not allowed. |
|
||||||
* If the return parameter is an error number, it must be named err. |
|
||||||
* If go func name needs to be different than its libc name, |
|
||||||
* or the function is not in libc, name could be specified |
|
||||||
* at the end, after "=" sign, like |
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
*/ |
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"flag" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"regexp" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian") |
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian") |
|
||||||
tags = flag.String("tags", "", "build tags") |
|
||||||
) |
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string { |
|
||||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ") |
|
||||||
} |
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string { |
|
||||||
return *tags |
|
||||||
} |
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct { |
|
||||||
Name string |
|
||||||
Type string |
|
||||||
} |
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() { |
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string { |
|
||||||
list = strings.TrimSpace(list) |
|
||||||
if list == "" { |
|
||||||
return []string{} |
|
||||||
} |
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1) |
|
||||||
} |
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param { |
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) |
|
||||||
if ps == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
return Param{ps[1], ps[2]} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
flag.Usage = usage |
|
||||||
flag.Parse() |
|
||||||
if len(flag.Args()) <= 0 { |
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n") |
|
||||||
usage() |
|
||||||
} |
|
||||||
|
|
||||||
endianness := "" |
|
||||||
if *b32 { |
|
||||||
endianness = "big-endian" |
|
||||||
} else if *l32 { |
|
||||||
endianness = "little-endian" |
|
||||||
} |
|
||||||
|
|
||||||
pack := "" |
|
||||||
text := "" |
|
||||||
dynimports := "" |
|
||||||
linknames := "" |
|
||||||
var vars []string |
|
||||||
for _, path := range flag.Args() { |
|
||||||
file, err := os.Open(path) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
s := bufio.NewScanner(file) |
|
||||||
for s.Scan() { |
|
||||||
t := s.Text() |
|
||||||
t = strings.TrimSpace(t) |
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) |
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { |
|
||||||
pack = p[1] |
|
||||||
} |
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) |
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) |
|
||||||
if f == nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] |
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps) |
|
||||||
out := parseParamList(outps) |
|
||||||
|
|
||||||
inps = strings.Join(in, ", ") |
|
||||||
outps = strings.Join(out, ", ") |
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" |
|
||||||
|
|
||||||
// So file name.
|
|
||||||
if modname == "" { |
|
||||||
modname = "libc" |
|
||||||
} |
|
||||||
|
|
||||||
// System call name.
|
|
||||||
if sysname == "" { |
|
||||||
sysname = funct |
|
||||||
} |
|
||||||
|
|
||||||
// System call pointer variable name.
|
|
||||||
sysvarname := fmt.Sprintf("proc%s", sysname) |
|
||||||
|
|
||||||
strconvfunc := "BytePtrFromString" |
|
||||||
strconvtype := "*byte" |
|
||||||
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
// Runtime import of function to allow cross-platform builds.
|
|
||||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname) |
|
||||||
// Link symbol to proc address variable.
|
|
||||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname) |
|
||||||
// Library proc address variable.
|
|
||||||
vars = append(vars, sysvarname) |
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
outlist := strings.Join(out, ", ") |
|
||||||
if outlist != "" { |
|
||||||
outlist = fmt.Sprintf(" (%s)", outlist) |
|
||||||
} |
|
||||||
if text != "" { |
|
||||||
text += "\n" |
|
||||||
} |
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist) |
|
||||||
|
|
||||||
// Check if err return available
|
|
||||||
errvar := "" |
|
||||||
for _, param := range out { |
|
||||||
p := parseParam(param) |
|
||||||
if p.Type == "error" { |
|
||||||
errvar = p.Name |
|
||||||
continue |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string |
|
||||||
n := 0 |
|
||||||
for _, param := range in { |
|
||||||
p := parseParam(param) |
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { |
|
||||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") |
|
||||||
} else if p.Type == "string" && errvar != "" { |
|
||||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) |
|
||||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) |
|
||||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "string" { |
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") |
|
||||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) |
|
||||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) |
|
||||||
n++ |
|
||||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil { |
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1]) |
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) |
|
||||||
n++ |
|
||||||
} else if p.Type == "int64" && endianness != "" { |
|
||||||
if endianness == "big-endian" { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) |
|
||||||
} |
|
||||||
} else if p.Type == "bool" { |
|
||||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n) |
|
||||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) |
|
||||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n)) |
|
||||||
n++ |
|
||||||
} else { |
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) |
|
||||||
} |
|
||||||
} |
|
||||||
nargs := len(args) |
|
||||||
|
|
||||||
// Determine which form to use; pad args with zeros.
|
|
||||||
asm := "sysvicall6" |
|
||||||
if nonblock != nil { |
|
||||||
asm = "rawSysvicall6" |
|
||||||
} |
|
||||||
if len(args) <= 6 { |
|
||||||
for len(args) < 6 { |
|
||||||
args = append(args, "0") |
|
||||||
} |
|
||||||
} else { |
|
||||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ") |
|
||||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist) |
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := "" |
|
||||||
ret := []string{"_", "_", "_"} |
|
||||||
doErrno := false |
|
||||||
for i := 0; i < len(out); i++ { |
|
||||||
p := parseParam(out[i]) |
|
||||||
reg := "" |
|
||||||
if p.Name == "err" { |
|
||||||
reg = "e1" |
|
||||||
ret[2] = reg |
|
||||||
doErrno = true |
|
||||||
} else { |
|
||||||
reg = fmt.Sprintf("r%d", i) |
|
||||||
ret[i] = reg |
|
||||||
} |
|
||||||
if p.Type == "bool" { |
|
||||||
reg = fmt.Sprintf("%d != 0", reg) |
|
||||||
} |
|
||||||
if p.Type == "int64" && endianness != "" { |
|
||||||
// 64-bit number in r1:r0 or r0:r1.
|
|
||||||
if i+2 > len(out) { |
|
||||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
if endianness == "big-endian" { |
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) |
|
||||||
} else { |
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) |
|
||||||
} |
|
||||||
ret[i] = fmt.Sprintf("r%d", i) |
|
||||||
ret[i+1] = fmt.Sprintf("r%d", i+1) |
|
||||||
} |
|
||||||
if reg != "e1" { |
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) |
|
||||||
} |
|
||||||
} |
|
||||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { |
|
||||||
text += fmt.Sprintf("\t%s\n", call) |
|
||||||
} else { |
|
||||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) |
|
||||||
} |
|
||||||
text += body |
|
||||||
|
|
||||||
if doErrno { |
|
||||||
text += "\tif e1 != 0 {\n" |
|
||||||
text += "\t\terr = e1\n" |
|
||||||
text += "\t}\n" |
|
||||||
} |
|
||||||
text += "\treturn\n" |
|
||||||
text += "}\n" |
|
||||||
} |
|
||||||
if err := s.Err(); err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, err.Error()) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
file.Close() |
|
||||||
} |
|
||||||
imp := "" |
|
||||||
if pack != "unix" { |
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n" |
|
||||||
|
|
||||||
} |
|
||||||
vardecls := "\t" + strings.Join(vars, ",\n\t") |
|
||||||
vardecls += " syscallFunc" |
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text) |
|
||||||
} |
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s |
|
||||||
|
|
||||||
import ( |
|
||||||
"syscall" |
|
||||||
"unsafe" |
|
||||||
) |
|
||||||
%s |
|
||||||
%s |
|
||||||
%s |
|
||||||
var ( |
|
||||||
%s
|
|
||||||
) |
|
||||||
|
|
||||||
%s |
|
||||||
` |
|
@ -1,355 +0,0 @@ |
|||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
|
||||||
//
|
|
||||||
// Build a MIB with each entry being an array containing the level, type and
|
|
||||||
// a hash that will contain additional entries if the current entry is a node.
|
|
||||||
// We then walk this MIB and create a flattened sysctl name to OID hash.
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"path/filepath" |
|
||||||
"regexp" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
goos, goarch string |
|
||||||
) |
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments.
|
|
||||||
func cmdLine() string { |
|
||||||
return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ") |
|
||||||
} |
|
||||||
|
|
||||||
// buildTags returns build tags.
|
|
||||||
func buildTags() string { |
|
||||||
return fmt.Sprintf("%s,%s", goarch, goos) |
|
||||||
} |
|
||||||
|
|
||||||
// reMatch performs regular expression match and stores the substring slice to value pointed by m.
|
|
||||||
func reMatch(re *regexp.Regexp, str string, m *[]string) bool { |
|
||||||
*m = re.FindStringSubmatch(str) |
|
||||||
if *m != nil { |
|
||||||
return true |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
type nodeElement struct { |
|
||||||
n int |
|
||||||
t string |
|
||||||
pE *map[string]nodeElement |
|
||||||
} |
|
||||||
|
|
||||||
var ( |
|
||||||
debugEnabled bool |
|
||||||
mib map[string]nodeElement |
|
||||||
node *map[string]nodeElement |
|
||||||
nodeMap map[string]string |
|
||||||
sysCtl []string |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`) |
|
||||||
ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`) |
|
||||||
ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`) |
|
||||||
netInetRE = regexp.MustCompile(`^netinet/`) |
|
||||||
netInet6RE = regexp.MustCompile(`^netinet6/`) |
|
||||||
netRE = regexp.MustCompile(`^net/`) |
|
||||||
bracesRE = regexp.MustCompile(`{.*}`) |
|
||||||
ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`) |
|
||||||
fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`) |
|
||||||
) |
|
||||||
|
|
||||||
func debug(s string) { |
|
||||||
if debugEnabled { |
|
||||||
fmt.Fprintln(os.Stderr, s) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Walk the MIB and build a sysctl name to OID mapping.
|
|
||||||
func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) { |
|
||||||
lNode := pNode // local copy of pointer to node
|
|
||||||
var keys []string |
|
||||||
for k := range *lNode { |
|
||||||
keys = append(keys, k) |
|
||||||
} |
|
||||||
sort.Strings(keys) |
|
||||||
|
|
||||||
for _, key := range keys { |
|
||||||
nodename := name |
|
||||||
if name != "" { |
|
||||||
nodename += "." |
|
||||||
} |
|
||||||
nodename += key |
|
||||||
|
|
||||||
nodeoid := append(oid, (*pNode)[key].n) |
|
||||||
|
|
||||||
if (*pNode)[key].t == `CTLTYPE_NODE` { |
|
||||||
if _, ok := nodeMap[nodename]; ok { |
|
||||||
lNode = &mib |
|
||||||
ctlName := nodeMap[nodename] |
|
||||||
for _, part := range strings.Split(ctlName, ".") { |
|
||||||
lNode = ((*lNode)[part]).pE |
|
||||||
} |
|
||||||
} else { |
|
||||||
lNode = (*pNode)[key].pE |
|
||||||
} |
|
||||||
buildSysctl(lNode, nodename, nodeoid) |
|
||||||
} else if (*pNode)[key].t != "" { |
|
||||||
oidStr := []string{} |
|
||||||
for j := range nodeoid { |
|
||||||
oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j])) |
|
||||||
} |
|
||||||
text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n" |
|
||||||
sysCtl = append(sysCtl, text) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
// Get the OS (using GOOS_TARGET if it exist)
|
|
||||||
goos = os.Getenv("GOOS_TARGET") |
|
||||||
if goos == "" { |
|
||||||
goos = os.Getenv("GOOS") |
|
||||||
} |
|
||||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goarch = os.Getenv("GOARCH_TARGET") |
|
||||||
if goarch == "" { |
|
||||||
goarch = os.Getenv("GOARCH") |
|
||||||
} |
|
||||||
// Check if GOOS and GOARCH environment variables are defined
|
|
||||||
if goarch == "" || goos == "" { |
|
||||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
mib = make(map[string]nodeElement) |
|
||||||
headers := [...]string{ |
|
||||||
`sys/sysctl.h`, |
|
||||||
`sys/socket.h`, |
|
||||||
`sys/tty.h`, |
|
||||||
`sys/malloc.h`, |
|
||||||
`sys/mount.h`, |
|
||||||
`sys/namei.h`, |
|
||||||
`sys/sem.h`, |
|
||||||
`sys/shm.h`, |
|
||||||
`sys/vmmeter.h`, |
|
||||||
`uvm/uvmexp.h`, |
|
||||||
`uvm/uvm_param.h`, |
|
||||||
`uvm/uvm_swap_encrypt.h`, |
|
||||||
`ddb/db_var.h`, |
|
||||||
`net/if.h`, |
|
||||||
`net/if_pfsync.h`, |
|
||||||
`net/pipex.h`, |
|
||||||
`netinet/in.h`, |
|
||||||
`netinet/icmp_var.h`, |
|
||||||
`netinet/igmp_var.h`, |
|
||||||
`netinet/ip_ah.h`, |
|
||||||
`netinet/ip_carp.h`, |
|
||||||
`netinet/ip_divert.h`, |
|
||||||
`netinet/ip_esp.h`, |
|
||||||
`netinet/ip_ether.h`, |
|
||||||
`netinet/ip_gre.h`, |
|
||||||
`netinet/ip_ipcomp.h`, |
|
||||||
`netinet/ip_ipip.h`, |
|
||||||
`netinet/pim_var.h`, |
|
||||||
`netinet/tcp_var.h`, |
|
||||||
`netinet/udp_var.h`, |
|
||||||
`netinet6/in6.h`, |
|
||||||
`netinet6/ip6_divert.h`, |
|
||||||
`netinet6/pim6_var.h`, |
|
||||||
`netinet/icmp6.h`, |
|
||||||
`netmpls/mpls.h`, |
|
||||||
} |
|
||||||
|
|
||||||
ctls := [...]string{ |
|
||||||
`kern`, |
|
||||||
`vm`, |
|
||||||
`fs`, |
|
||||||
`net`, |
|
||||||
//debug /* Special handling required */
|
|
||||||
`hw`, |
|
||||||
//machdep /* Arch specific */
|
|
||||||
`user`, |
|
||||||
`ddb`, |
|
||||||
//vfs /* Special handling required */
|
|
||||||
`fs.posix`, |
|
||||||
`kern.forkstat`, |
|
||||||
`kern.intrcnt`, |
|
||||||
`kern.malloc`, |
|
||||||
`kern.nchstats`, |
|
||||||
`kern.seminfo`, |
|
||||||
`kern.shminfo`, |
|
||||||
`kern.timecounter`, |
|
||||||
`kern.tty`, |
|
||||||
`kern.watchdog`, |
|
||||||
`net.bpf`, |
|
||||||
`net.ifq`, |
|
||||||
`net.inet`, |
|
||||||
`net.inet.ah`, |
|
||||||
`net.inet.carp`, |
|
||||||
`net.inet.divert`, |
|
||||||
`net.inet.esp`, |
|
||||||
`net.inet.etherip`, |
|
||||||
`net.inet.gre`, |
|
||||||
`net.inet.icmp`, |
|
||||||
`net.inet.igmp`, |
|
||||||
`net.inet.ip`, |
|
||||||
`net.inet.ip.ifq`, |
|
||||||
`net.inet.ipcomp`, |
|
||||||
`net.inet.ipip`, |
|
||||||
`net.inet.mobileip`, |
|
||||||
`net.inet.pfsync`, |
|
||||||
`net.inet.pim`, |
|
||||||
`net.inet.tcp`, |
|
||||||
`net.inet.udp`, |
|
||||||
`net.inet6`, |
|
||||||
`net.inet6.divert`, |
|
||||||
`net.inet6.ip6`, |
|
||||||
`net.inet6.icmp6`, |
|
||||||
`net.inet6.pim6`, |
|
||||||
`net.inet6.tcp6`, |
|
||||||
`net.inet6.udp6`, |
|
||||||
`net.mpls`, |
|
||||||
`net.mpls.ifq`, |
|
||||||
`net.key`, |
|
||||||
`net.pflow`, |
|
||||||
`net.pfsync`, |
|
||||||
`net.pipex`, |
|
||||||
`net.rt`, |
|
||||||
`vm.swapencrypt`, |
|
||||||
//vfsgenctl /* Special handling required */
|
|
||||||
} |
|
||||||
|
|
||||||
// Node name "fixups"
|
|
||||||
ctlMap := map[string]string{ |
|
||||||
"ipproto": "net.inet", |
|
||||||
"net.inet.ipproto": "net.inet", |
|
||||||
"net.inet6.ipv6proto": "net.inet6", |
|
||||||
"net.inet6.ipv6": "net.inet6.ip6", |
|
||||||
"net.inet.icmpv6": "net.inet6.icmp6", |
|
||||||
"net.inet6.divert6": "net.inet6.divert", |
|
||||||
"net.inet6.tcp6": "net.inet.tcp", |
|
||||||
"net.inet6.udp6": "net.inet.udp", |
|
||||||
"mpls": "net.mpls", |
|
||||||
"swpenc": "vm.swapencrypt", |
|
||||||
} |
|
||||||
|
|
||||||
// Node mappings
|
|
||||||
nodeMap = map[string]string{ |
|
||||||
"net.inet.ip.ifq": "net.ifq", |
|
||||||
"net.inet.pfsync": "net.pfsync", |
|
||||||
"net.mpls.ifq": "net.ifq", |
|
||||||
} |
|
||||||
|
|
||||||
mCtls := make(map[string]bool) |
|
||||||
for _, ctl := range ctls { |
|
||||||
mCtls[ctl] = true |
|
||||||
} |
|
||||||
|
|
||||||
for _, header := range headers { |
|
||||||
debug("Processing " + header) |
|
||||||
file, err := os.Open(filepath.Join("/usr/include", header)) |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
s := bufio.NewScanner(file) |
|
||||||
for s.Scan() { |
|
||||||
var sub []string |
|
||||||
if reMatch(ctlNames1RE, s.Text(), &sub) || |
|
||||||
reMatch(ctlNames2RE, s.Text(), &sub) || |
|
||||||
reMatch(ctlNames3RE, s.Text(), &sub) { |
|
||||||
if sub[1] == `CTL_NAMES` { |
|
||||||
// Top level.
|
|
||||||
node = &mib |
|
||||||
} else { |
|
||||||
// Node.
|
|
||||||
nodename := strings.ToLower(sub[2]) |
|
||||||
ctlName := "" |
|
||||||
if reMatch(netInetRE, header, &sub) { |
|
||||||
ctlName = "net.inet." + nodename |
|
||||||
} else if reMatch(netInet6RE, header, &sub) { |
|
||||||
ctlName = "net.inet6." + nodename |
|
||||||
} else if reMatch(netRE, header, &sub) { |
|
||||||
ctlName = "net." + nodename |
|
||||||
} else { |
|
||||||
ctlName = nodename |
|
||||||
ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`) |
|
||||||
} |
|
||||||
|
|
||||||
if val, ok := ctlMap[ctlName]; ok { |
|
||||||
ctlName = val |
|
||||||
} |
|
||||||
if _, ok := mCtls[ctlName]; !ok { |
|
||||||
debug("Ignoring " + ctlName + "...") |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
// Walk down from the top of the MIB.
|
|
||||||
node = &mib |
|
||||||
for _, part := range strings.Split(ctlName, ".") { |
|
||||||
if _, ok := (*node)[part]; !ok { |
|
||||||
debug("Missing node " + part) |
|
||||||
(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}} |
|
||||||
} |
|
||||||
node = (*node)[part].pE |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Populate current node with entries.
|
|
||||||
i := -1 |
|
||||||
for !strings.HasPrefix(s.Text(), "}") { |
|
||||||
s.Scan() |
|
||||||
if reMatch(bracesRE, s.Text(), &sub) { |
|
||||||
i++ |
|
||||||
} |
|
||||||
if !reMatch(ctlTypeRE, s.Text(), &sub) { |
|
||||||
continue |
|
||||||
} |
|
||||||
(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
err = s.Err() |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
file.Close() |
|
||||||
} |
|
||||||
buildSysctl(&mib, "", []int{}) |
|
||||||
|
|
||||||
sort.Strings(sysCtl) |
|
||||||
text := strings.Join(sysCtl, "") |
|
||||||
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) |
|
||||||
} |
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
type mibentry struct { |
|
||||||
ctlname string |
|
||||||
ctloid []_C_int |
|
||||||
} |
|
||||||
|
|
||||||
var sysctlMib = []mibentry { |
|
||||||
%s |
|
||||||
} |
|
||||||
` |
|
@ -1,190 +0,0 @@ |
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// Generate system call table for DragonFly, NetBSD,
|
|
||||||
// FreeBSD, OpenBSD or Darwin from master list
|
|
||||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
|
||||||
// sys/syscall.h).
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"io" |
|
||||||
"io/ioutil" |
|
||||||
"net/http" |
|
||||||
"os" |
|
||||||
"regexp" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
goos, goarch string |
|
||||||
) |
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string { |
|
||||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ") |
|
||||||
} |
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string { |
|
||||||
return fmt.Sprintf("%s,%s", goarch, goos) |
|
||||||
} |
|
||||||
|
|
||||||
func checkErr(err error) { |
|
||||||
if err != nil { |
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// source string and substring slice for regexp
|
|
||||||
type re struct { |
|
||||||
str string // source string
|
|
||||||
sub []string // matched sub-string
|
|
||||||
} |
|
||||||
|
|
||||||
// Match performs regular expression match
|
|
||||||
func (r *re) Match(exp string) bool { |
|
||||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str) |
|
||||||
if r.sub != nil { |
|
||||||
return true |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
// fetchFile fetches a text file from URL
|
|
||||||
func fetchFile(URL string) io.Reader { |
|
||||||
resp, err := http.Get(URL) |
|
||||||
checkErr(err) |
|
||||||
defer resp.Body.Close() |
|
||||||
body, err := ioutil.ReadAll(resp.Body) |
|
||||||
checkErr(err) |
|
||||||
return strings.NewReader(string(body)) |
|
||||||
} |
|
||||||
|
|
||||||
// readFile reads a text file from path
|
|
||||||
func readFile(path string) io.Reader { |
|
||||||
file, err := os.Open(os.Args[1]) |
|
||||||
checkErr(err) |
|
||||||
return file |
|
||||||
} |
|
||||||
|
|
||||||
func format(name, num, proto string) string { |
|
||||||
name = strings.ToUpper(name) |
|
||||||
// There are multiple entries for enosys and nosys, so comment them out.
|
|
||||||
nm := re{str: name} |
|
||||||
if nm.Match(`^SYS_E?NOSYS$`) { |
|
||||||
name = fmt.Sprintf("// %s", name) |
|
||||||
} |
|
||||||
if name == `SYS_SYS_EXIT` { |
|
||||||
name = `SYS_EXIT` |
|
||||||
} |
|
||||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
// Get the OS (using GOOS_TARGET if it exist)
|
|
||||||
goos = os.Getenv("GOOS_TARGET") |
|
||||||
if goos == "" { |
|
||||||
goos = os.Getenv("GOOS") |
|
||||||
} |
|
||||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goarch = os.Getenv("GOARCH_TARGET") |
|
||||||
if goarch == "" { |
|
||||||
goarch = os.Getenv("GOARCH") |
|
||||||
} |
|
||||||
// Check if GOOS and GOARCH environment variables are defined
|
|
||||||
if goarch == "" || goos == "" { |
|
||||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
|
|
||||||
file := strings.TrimSpace(os.Args[1]) |
|
||||||
var syscalls io.Reader |
|
||||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") { |
|
||||||
// Download syscalls.master file
|
|
||||||
syscalls = fetchFile(file) |
|
||||||
} else { |
|
||||||
syscalls = readFile(file) |
|
||||||
} |
|
||||||
|
|
||||||
var text, line string |
|
||||||
s := bufio.NewScanner(syscalls) |
|
||||||
for s.Scan() { |
|
||||||
t := re{str: line} |
|
||||||
if t.Match(`^(.*)\\$`) { |
|
||||||
// Handle continuation
|
|
||||||
line = t.sub[1] |
|
||||||
line += strings.TrimLeft(s.Text(), " \t") |
|
||||||
} else { |
|
||||||
// New line
|
|
||||||
line = s.Text() |
|
||||||
} |
|
||||||
t = re{str: line} |
|
||||||
if t.Match(`\\$`) { |
|
||||||
continue |
|
||||||
} |
|
||||||
t = re{str: line} |
|
||||||
|
|
||||||
switch goos { |
|
||||||
case "dragonfly": |
|
||||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) { |
|
||||||
num, proto := t.sub[1], t.sub[2] |
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3]) |
|
||||||
text += format(name, num, proto) |
|
||||||
} |
|
||||||
case "freebsd": |
|
||||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) { |
|
||||||
num, proto := t.sub[1], t.sub[2] |
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3]) |
|
||||||
text += format(name, num, proto) |
|
||||||
} |
|
||||||
case "openbsd": |
|
||||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) { |
|
||||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4] |
|
||||||
text += format(name, num, proto) |
|
||||||
} |
|
||||||
case "netbsd": |
|
||||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) { |
|
||||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8] |
|
||||||
name := t.sub[7] + "_" + t.sub[9] |
|
||||||
if t.sub[11] != "" { |
|
||||||
name = t.sub[7] + "_" + t.sub[11] |
|
||||||
} |
|
||||||
name = strings.ToUpper(name) |
|
||||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" { |
|
||||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) |
|
||||||
} |
|
||||||
} |
|
||||||
case "darwin": |
|
||||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) { |
|
||||||
name, num := t.sub[1], t.sub[2] |
|
||||||
name = strings.ToUpper(name) |
|
||||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num) |
|
||||||
} |
|
||||||
default: |
|
||||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos) |
|
||||||
os.Exit(1) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
err := s.Err() |
|
||||||
checkErr(err) |
|
||||||
|
|
||||||
fmt.Printf(template, cmdLine(), buildTags(), text) |
|
||||||
} |
|
||||||
|
|
||||||
const template = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
const( |
|
||||||
%s)` |
|
@ -1,237 +0,0 @@ |
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
// +build aix
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See also mkerrors.sh and mkall.sh |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/limits.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <utime.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/poll.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/statfs.h> |
|
||||||
#include <sys/termio.h> |
|
||||||
#include <sys/ioctl.h> |
|
||||||
|
|
||||||
#include <termios.h> |
|
||||||
|
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
|
|
||||||
|
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
PathMax = C.PATH_MAX |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
type off64 C.off64_t |
|
||||||
type off C.off_t |
|
||||||
type Mode_t C.mode_t |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
type Timeval32 C.struct_timeval32 |
|
||||||
|
|
||||||
type Timex C.struct_timex |
|
||||||
|
|
||||||
type Time_t C.time_t |
|
||||||
|
|
||||||
type Tms C.struct_tms |
|
||||||
|
|
||||||
type Utimbuf C.struct_utimbuf |
|
||||||
|
|
||||||
type Timezone C.struct_timezone |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit64 |
|
||||||
|
|
||||||
type Pid_t C.pid_t |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
type dev_t C.dev_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat |
|
||||||
|
|
||||||
type StatxTimestamp C.struct_statx_timestamp |
|
||||||
|
|
||||||
type Statx_t C.struct_statx |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
) |
|
||||||
|
|
||||||
type IfMsgHdr C.struct_if_msghdr |
|
||||||
|
|
||||||
// Misc
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
||||||
|
|
||||||
type Ustat_t C.struct_ustat |
|
||||||
|
|
||||||
type Sigset_t C.sigset_t |
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_REMOVEDIR = C.AT_REMOVEDIR |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
) |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Termio C.struct_termio |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
//poll
|
|
||||||
|
|
||||||
type PollFd struct { |
|
||||||
Fd int32 |
|
||||||
Events uint16 |
|
||||||
Revents uint16 |
|
||||||
} |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
||||||
|
|
||||||
//flock_t
|
|
||||||
|
|
||||||
type Flock_t C.struct_flock64 |
|
||||||
|
|
||||||
// Statfs
|
|
||||||
|
|
||||||
type Fsid_t C.struct_fsid_t |
|
||||||
type Fsid64_t C.struct_fsid64_t |
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs |
|
||||||
|
|
||||||
const RNDGETENTCNT = 0x80045200 |
|
@ -1,283 +0,0 @@ |
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See README.md |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#define __DARWIN_UNIX03 0 |
|
||||||
#define KERNEL |
|
||||||
#define _DARWIN_USE_64_BIT_INODE |
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <poll.h> |
|
||||||
#include <signal.h> |
|
||||||
#include <termios.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <mach/mach.h> |
|
||||||
#include <mach/message.h> |
|
||||||
#include <sys/event.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/mount.h> |
|
||||||
#include <sys/param.h> |
|
||||||
#include <sys/ptrace.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/select.h> |
|
||||||
#include <sys/signal.h> |
|
||||||
#include <sys/socket.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/uio.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/wait.h> |
|
||||||
#include <net/bpf.h> |
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <net/if_var.h> |
|
||||||
#include <net/route.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
#include <netinet/tcp.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
type Timeval32 C.struct_timeval32 |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat64 |
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs64 |
|
||||||
|
|
||||||
type Flock_t C.struct_flock |
|
||||||
|
|
||||||
type Fstore_t C.struct_fstore |
|
||||||
|
|
||||||
type Radvisory_t C.struct_radvisory |
|
||||||
|
|
||||||
type Fbootstraptransfer_t C.struct_fbootstraptransfer |
|
||||||
|
|
||||||
type Log2phys_t C.struct_log2phys |
|
||||||
|
|
||||||
type Fsid C.struct_fsid |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type Inet4Pktinfo C.struct_in_pktinfo |
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo |
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Ptrace requests
|
|
||||||
|
|
||||||
const ( |
|
||||||
PTRACE_TRACEME = C.PT_TRACE_ME |
|
||||||
PTRACE_CONT = C.PT_CONTINUE |
|
||||||
PTRACE_KILL = C.PT_KILL |
|
||||||
) |
|
||||||
|
|
||||||
// Events (kqueue, kevent)
|
|
||||||
|
|
||||||
type Kevent_t C.struct_kevent |
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
SizeofIfData = C.sizeof_struct_if_data |
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr |
|
||||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr |
|
||||||
SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2 |
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr |
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics |
|
||||||
) |
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr |
|
||||||
|
|
||||||
type IfData C.struct_if_data |
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr |
|
||||||
|
|
||||||
type IfmaMsghdr C.struct_ifma_msghdr |
|
||||||
|
|
||||||
type IfmaMsghdr2 C.struct_ifma_msghdr2 |
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr |
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics |
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version |
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat |
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program |
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn |
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr |
|
||||||
) |
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version |
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat |
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program |
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn |
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
// fchmodat-like syscalls.
|
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_REMOVEDIR = C.AT_REMOVEDIR |
|
||||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
) |
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
||||||
|
|
||||||
// uname
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
||||||
|
|
||||||
// Clockinfo
|
|
||||||
|
|
||||||
const SizeofClockinfo = C.sizeof_struct_clockinfo |
|
||||||
|
|
||||||
type Clockinfo C.struct_clockinfo |
|
@ -1,263 +0,0 @@ |
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See README.md |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#define KERNEL |
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <poll.h> |
|
||||||
#include <signal.h> |
|
||||||
#include <termios.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/event.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/mount.h> |
|
||||||
#include <sys/param.h> |
|
||||||
#include <sys/ptrace.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/select.h> |
|
||||||
#include <sys/signal.h> |
|
||||||
#include <sys/socket.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/wait.h> |
|
||||||
#include <net/bpf.h> |
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <net/route.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
#include <netinet/tcp.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat |
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs |
|
||||||
|
|
||||||
type Flock_t C.struct_flock |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
type Fsid C.struct_fsid |
|
||||||
|
|
||||||
// File system limits
|
|
||||||
|
|
||||||
const ( |
|
||||||
PathMax = C.PATH_MAX |
|
||||||
) |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Ptrace requests
|
|
||||||
|
|
||||||
const ( |
|
||||||
PTRACE_TRACEME = C.PT_TRACE_ME |
|
||||||
PTRACE_CONT = C.PT_CONTINUE |
|
||||||
PTRACE_KILL = C.PT_KILL |
|
||||||
) |
|
||||||
|
|
||||||
// Events (kqueue, kevent)
|
|
||||||
|
|
||||||
type Kevent_t C.struct_kevent |
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
SizeofIfData = C.sizeof_struct_if_data |
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr |
|
||||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr |
|
||||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr |
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr |
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics |
|
||||||
) |
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr |
|
||||||
|
|
||||||
type IfData C.struct_if_data |
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr |
|
||||||
|
|
||||||
type IfmaMsghdr C.struct_ifma_msghdr |
|
||||||
|
|
||||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr |
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr |
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics |
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version |
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat |
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program |
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn |
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr |
|
||||||
) |
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version |
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat |
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program |
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn |
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
// fchmodat-like syscalls.
|
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
) |
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
||||||
|
|
||||||
// Uname
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
@ -1,400 +0,0 @@ |
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See README.md |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#define _WANT_FREEBSD11_STAT 1 |
|
||||||
#define _WANT_FREEBSD11_STATFS 1 |
|
||||||
#define _WANT_FREEBSD11_DIRENT 1 |
|
||||||
#define _WANT_FREEBSD11_KEVENT 1 |
|
||||||
|
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <poll.h> |
|
||||||
#include <signal.h> |
|
||||||
#include <termios.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/capsicum.h> |
|
||||||
#include <sys/event.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/mount.h> |
|
||||||
#include <sys/param.h> |
|
||||||
#include <sys/ptrace.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/select.h> |
|
||||||
#include <sys/signal.h> |
|
||||||
#include <sys/socket.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/wait.h> |
|
||||||
#include <net/bpf.h> |
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <net/route.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
#include <netinet/tcp.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
// This structure is a duplicate of if_data on FreeBSD 8-STABLE.
|
|
||||||
// See /usr/include/net/if.h.
|
|
||||||
struct if_data8 { |
|
||||||
u_char ifi_type; |
|
||||||
u_char ifi_physical; |
|
||||||
u_char ifi_addrlen; |
|
||||||
u_char ifi_hdrlen; |
|
||||||
u_char ifi_link_state; |
|
||||||
u_char ifi_spare_char1; |
|
||||||
u_char ifi_spare_char2; |
|
||||||
u_char ifi_datalen; |
|
||||||
u_long ifi_mtu; |
|
||||||
u_long ifi_metric; |
|
||||||
u_long ifi_baudrate; |
|
||||||
u_long ifi_ipackets; |
|
||||||
u_long ifi_ierrors; |
|
||||||
u_long ifi_opackets; |
|
||||||
u_long ifi_oerrors; |
|
||||||
u_long ifi_collisions; |
|
||||||
u_long ifi_ibytes; |
|
||||||
u_long ifi_obytes; |
|
||||||
u_long ifi_imcasts; |
|
||||||
u_long ifi_omcasts; |
|
||||||
u_long ifi_iqdrops; |
|
||||||
u_long ifi_noproto; |
|
||||||
u_long ifi_hwassist; |
|
||||||
// FIXME: these are now unions, so maybe need to change definitions?
|
|
||||||
#undef ifi_epoch |
|
||||||
time_t ifi_epoch; |
|
||||||
#undef ifi_lastchange |
|
||||||
struct timeval ifi_lastchange; |
|
||||||
}; |
|
||||||
|
|
||||||
// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE.
|
|
||||||
// See /usr/include/net/if.h.
|
|
||||||
struct if_msghdr8 { |
|
||||||
u_short ifm_msglen; |
|
||||||
u_char ifm_version; |
|
||||||
u_char ifm_type; |
|
||||||
int ifm_addrs; |
|
||||||
int ifm_flags; |
|
||||||
u_short ifm_index; |
|
||||||
struct if_data8 ifm_data; |
|
||||||
}; |
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
const ( |
|
||||||
_statfsVersion = C.STATFS_VERSION |
|
||||||
_dirblksiz = C.DIRBLKSIZ |
|
||||||
) |
|
||||||
|
|
||||||
type Stat_t C.struct_stat |
|
||||||
|
|
||||||
type stat_freebsd11_t C.struct_freebsd11_stat |
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs |
|
||||||
|
|
||||||
type statfs_freebsd11_t C.struct_freebsd11_statfs |
|
||||||
|
|
||||||
type Flock_t C.struct_flock |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
type dirent_freebsd11 C.struct_freebsd11_dirent |
|
||||||
|
|
||||||
type Fsid C.struct_fsid |
|
||||||
|
|
||||||
// File system limits
|
|
||||||
|
|
||||||
const ( |
|
||||||
PathMax = C.PATH_MAX |
|
||||||
) |
|
||||||
|
|
||||||
// Advice to Fadvise
|
|
||||||
|
|
||||||
const ( |
|
||||||
FADV_NORMAL = C.POSIX_FADV_NORMAL |
|
||||||
FADV_RANDOM = C.POSIX_FADV_RANDOM |
|
||||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL |
|
||||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED |
|
||||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED |
|
||||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE |
|
||||||
) |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPMreqn C.struct_ip_mreqn |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPMreqn = C.sizeof_struct_ip_mreqn |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Ptrace requests
|
|
||||||
|
|
||||||
const ( |
|
||||||
PTRACE_ATTACH = C.PT_ATTACH |
|
||||||
PTRACE_CONT = C.PT_CONTINUE |
|
||||||
PTRACE_DETACH = C.PT_DETACH |
|
||||||
PTRACE_GETFPREGS = C.PT_GETFPREGS |
|
||||||
PTRACE_GETFSBASE = C.PT_GETFSBASE |
|
||||||
PTRACE_GETLWPLIST = C.PT_GETLWPLIST |
|
||||||
PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS |
|
||||||
PTRACE_GETREGS = C.PT_GETREGS |
|
||||||
PTRACE_GETXSTATE = C.PT_GETXSTATE |
|
||||||
PTRACE_IO = C.PT_IO |
|
||||||
PTRACE_KILL = C.PT_KILL |
|
||||||
PTRACE_LWPEVENTS = C.PT_LWP_EVENTS |
|
||||||
PTRACE_LWPINFO = C.PT_LWPINFO |
|
||||||
PTRACE_SETFPREGS = C.PT_SETFPREGS |
|
||||||
PTRACE_SETREGS = C.PT_SETREGS |
|
||||||
PTRACE_SINGLESTEP = C.PT_STEP |
|
||||||
PTRACE_TRACEME = C.PT_TRACE_ME |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
PIOD_READ_D = C.PIOD_READ_D |
|
||||||
PIOD_WRITE_D = C.PIOD_WRITE_D |
|
||||||
PIOD_READ_I = C.PIOD_READ_I |
|
||||||
PIOD_WRITE_I = C.PIOD_WRITE_I |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
PL_FLAG_BORN = C.PL_FLAG_BORN |
|
||||||
PL_FLAG_EXITED = C.PL_FLAG_EXITED |
|
||||||
PL_FLAG_SI = C.PL_FLAG_SI |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
TRAP_BRKPT = C.TRAP_BRKPT |
|
||||||
TRAP_TRACE = C.TRAP_TRACE |
|
||||||
) |
|
||||||
|
|
||||||
type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo |
|
||||||
|
|
||||||
type __Siginfo C.struct___siginfo |
|
||||||
|
|
||||||
type Sigset_t C.sigset_t |
|
||||||
|
|
||||||
type Reg C.struct_reg |
|
||||||
|
|
||||||
type FpReg C.struct_fpreg |
|
||||||
|
|
||||||
type PtraceIoDesc C.struct_ptrace_io_desc |
|
||||||
|
|
||||||
// Events (kqueue, kevent)
|
|
||||||
|
|
||||||
type Kevent_t C.struct_kevent_freebsd11 |
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
sizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr8 |
|
||||||
sizeofIfData = C.sizeof_struct_if_data |
|
||||||
SizeofIfData = C.sizeof_struct_if_data8 |
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr |
|
||||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr |
|
||||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr |
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr |
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics |
|
||||||
) |
|
||||||
|
|
||||||
type ifMsghdr C.struct_if_msghdr |
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr8 |
|
||||||
|
|
||||||
type ifData C.struct_if_data |
|
||||||
|
|
||||||
type IfData C.struct_if_data8 |
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr |
|
||||||
|
|
||||||
type IfmaMsghdr C.struct_ifma_msghdr |
|
||||||
|
|
||||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr |
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr |
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics |
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version |
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat |
|
||||||
SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf |
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program |
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn |
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr |
|
||||||
SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header |
|
||||||
) |
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version |
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat |
|
||||||
|
|
||||||
type BpfZbuf C.struct_bpf_zbuf |
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program |
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn |
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr |
|
||||||
|
|
||||||
type BpfZbufHeader C.struct_bpf_zbuf_header |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
// fchmodat-like syscalls.
|
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_REMOVEDIR = C.AT_REMOVEDIR |
|
||||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
) |
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLINIGNEOF = C.POLLINIGNEOF |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
||||||
|
|
||||||
// Capabilities
|
|
||||||
|
|
||||||
type CapRights C.struct_cap_rights |
|
||||||
|
|
||||||
// Uname
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
@ -1,290 +0,0 @@ |
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See README.md |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#define KERNEL |
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <poll.h> |
|
||||||
#include <signal.h> |
|
||||||
#include <termios.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/param.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/event.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/mount.h> |
|
||||||
#include <sys/ptrace.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/select.h> |
|
||||||
#include <sys/signal.h> |
|
||||||
#include <sys/socket.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/sysctl.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/uio.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/wait.h> |
|
||||||
#include <net/bpf.h> |
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <net/route.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
#include <netinet/tcp.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat |
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs |
|
||||||
|
|
||||||
type Flock_t C.struct_flock |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
type Fsid C.fsid_t |
|
||||||
|
|
||||||
// File system limits
|
|
||||||
|
|
||||||
const ( |
|
||||||
PathMax = C.PATH_MAX |
|
||||||
) |
|
||||||
|
|
||||||
// Advice to Fadvise
|
|
||||||
|
|
||||||
const ( |
|
||||||
FADV_NORMAL = C.POSIX_FADV_NORMAL |
|
||||||
FADV_RANDOM = C.POSIX_FADV_RANDOM |
|
||||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL |
|
||||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED |
|
||||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED |
|
||||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE |
|
||||||
) |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Ptrace requests
|
|
||||||
|
|
||||||
const ( |
|
||||||
PTRACE_TRACEME = C.PT_TRACE_ME |
|
||||||
PTRACE_CONT = C.PT_CONTINUE |
|
||||||
PTRACE_KILL = C.PT_KILL |
|
||||||
) |
|
||||||
|
|
||||||
// Events (kqueue, kevent)
|
|
||||||
|
|
||||||
type Kevent_t C.struct_kevent |
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
SizeofIfData = C.sizeof_struct_if_data |
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr |
|
||||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr |
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr |
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics |
|
||||||
) |
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr |
|
||||||
|
|
||||||
type IfData C.struct_if_data |
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr |
|
||||||
|
|
||||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr |
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr |
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics |
|
||||||
|
|
||||||
type Mclpool C.struct_mclpool |
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version |
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat |
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program |
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn |
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr |
|
||||||
) |
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version |
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat |
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program |
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn |
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr |
|
||||||
|
|
||||||
type BpfTimeval C.struct_bpf_timeval |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
type Ptmget C.struct_ptmget |
|
||||||
|
|
||||||
// fchmodat-like syscalls.
|
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
) |
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
||||||
|
|
||||||
// Sysctl
|
|
||||||
|
|
||||||
type Sysctlnode C.struct_sysctlnode |
|
||||||
|
|
||||||
// Uname
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
||||||
|
|
||||||
// Clockinfo
|
|
||||||
|
|
||||||
const SizeofClockinfo = C.sizeof_struct_clockinfo |
|
||||||
|
|
||||||
type Clockinfo C.struct_clockinfo |
|
@ -1,283 +0,0 @@ |
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See README.md |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#define KERNEL |
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <poll.h> |
|
||||||
#include <signal.h> |
|
||||||
#include <termios.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/param.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/event.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/mount.h> |
|
||||||
#include <sys/ptrace.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/select.h> |
|
||||||
#include <sys/signal.h> |
|
||||||
#include <sys/socket.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/uio.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/wait.h> |
|
||||||
#include <uvm/uvmexp.h> |
|
||||||
#include <net/bpf.h> |
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <net/route.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
#include <netinet/tcp.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat |
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs |
|
||||||
|
|
||||||
type Flock_t C.struct_flock |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
type Fsid C.fsid_t |
|
||||||
|
|
||||||
// File system limits
|
|
||||||
|
|
||||||
const ( |
|
||||||
PathMax = C.PATH_MAX |
|
||||||
) |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Ptrace requests
|
|
||||||
|
|
||||||
const ( |
|
||||||
PTRACE_TRACEME = C.PT_TRACE_ME |
|
||||||
PTRACE_CONT = C.PT_CONTINUE |
|
||||||
PTRACE_KILL = C.PT_KILL |
|
||||||
) |
|
||||||
|
|
||||||
// Events (kqueue, kevent)
|
|
||||||
|
|
||||||
type Kevent_t C.struct_kevent |
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
SizeofIfData = C.sizeof_struct_if_data |
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr |
|
||||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr |
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr |
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics |
|
||||||
) |
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr |
|
||||||
|
|
||||||
type IfData C.struct_if_data |
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr |
|
||||||
|
|
||||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr |
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr |
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics |
|
||||||
|
|
||||||
type Mclpool C.struct_mclpool |
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version |
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat |
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program |
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn |
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr |
|
||||||
) |
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version |
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat |
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program |
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn |
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr |
|
||||||
|
|
||||||
type BpfTimeval C.struct_bpf_timeval |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
// fchmodat-like syscalls.
|
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
) |
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
||||||
|
|
||||||
// Signal Sets
|
|
||||||
|
|
||||||
type Sigset_t C.sigset_t |
|
||||||
|
|
||||||
// Uname
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
||||||
|
|
||||||
// Uvmexp
|
|
||||||
|
|
||||||
const SizeofUvmexp = C.sizeof_struct_uvmexp |
|
||||||
|
|
||||||
type Uvmexp C.struct_uvmexp |
|
||||||
|
|
||||||
// Clockinfo
|
|
||||||
|
|
||||||
const SizeofClockinfo = C.sizeof_struct_clockinfo |
|
||||||
|
|
||||||
type Clockinfo C.struct_clockinfo |
|
@ -1,266 +0,0 @@ |
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/* |
|
||||||
Input to cgo -godefs. See README.md |
|
||||||
*/ |
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix |
|
||||||
|
|
||||||
/* |
|
||||||
#define KERNEL |
|
||||||
// These defines ensure that builds done on newer versions of Solaris are
|
|
||||||
// backwards-compatible with older versions of Solaris and
|
|
||||||
// OpenSolaris-based derivatives.
|
|
||||||
#define __USE_SUNOS_SOCKETS__ // msghdr
|
|
||||||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
|
||||||
#include <dirent.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <netdb.h> |
|
||||||
#include <limits.h> |
|
||||||
#include <poll.h> |
|
||||||
#include <signal.h> |
|
||||||
#include <termios.h> |
|
||||||
#include <termio.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <unistd.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
#include <sys/mount.h> |
|
||||||
#include <sys/param.h> |
|
||||||
#include <sys/resource.h> |
|
||||||
#include <sys/select.h> |
|
||||||
#include <sys/signal.h> |
|
||||||
#include <sys/socket.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
#include <sys/statvfs.h> |
|
||||||
#include <sys/time.h> |
|
||||||
#include <sys/times.h> |
|
||||||
#include <sys/types.h> |
|
||||||
#include <sys/utsname.h> |
|
||||||
#include <sys/un.h> |
|
||||||
#include <sys/wait.h> |
|
||||||
#include <net/bpf.h> |
|
||||||
#include <net/if.h> |
|
||||||
#include <net/if_dl.h> |
|
||||||
#include <net/route.h> |
|
||||||
#include <netinet/in.h> |
|
||||||
#include <netinet/icmp6.h> |
|
||||||
#include <netinet/tcp.h> |
|
||||||
#include <ustat.h> |
|
||||||
#include <utime.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
sizeofPtr = sizeof(void*), |
|
||||||
}; |
|
||||||
|
|
||||||
union sockaddr_all { |
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3; |
|
||||||
struct sockaddr_un s4; |
|
||||||
struct sockaddr_dl s5; |
|
||||||
}; |
|
||||||
|
|
||||||
struct sockaddr_any { |
|
||||||
struct sockaddr addr; |
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; |
|
||||||
}; |
|
||||||
|
|
||||||
*/ |
|
||||||
import "C" |
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofPtr = C.sizeofPtr |
|
||||||
SizeofShort = C.sizeof_short |
|
||||||
SizeofInt = C.sizeof_int |
|
||||||
SizeofLong = C.sizeof_long |
|
||||||
SizeofLongLong = C.sizeof_longlong |
|
||||||
PathMax = C.PATH_MAX |
|
||||||
MaxHostNameLen = C.MAXHOSTNAMELEN |
|
||||||
) |
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type ( |
|
||||||
_C_short C.short |
|
||||||
_C_int C.int |
|
||||||
_C_long C.long |
|
||||||
_C_long_long C.longlong |
|
||||||
) |
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec |
|
||||||
|
|
||||||
type Timeval C.struct_timeval |
|
||||||
|
|
||||||
type Timeval32 C.struct_timeval32 |
|
||||||
|
|
||||||
type Tms C.struct_tms |
|
||||||
|
|
||||||
type Utimbuf C.struct_utimbuf |
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage |
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit |
|
||||||
|
|
||||||
type _Gid_t C.gid_t |
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat |
|
||||||
|
|
||||||
type Flock_t C.struct_flock |
|
||||||
|
|
||||||
type Dirent C.struct_dirent |
|
||||||
|
|
||||||
// Filesystems
|
|
||||||
|
|
||||||
type _Fsblkcnt_t C.fsblkcnt_t |
|
||||||
|
|
||||||
type Statvfs_t C.struct_statvfs |
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in |
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6 |
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un |
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl |
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr |
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any |
|
||||||
|
|
||||||
type _Socklen C.socklen_t |
|
||||||
|
|
||||||
type Linger C.struct_linger |
|
||||||
|
|
||||||
type Iovec C.struct_iovec |
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq |
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq |
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr |
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr |
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo |
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo |
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter |
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in |
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 |
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any |
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un |
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl |
|
||||||
SizeofLinger = C.sizeof_struct_linger |
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq |
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq |
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr |
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr |
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo |
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo |
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter |
|
||||||
) |
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set |
|
||||||
|
|
||||||
// Misc
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname |
|
||||||
|
|
||||||
type Ustat_t C.struct_ustat |
|
||||||
|
|
||||||
const ( |
|
||||||
AT_FDCWD = C.AT_FDCWD |
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW |
|
||||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW |
|
||||||
AT_REMOVEDIR = C.AT_REMOVEDIR |
|
||||||
AT_EACCESS = C.AT_EACCESS |
|
||||||
) |
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr |
|
||||||
SizeofIfData = C.sizeof_struct_if_data |
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr |
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr |
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics |
|
||||||
) |
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr |
|
||||||
|
|
||||||
type IfData C.struct_if_data |
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr |
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr |
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics |
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const ( |
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version |
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat |
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program |
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn |
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr |
|
||||||
) |
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version |
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat |
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program |
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn |
|
||||||
|
|
||||||
type BpfTimeval C.struct_bpf_timeval |
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr |
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios |
|
||||||
|
|
||||||
type Termio C.struct_termio |
|
||||||
|
|
||||||
type Winsize C.struct_winsize |
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd |
|
||||||
|
|
||||||
const ( |
|
||||||
POLLERR = C.POLLERR |
|
||||||
POLLHUP = C.POLLHUP |
|
||||||
POLLIN = C.POLLIN |
|
||||||
POLLNVAL = C.POLLNVAL |
|
||||||
POLLOUT = C.POLLOUT |
|
||||||
POLLPRI = C.POLLPRI |
|
||||||
POLLRDBAND = C.POLLRDBAND |
|
||||||
POLLRDNORM = C.POLLRDNORM |
|
||||||
POLLWRBAND = C.POLLWRBAND |
|
||||||
POLLWRNORM = C.POLLWRNORM |
|
||||||
) |
|
@ -1,556 +0,0 @@ |
|||||||
// Copyright 2013 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"net/http" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
"unicode/utf8" |
|
||||||
|
|
||||||
"golang.org/x/text/encoding" |
|
||||||
"golang.org/x/text/internal/gen" |
|
||||||
) |
|
||||||
|
|
||||||
const ascii = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + |
|
||||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + |
|
||||||
` !"#$%&'()*+,-./0123456789:;<=>?` + |
|
||||||
`@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` + |
|
||||||
"`abcdefghijklmnopqrstuvwxyz{|}~\u007f" |
|
||||||
|
|
||||||
var encodings = []struct { |
|
||||||
name string |
|
||||||
mib string |
|
||||||
comment string |
|
||||||
varName string |
|
||||||
replacement byte |
|
||||||
mapping string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"IBM Code Page 037", |
|
||||||
"IBM037", |
|
||||||
"", |
|
||||||
"CodePage037", |
|
||||||
0x3f, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM037-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 437", |
|
||||||
"PC8CodePage437", |
|
||||||
"", |
|
||||||
"CodePage437", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM437-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 850", |
|
||||||
"PC850Multilingual", |
|
||||||
"", |
|
||||||
"CodePage850", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM850-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 852", |
|
||||||
"PCp852", |
|
||||||
"", |
|
||||||
"CodePage852", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM852-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 855", |
|
||||||
"IBM855", |
|
||||||
"", |
|
||||||
"CodePage855", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM855-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows Code Page 858", // PC latin1 with Euro
|
|
||||||
"IBM00858", |
|
||||||
"", |
|
||||||
"CodePage858", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-858-2000.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 860", |
|
||||||
"IBM860", |
|
||||||
"", |
|
||||||
"CodePage860", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM860-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 862", |
|
||||||
"PC862LatinHebrew", |
|
||||||
"", |
|
||||||
"CodePage862", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM862-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 863", |
|
||||||
"IBM863", |
|
||||||
"", |
|
||||||
"CodePage863", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM863-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 865", |
|
||||||
"IBM865", |
|
||||||
"", |
|
||||||
"CodePage865", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM865-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 866", |
|
||||||
"IBM866", |
|
||||||
"", |
|
||||||
"CodePage866", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-ibm866.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 1047", |
|
||||||
"IBM1047", |
|
||||||
"", |
|
||||||
"CodePage1047", |
|
||||||
0x3f, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM1047-2.1.2.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"IBM Code Page 1140", |
|
||||||
"IBM01140", |
|
||||||
"", |
|
||||||
"CodePage1140", |
|
||||||
0x3f, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/ibm-1140_P100-1997.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-1", |
|
||||||
"ISOLatin1", |
|
||||||
"", |
|
||||||
"ISO8859_1", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_1-1998.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-2", |
|
||||||
"ISOLatin2", |
|
||||||
"", |
|
||||||
"ISO8859_2", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-2.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-3", |
|
||||||
"ISOLatin3", |
|
||||||
"", |
|
||||||
"ISO8859_3", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-3.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-4", |
|
||||||
"ISOLatin4", |
|
||||||
"", |
|
||||||
"ISO8859_4", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-4.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-5", |
|
||||||
"ISOLatinCyrillic", |
|
||||||
"", |
|
||||||
"ISO8859_5", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-5.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-6", |
|
||||||
"ISOLatinArabic", |
|
||||||
"", |
|
||||||
"ISO8859_6,ISO8859_6E,ISO8859_6I", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-6.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-7", |
|
||||||
"ISOLatinGreek", |
|
||||||
"", |
|
||||||
"ISO8859_7", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-7.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-8", |
|
||||||
"ISOLatinHebrew", |
|
||||||
"", |
|
||||||
"ISO8859_8,ISO8859_8E,ISO8859_8I", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-8.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-9", |
|
||||||
"ISOLatin5", |
|
||||||
"", |
|
||||||
"ISO8859_9", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_9-1999.ucm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-10", |
|
||||||
"ISOLatin6", |
|
||||||
"", |
|
||||||
"ISO8859_10", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-10.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-13", |
|
||||||
"ISO885913", |
|
||||||
"", |
|
||||||
"ISO8859_13", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-13.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-14", |
|
||||||
"ISO885914", |
|
||||||
"", |
|
||||||
"ISO8859_14", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-14.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-15", |
|
||||||
"ISO885915", |
|
||||||
"", |
|
||||||
"ISO8859_15", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-15.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"ISO 8859-16", |
|
||||||
"ISO885916", |
|
||||||
"", |
|
||||||
"ISO8859_16", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-iso-8859-16.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"KOI8-R", |
|
||||||
"KOI8R", |
|
||||||
"", |
|
||||||
"KOI8R", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-koi8-r.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"KOI8-U", |
|
||||||
"KOI8U", |
|
||||||
"", |
|
||||||
"KOI8U", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-koi8-u.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Macintosh", |
|
||||||
"Macintosh", |
|
||||||
"", |
|
||||||
"Macintosh", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-macintosh.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Macintosh Cyrillic", |
|
||||||
"MacintoshCyrillic", |
|
||||||
"", |
|
||||||
"MacintoshCyrillic", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-x-mac-cyrillic.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 874", |
|
||||||
"Windows874", |
|
||||||
"", |
|
||||||
"Windows874", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-874.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1250", |
|
||||||
"Windows1250", |
|
||||||
"", |
|
||||||
"Windows1250", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1250.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1251", |
|
||||||
"Windows1251", |
|
||||||
"", |
|
||||||
"Windows1251", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1251.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1252", |
|
||||||
"Windows1252", |
|
||||||
"", |
|
||||||
"Windows1252", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1252.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1253", |
|
||||||
"Windows1253", |
|
||||||
"", |
|
||||||
"Windows1253", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1253.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1254", |
|
||||||
"Windows1254", |
|
||||||
"", |
|
||||||
"Windows1254", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1254.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1255", |
|
||||||
"Windows1255", |
|
||||||
"", |
|
||||||
"Windows1255", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1255.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1256", |
|
||||||
"Windows1256", |
|
||||||
"", |
|
||||||
"Windows1256", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1256.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1257", |
|
||||||
"Windows1257", |
|
||||||
"", |
|
||||||
"Windows1257", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1257.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"Windows 1258", |
|
||||||
"Windows1258", |
|
||||||
"", |
|
||||||
"Windows1258", |
|
||||||
encoding.ASCIISub, |
|
||||||
"http://encoding.spec.whatwg.org/index-windows-1258.txt", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"X-User-Defined", |
|
||||||
"XUserDefined", |
|
||||||
"It is defined at http://encoding.spec.whatwg.org/#x-user-defined", |
|
||||||
"XUserDefined", |
|
||||||
encoding.ASCIISub, |
|
||||||
ascii + |
|
||||||
"\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787" + |
|
||||||
"\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f" + |
|
||||||
"\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797" + |
|
||||||
"\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f" + |
|
||||||
"\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7" + |
|
||||||
"\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af" + |
|
||||||
"\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7" + |
|
||||||
"\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf" + |
|
||||||
"\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7" + |
|
||||||
"\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf" + |
|
||||||
"\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7" + |
|
||||||
"\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df" + |
|
||||||
"\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7" + |
|
||||||
"\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef" + |
|
||||||
"\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7" + |
|
||||||
"\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
func getWHATWG(url string) string { |
|
||||||
res, err := http.Get(url) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("%q: Get: %v", url, err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
mapping := make([]rune, 128) |
|
||||||
for i := range mapping { |
|
||||||
mapping[i] = '\ufffd' |
|
||||||
} |
|
||||||
|
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
x, y := 0, 0 |
|
||||||
if _, err := fmt.Sscanf(s, "%d\t0x%x", &x, &y); err != nil { |
|
||||||
log.Fatalf("could not parse %q", s) |
|
||||||
} |
|
||||||
if x < 0 || 128 <= x { |
|
||||||
log.Fatalf("code %d is out of range", x) |
|
||||||
} |
|
||||||
if 0x80 <= y && y < 0xa0 { |
|
||||||
// We diverge from the WHATWG spec by mapping control characters
|
|
||||||
// in the range [0x80, 0xa0) to U+FFFD.
|
|
||||||
continue |
|
||||||
} |
|
||||||
mapping[x] = rune(y) |
|
||||||
} |
|
||||||
return ascii + string(mapping) |
|
||||||
} |
|
||||||
|
|
||||||
func getUCM(url string) string { |
|
||||||
res, err := http.Get(url) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("%q: Get: %v", url, err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
mapping := make([]rune, 256) |
|
||||||
for i := range mapping { |
|
||||||
mapping[i] = '\ufffd' |
|
||||||
} |
|
||||||
|
|
||||||
charsFound := 0 |
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
var c byte |
|
||||||
var r rune |
|
||||||
if _, err := fmt.Sscanf(s, `<U%x> \x%x |0`, &r, &c); err != nil { |
|
||||||
continue |
|
||||||
} |
|
||||||
mapping[c] = r |
|
||||||
charsFound++ |
|
||||||
} |
|
||||||
|
|
||||||
if charsFound < 200 { |
|
||||||
log.Fatalf("%q: only %d characters found (wrong page format?)", url, charsFound) |
|
||||||
} |
|
||||||
|
|
||||||
return string(mapping) |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
mibs := map[string]bool{} |
|
||||||
all := []string{} |
|
||||||
|
|
||||||
w := gen.NewCodeWriter() |
|
||||||
defer w.WriteGoFile("tables.go", "charmap") |
|
||||||
|
|
||||||
printf := func(s string, a ...interface{}) { fmt.Fprintf(w, s, a...) } |
|
||||||
|
|
||||||
printf("import (\n") |
|
||||||
printf("\t\"golang.org/x/text/encoding\"\n") |
|
||||||
printf("\t\"golang.org/x/text/encoding/internal/identifier\"\n") |
|
||||||
printf(")\n\n") |
|
||||||
for _, e := range encodings { |
|
||||||
varNames := strings.Split(e.varName, ",") |
|
||||||
all = append(all, varNames...) |
|
||||||
varName := varNames[0] |
|
||||||
switch { |
|
||||||
case strings.HasPrefix(e.mapping, "http://encoding.spec.whatwg.org/"): |
|
||||||
e.mapping = getWHATWG(e.mapping) |
|
||||||
case strings.HasPrefix(e.mapping, "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/"): |
|
||||||
e.mapping = getUCM(e.mapping) |
|
||||||
} |
|
||||||
|
|
||||||
asciiSuperset, low := strings.HasPrefix(e.mapping, ascii), 0x00 |
|
||||||
if asciiSuperset { |
|
||||||
low = 0x80 |
|
||||||
} |
|
||||||
lvn := 1 |
|
||||||
if strings.HasPrefix(varName, "ISO") || strings.HasPrefix(varName, "KOI") { |
|
||||||
lvn = 3 |
|
||||||
} |
|
||||||
lowerVarName := strings.ToLower(varName[:lvn]) + varName[lvn:] |
|
||||||
printf("// %s is the %s encoding.\n", varName, e.name) |
|
||||||
if e.comment != "" { |
|
||||||
printf("//\n// %s\n", e.comment) |
|
||||||
} |
|
||||||
printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n", |
|
||||||
varName, lowerVarName, lowerVarName, e.name) |
|
||||||
if mibs[e.mib] { |
|
||||||
log.Fatalf("MIB type %q declared multiple times.", e.mib) |
|
||||||
} |
|
||||||
printf("mib: identifier.%s,\n", e.mib) |
|
||||||
printf("asciiSuperset: %t,\n", asciiSuperset) |
|
||||||
printf("low: 0x%02x,\n", low) |
|
||||||
printf("replacement: 0x%02x,\n", e.replacement) |
|
||||||
|
|
||||||
printf("decode: [256]utf8Enc{\n") |
|
||||||
i, backMapping := 0, map[rune]byte{} |
|
||||||
for _, c := range e.mapping { |
|
||||||
if _, ok := backMapping[c]; !ok && c != utf8.RuneError { |
|
||||||
backMapping[c] = byte(i) |
|
||||||
} |
|
||||||
var buf [8]byte |
|
||||||
n := utf8.EncodeRune(buf[:], c) |
|
||||||
if n > 3 { |
|
||||||
panic(fmt.Sprintf("rune %q (%U) is too long", c, c)) |
|
||||||
} |
|
||||||
printf("{%d,[3]byte{0x%02x,0x%02x,0x%02x}},", n, buf[0], buf[1], buf[2]) |
|
||||||
if i%2 == 1 { |
|
||||||
printf("\n") |
|
||||||
} |
|
||||||
i++ |
|
||||||
} |
|
||||||
printf("},\n") |
|
||||||
|
|
||||||
printf("encode: [256]uint32{\n") |
|
||||||
encode := make([]uint32, 0, 256) |
|
||||||
for c, i := range backMapping { |
|
||||||
encode = append(encode, uint32(i)<<24|uint32(c)) |
|
||||||
} |
|
||||||
sort.Sort(byRune(encode)) |
|
||||||
for len(encode) < cap(encode) { |
|
||||||
encode = append(encode, encode[len(encode)-1]) |
|
||||||
} |
|
||||||
for i, enc := range encode { |
|
||||||
printf("0x%08x,", enc) |
|
||||||
if i%8 == 7 { |
|
||||||
printf("\n") |
|
||||||
} |
|
||||||
} |
|
||||||
printf("},\n}\n") |
|
||||||
|
|
||||||
// Add an estimate of the size of a single Charmap{} struct value, which
|
|
||||||
// includes two 256 elem arrays of 4 bytes and some extra fields, which
|
|
||||||
// align to 3 uint64s on 64-bit architectures.
|
|
||||||
w.Size += 2*4*256 + 3*8 |
|
||||||
} |
|
||||||
// TODO: add proper line breaking.
|
|
||||||
printf("var listAll = []encoding.Encoding{\n%s,\n}\n\n", strings.Join(all, ",\n")) |
|
||||||
} |
|
||||||
|
|
||||||
type byRune []uint32 |
|
||||||
|
|
||||||
func (b byRune) Len() int { return len(b) } |
|
||||||
func (b byRune) Less(i, j int) bool { return b[i]&0xffffff < b[j]&0xffffff } |
|
||||||
func (b byRune) Swap(i, j int) { b[i], b[j] = b[j], b[i] } |
|
@ -1,173 +0,0 @@ |
|||||||
// 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"encoding/json" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"golang.org/x/text/internal/gen" |
|
||||||
) |
|
||||||
|
|
||||||
type group struct { |
|
||||||
Encodings []struct { |
|
||||||
Labels []string |
|
||||||
Name string |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
gen.Init() |
|
||||||
|
|
||||||
r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json") |
|
||||||
var groups []group |
|
||||||
if err := json.NewDecoder(r).Decode(&groups); err != nil { |
|
||||||
log.Fatalf("Error reading encodings.json: %v", err) |
|
||||||
} |
|
||||||
|
|
||||||
w := &bytes.Buffer{} |
|
||||||
fmt.Fprintln(w, "type htmlEncoding byte") |
|
||||||
fmt.Fprintln(w, "const (") |
|
||||||
for i, g := range groups { |
|
||||||
for _, e := range g.Encodings { |
|
||||||
key := strings.ToLower(e.Name) |
|
||||||
name := consts[key] |
|
||||||
if name == "" { |
|
||||||
log.Fatalf("No const defined for %s.", key) |
|
||||||
} |
|
||||||
if i == 0 { |
|
||||||
fmt.Fprintf(w, "%s htmlEncoding = iota\n", name) |
|
||||||
} else { |
|
||||||
fmt.Fprintf(w, "%s\n", name) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Fprintln(w, "numEncodings") |
|
||||||
fmt.Fprint(w, ")\n\n") |
|
||||||
|
|
||||||
fmt.Fprintln(w, "var canonical = [numEncodings]string{") |
|
||||||
for _, g := range groups { |
|
||||||
for _, e := range g.Encodings { |
|
||||||
fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name)) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Fprint(w, "}\n\n") |
|
||||||
|
|
||||||
fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{") |
|
||||||
for _, g := range groups { |
|
||||||
for _, e := range g.Encodings { |
|
||||||
for _, l := range e.Labels { |
|
||||||
key := strings.ToLower(e.Name) |
|
||||||
name := consts[key] |
|
||||||
fmt.Fprintf(w, "%q: %s,\n", l, name) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Fprint(w, "}\n\n") |
|
||||||
|
|
||||||
var tags []string |
|
||||||
fmt.Fprintln(w, "var localeMap = []htmlEncoding{") |
|
||||||
for _, loc := range locales { |
|
||||||
tags = append(tags, loc.tag) |
|
||||||
fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag) |
|
||||||
} |
|
||||||
fmt.Fprint(w, "}\n\n") |
|
||||||
|
|
||||||
fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " ")) |
|
||||||
|
|
||||||
gen.WriteGoFile("tables.go", "htmlindex", w.Bytes()) |
|
||||||
} |
|
||||||
|
|
||||||
// consts maps canonical encoding name to internal constant.
|
|
||||||
var consts = map[string]string{ |
|
||||||
"utf-8": "utf8", |
|
||||||
"ibm866": "ibm866", |
|
||||||
"iso-8859-2": "iso8859_2", |
|
||||||
"iso-8859-3": "iso8859_3", |
|
||||||
"iso-8859-4": "iso8859_4", |
|
||||||
"iso-8859-5": "iso8859_5", |
|
||||||
"iso-8859-6": "iso8859_6", |
|
||||||
"iso-8859-7": "iso8859_7", |
|
||||||
"iso-8859-8": "iso8859_8", |
|
||||||
"iso-8859-8-i": "iso8859_8I", |
|
||||||
"iso-8859-10": "iso8859_10", |
|
||||||
"iso-8859-13": "iso8859_13", |
|
||||||
"iso-8859-14": "iso8859_14", |
|
||||||
"iso-8859-15": "iso8859_15", |
|
||||||
"iso-8859-16": "iso8859_16", |
|
||||||
"koi8-r": "koi8r", |
|
||||||
"koi8-u": "koi8u", |
|
||||||
"macintosh": "macintosh", |
|
||||||
"windows-874": "windows874", |
|
||||||
"windows-1250": "windows1250", |
|
||||||
"windows-1251": "windows1251", |
|
||||||
"windows-1252": "windows1252", |
|
||||||
"windows-1253": "windows1253", |
|
||||||
"windows-1254": "windows1254", |
|
||||||
"windows-1255": "windows1255", |
|
||||||
"windows-1256": "windows1256", |
|
||||||
"windows-1257": "windows1257", |
|
||||||
"windows-1258": "windows1258", |
|
||||||
"x-mac-cyrillic": "macintoshCyrillic", |
|
||||||
"gbk": "gbk", |
|
||||||
"gb18030": "gb18030", |
|
||||||
// "hz-gb-2312": "hzgb2312", // Was removed from WhatWG
|
|
||||||
"big5": "big5", |
|
||||||
"euc-jp": "eucjp", |
|
||||||
"iso-2022-jp": "iso2022jp", |
|
||||||
"shift_jis": "shiftJIS", |
|
||||||
"euc-kr": "euckr", |
|
||||||
"replacement": "replacement", |
|
||||||
"utf-16be": "utf16be", |
|
||||||
"utf-16le": "utf16le", |
|
||||||
"x-user-defined": "xUserDefined", |
|
||||||
} |
|
||||||
|
|
||||||
// locales is taken from
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm.
|
|
||||||
var locales = []struct{ tag, name string }{ |
|
||||||
// The default value. Explicitly state latin to benefit from the exact
|
|
||||||
// script option, while still making 1252 the default encoding for languages
|
|
||||||
// written in Latin script.
|
|
||||||
{"und_Latn", "windows-1252"}, |
|
||||||
{"ar", "windows-1256"}, |
|
||||||
{"ba", "windows-1251"}, |
|
||||||
{"be", "windows-1251"}, |
|
||||||
{"bg", "windows-1251"}, |
|
||||||
{"cs", "windows-1250"}, |
|
||||||
{"el", "iso-8859-7"}, |
|
||||||
{"et", "windows-1257"}, |
|
||||||
{"fa", "windows-1256"}, |
|
||||||
{"he", "windows-1255"}, |
|
||||||
{"hr", "windows-1250"}, |
|
||||||
{"hu", "iso-8859-2"}, |
|
||||||
{"ja", "shift_jis"}, |
|
||||||
{"kk", "windows-1251"}, |
|
||||||
{"ko", "euc-kr"}, |
|
||||||
{"ku", "windows-1254"}, |
|
||||||
{"ky", "windows-1251"}, |
|
||||||
{"lt", "windows-1257"}, |
|
||||||
{"lv", "windows-1257"}, |
|
||||||
{"mk", "windows-1251"}, |
|
||||||
{"pl", "iso-8859-2"}, |
|
||||||
{"ru", "windows-1251"}, |
|
||||||
{"sah", "windows-1251"}, |
|
||||||
{"sk", "windows-1250"}, |
|
||||||
{"sl", "iso-8859-2"}, |
|
||||||
{"sr", "windows-1251"}, |
|
||||||
{"tg", "windows-1251"}, |
|
||||||
{"th", "windows-874"}, |
|
||||||
{"tr", "windows-1254"}, |
|
||||||
{"tt", "windows-1251"}, |
|
||||||
{"uk", "windows-1251"}, |
|
||||||
{"vi", "windows-1258"}, |
|
||||||
{"zh-hans", "gb18030"}, |
|
||||||
{"zh-hant", "big5"}, |
|
||||||
} |
|
@ -1,142 +0,0 @@ |
|||||||
// 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"encoding/xml" |
|
||||||
"fmt" |
|
||||||
"io" |
|
||||||
"log" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"golang.org/x/text/internal/gen" |
|
||||||
) |
|
||||||
|
|
||||||
type registry struct { |
|
||||||
XMLName xml.Name `xml:"registry"` |
|
||||||
Updated string `xml:"updated"` |
|
||||||
Registry []struct { |
|
||||||
ID string `xml:"id,attr"` |
|
||||||
Record []struct { |
|
||||||
Name string `xml:"name"` |
|
||||||
Xref []struct { |
|
||||||
Type string `xml:"type,attr"` |
|
||||||
Data string `xml:"data,attr"` |
|
||||||
} `xml:"xref"` |
|
||||||
Desc struct { |
|
||||||
Data string `xml:",innerxml"` |
|
||||||
// Any []struct {
|
|
||||||
// Data string `xml:",chardata"`
|
|
||||||
// } `xml:",any"`
|
|
||||||
// Data string `xml:",chardata"`
|
|
||||||
} `xml:"description,"` |
|
||||||
MIB string `xml:"value"` |
|
||||||
Alias []string `xml:"alias"` |
|
||||||
MIME string `xml:"preferred_alias"` |
|
||||||
} `xml:"record"` |
|
||||||
} `xml:"registry"` |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") |
|
||||||
reg := ®istry{} |
|
||||||
if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { |
|
||||||
log.Fatalf("Error decoding charset registry: %v", err) |
|
||||||
} |
|
||||||
if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { |
|
||||||
log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) |
|
||||||
} |
|
||||||
|
|
||||||
w := &bytes.Buffer{} |
|
||||||
fmt.Fprintf(w, "const (\n") |
|
||||||
for _, rec := range reg.Registry[0].Record { |
|
||||||
constName := "" |
|
||||||
for _, a := range rec.Alias { |
|
||||||
if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { |
|
||||||
// Some of the constant definitions have comments in them. Strip those.
|
|
||||||
constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) |
|
||||||
} |
|
||||||
} |
|
||||||
if constName == "" { |
|
||||||
switch rec.MIB { |
|
||||||
case "2085": |
|
||||||
constName = "HZGB2312" // Not listed as alias for some reason.
|
|
||||||
default: |
|
||||||
log.Fatalf("No cs alias defined for %s.", rec.MIB) |
|
||||||
} |
|
||||||
} |
|
||||||
if rec.MIME != "" { |
|
||||||
rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) |
|
||||||
} |
|
||||||
fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) |
|
||||||
if len(rec.Desc.Data) > 0 { |
|
||||||
fmt.Fprint(w, "// ") |
|
||||||
d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) |
|
||||||
inElem := true |
|
||||||
attr := "" |
|
||||||
for { |
|
||||||
t, err := d.Token() |
|
||||||
if err != nil { |
|
||||||
if err != io.EOF { |
|
||||||
log.Fatal(err) |
|
||||||
} |
|
||||||
break |
|
||||||
} |
|
||||||
switch x := t.(type) { |
|
||||||
case xml.CharData: |
|
||||||
attr = "" // Don't need attribute info.
|
|
||||||
a := bytes.Split([]byte(x), []byte("\n")) |
|
||||||
for i, b := range a { |
|
||||||
if b = bytes.TrimSpace(b); len(b) != 0 { |
|
||||||
if !inElem && i > 0 { |
|
||||||
fmt.Fprint(w, "\n// ") |
|
||||||
} |
|
||||||
inElem = false |
|
||||||
fmt.Fprintf(w, "%s ", string(b)) |
|
||||||
} |
|
||||||
} |
|
||||||
case xml.StartElement: |
|
||||||
if x.Name.Local == "xref" { |
|
||||||
inElem = true |
|
||||||
use := false |
|
||||||
for _, a := range x.Attr { |
|
||||||
if a.Name.Local == "type" { |
|
||||||
use = use || a.Value != "person" |
|
||||||
} |
|
||||||
if a.Name.Local == "data" && use { |
|
||||||
// Patch up URLs to use https. From some links, the
|
|
||||||
// https version is different from the http one.
|
|
||||||
s := a.Value |
|
||||||
s = strings.Replace(s, "http://", "https://", -1) |
|
||||||
s = strings.Replace(s, "/unicode/", "/", -1) |
|
||||||
attr = s + " " |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
case xml.EndElement: |
|
||||||
inElem = false |
|
||||||
fmt.Fprint(w, attr) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Fprint(w, "\n") |
|
||||||
} |
|
||||||
for _, x := range rec.Xref { |
|
||||||
switch x.Type { |
|
||||||
case "rfc": |
|
||||||
fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) |
|
||||||
case "uri": |
|
||||||
fmt.Fprintf(w, "// Reference: %s\n", x.Data) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) |
|
||||||
fmt.Fprintln(w) |
|
||||||
} |
|
||||||
fmt.Fprintln(w, ")") |
|
||||||
|
|
||||||
gen.WriteGoFile("mib.go", "identifier", w.Bytes()) |
|
||||||
} |
|
@ -1,161 +0,0 @@ |
|||||||
// Copyright 2013 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
// This program generates tables.go:
|
|
||||||
// go run maketables.go | gofmt > tables.go
|
|
||||||
|
|
||||||
// TODO: Emoji extensions?
|
|
||||||
// https://www.unicode.org/faq/emoji_dingbats.html
|
|
||||||
// https://www.unicode.org/Public/UNIDATA/EmojiSources.txt
|
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"net/http" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
type entry struct { |
|
||||||
jisCode, table int |
|
||||||
} |
|
||||||
|
|
||||||
func main() { |
|
||||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") |
|
||||||
fmt.Printf("// Package japanese provides Japanese encodings such as EUC-JP and Shift JIS.\n") |
|
||||||
fmt.Printf(`package japanese // import "golang.org/x/text/encoding/japanese"` + "\n\n") |
|
||||||
|
|
||||||
reverse := [65536]entry{} |
|
||||||
for i := range reverse { |
|
||||||
reverse[i].table = -1 |
|
||||||
} |
|
||||||
|
|
||||||
tables := []struct { |
|
||||||
url string |
|
||||||
name string |
|
||||||
}{ |
|
||||||
{"http://encoding.spec.whatwg.org/index-jis0208.txt", "0208"}, |
|
||||||
{"http://encoding.spec.whatwg.org/index-jis0212.txt", "0212"}, |
|
||||||
} |
|
||||||
for i, table := range tables { |
|
||||||
res, err := http.Get(table.url) |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("%q: Get: %v", table.url, err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
mapping := [65536]uint16{} |
|
||||||
|
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
x, y := 0, uint16(0) |
|
||||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { |
|
||||||
log.Fatalf("%q: could not parse %q", table.url, s) |
|
||||||
} |
|
||||||
if x < 0 || 120*94 <= x { |
|
||||||
log.Fatalf("%q: JIS code %d is out of range", table.url, x) |
|
||||||
} |
|
||||||
mapping[x] = y |
|
||||||
if reverse[y].table == -1 { |
|
||||||
reverse[y] = entry{jisCode: x, table: i} |
|
||||||
} |
|
||||||
} |
|
||||||
if err := scanner.Err(); err != nil { |
|
||||||
log.Fatalf("%q: scanner error: %v", table.url, err) |
|
||||||
} |
|
||||||
|
|
||||||
fmt.Printf("// jis%sDecode is the decoding table from JIS %s code to Unicode.\n// It is defined at %s\n", |
|
||||||
table.name, table.name, table.url) |
|
||||||
fmt.Printf("var jis%sDecode = [...]uint16{\n", table.name) |
|
||||||
for i, m := range mapping { |
|
||||||
if m != 0 { |
|
||||||
fmt.Printf("\t%d: 0x%04X,\n", i, m) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
} |
|
||||||
|
|
||||||
// Any run of at least separation continuous zero entries in the reverse map will
|
|
||||||
// be a separate encode table.
|
|
||||||
const separation = 1024 |
|
||||||
|
|
||||||
intervals := []interval(nil) |
|
||||||
low, high := -1, -1 |
|
||||||
for i, v := range reverse { |
|
||||||
if v.table == -1 { |
|
||||||
continue |
|
||||||
} |
|
||||||
if low < 0 { |
|
||||||
low = i |
|
||||||
} else if i-high >= separation { |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
low = i |
|
||||||
} |
|
||||||
high = i + 1 |
|
||||||
} |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
sort.Sort(byDecreasingLength(intervals)) |
|
||||||
|
|
||||||
fmt.Printf("const (\n") |
|
||||||
fmt.Printf("\tjis0208 = 1\n") |
|
||||||
fmt.Printf("\tjis0212 = 2\n") |
|
||||||
fmt.Printf("\tcodeMask = 0x7f\n") |
|
||||||
fmt.Printf("\tcodeShift = 7\n") |
|
||||||
fmt.Printf("\ttableShift = 14\n") |
|
||||||
fmt.Printf(")\n\n") |
|
||||||
|
|
||||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) |
|
||||||
fmt.Printf("// encodeX are the encoding tables from Unicode to JIS code,\n") |
|
||||||
fmt.Printf("// sorted by decreasing length.\n") |
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) |
|
||||||
} |
|
||||||
fmt.Printf("//\n") |
|
||||||
fmt.Printf("// The high two bits of the value record whether the JIS code comes from the\n") |
|
||||||
fmt.Printf("// JIS0208 table (high bits == 1) or the JIS0212 table (high bits == 2).\n") |
|
||||||
fmt.Printf("// The low 14 bits are two 7-bit unsigned integers j1 and j2 that form the\n") |
|
||||||
fmt.Printf("// JIS code (94*j1 + j2) within that table.\n") |
|
||||||
fmt.Printf("\n") |
|
||||||
|
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) |
|
||||||
fmt.Printf("var encode%d = [...]uint16{\n", i) |
|
||||||
for j := v.low; j < v.high; j++ { |
|
||||||
x := reverse[j] |
|
||||||
if x.table == -1 { |
|
||||||
continue |
|
||||||
} |
|
||||||
fmt.Printf("\t%d - %d: jis%s<<14 | 0x%02X<<7 | 0x%02X,\n", |
|
||||||
j, v.low, tables[x.table].name, x.jisCode/94, x.jisCode%94) |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// interval is a half-open interval [low, high).
|
|
||||||
type interval struct { |
|
||||||
low, high int |
|
||||||
} |
|
||||||
|
|
||||||
func (i interval) len() int { return i.high - i.low } |
|
||||||
|
|
||||||
// byDecreasingLength sorts intervals by decreasing length.
|
|
||||||
type byDecreasingLength []interval |
|
||||||
|
|
||||||
func (b byDecreasingLength) Len() int { return len(b) } |
|
||||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } |
|
||||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } |
|
@ -1,143 +0,0 @@ |
|||||||
// Copyright 2013 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
// This program generates tables.go:
|
|
||||||
// go run maketables.go | gofmt > tables.go
|
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"net/http" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
func main() { |
|
||||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") |
|
||||||
fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n") |
|
||||||
fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n") |
|
||||||
|
|
||||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt") |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("Get: %v", err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
mapping := [65536]uint16{} |
|
||||||
reverse := [65536]uint16{} |
|
||||||
|
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
x, y := uint16(0), uint16(0) |
|
||||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { |
|
||||||
log.Fatalf("could not parse %q", s) |
|
||||||
} |
|
||||||
if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x { |
|
||||||
log.Fatalf("EUC-KR code %d is out of range", x) |
|
||||||
} |
|
||||||
mapping[x] = y |
|
||||||
if reverse[y] == 0 { |
|
||||||
c0, c1 := uint16(0), uint16(0) |
|
||||||
if x < 178*(0xc7-0x81) { |
|
||||||
c0 = uint16(x/178) + 0x81 |
|
||||||
c1 = uint16(x % 178) |
|
||||||
switch { |
|
||||||
case c1 < 1*26: |
|
||||||
c1 += 0x41 |
|
||||||
case c1 < 2*26: |
|
||||||
c1 += 0x47 |
|
||||||
default: |
|
||||||
c1 += 0x4d |
|
||||||
} |
|
||||||
} else { |
|
||||||
x -= 178 * (0xc7 - 0x81) |
|
||||||
c0 = uint16(x/94) + 0xc7 |
|
||||||
c1 = uint16(x%94) + 0xa1 |
|
||||||
} |
|
||||||
reverse[y] = c0<<8 | c1 |
|
||||||
} |
|
||||||
} |
|
||||||
if err := scanner.Err(); err != nil { |
|
||||||
log.Fatalf("scanner error: %v", err) |
|
||||||
} |
|
||||||
|
|
||||||
fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n") |
|
||||||
fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n") |
|
||||||
fmt.Printf("var decode = [...]uint16{\n") |
|
||||||
for i, v := range mapping { |
|
||||||
if v != 0 { |
|
||||||
fmt.Printf("\t%d: 0x%04X,\n", i, v) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
|
|
||||||
// Any run of at least separation continuous zero entries in the reverse map will
|
|
||||||
// be a separate encode table.
|
|
||||||
const separation = 1024 |
|
||||||
|
|
||||||
intervals := []interval(nil) |
|
||||||
low, high := -1, -1 |
|
||||||
for i, v := range reverse { |
|
||||||
if v == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
if low < 0 { |
|
||||||
low = i |
|
||||||
} else if i-high >= separation { |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
low = i |
|
||||||
} |
|
||||||
high = i + 1 |
|
||||||
} |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
sort.Sort(byDecreasingLength(intervals)) |
|
||||||
|
|
||||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) |
|
||||||
fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n") |
|
||||||
fmt.Printf("// sorted by decreasing length.\n") |
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) |
|
||||||
} |
|
||||||
fmt.Printf("\n") |
|
||||||
|
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) |
|
||||||
fmt.Printf("var encode%d = [...]uint16{\n", i) |
|
||||||
for j := v.low; j < v.high; j++ { |
|
||||||
x := reverse[j] |
|
||||||
if x == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// interval is a half-open interval [low, high).
|
|
||||||
type interval struct { |
|
||||||
low, high int |
|
||||||
} |
|
||||||
|
|
||||||
func (i interval) len() int { return i.high - i.low } |
|
||||||
|
|
||||||
// byDecreasingLength sorts intervals by decreasing length.
|
|
||||||
type byDecreasingLength []interval |
|
||||||
|
|
||||||
func (b byDecreasingLength) Len() int { return len(b) } |
|
||||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } |
|
||||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } |
|
@ -1,161 +0,0 @@ |
|||||||
// Copyright 2013 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
// This program generates tables.go:
|
|
||||||
// go run maketables.go | gofmt > tables.go
|
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"net/http" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
func main() { |
|
||||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") |
|
||||||
fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n") |
|
||||||
fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n") |
|
||||||
|
|
||||||
printGB18030() |
|
||||||
printGBK() |
|
||||||
} |
|
||||||
|
|
||||||
func printGB18030() { |
|
||||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt") |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("Get: %v", err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n") |
|
||||||
fmt.Printf("var gb18030 = [...][2]uint16{\n") |
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
x, y := uint32(0), uint32(0) |
|
||||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { |
|
||||||
log.Fatalf("could not parse %q", s) |
|
||||||
} |
|
||||||
if x < 0x10000 && y < 0x10000 { |
|
||||||
fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
} |
|
||||||
|
|
||||||
func printGBK() { |
|
||||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt") |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("Get: %v", err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
mapping := [65536]uint16{} |
|
||||||
reverse := [65536]uint16{} |
|
||||||
|
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
x, y := uint16(0), uint16(0) |
|
||||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { |
|
||||||
log.Fatalf("could not parse %q", s) |
|
||||||
} |
|
||||||
if x < 0 || 126*190 <= x { |
|
||||||
log.Fatalf("GBK code %d is out of range", x) |
|
||||||
} |
|
||||||
mapping[x] = y |
|
||||||
if reverse[y] == 0 { |
|
||||||
c0, c1 := x/190, x%190 |
|
||||||
if c1 >= 0x3f { |
|
||||||
c1++ |
|
||||||
} |
|
||||||
reverse[y] = (0x81+c0)<<8 | (0x40 + c1) |
|
||||||
} |
|
||||||
} |
|
||||||
if err := scanner.Err(); err != nil { |
|
||||||
log.Fatalf("scanner error: %v", err) |
|
||||||
} |
|
||||||
|
|
||||||
fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n") |
|
||||||
fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n") |
|
||||||
fmt.Printf("var decode = [...]uint16{\n") |
|
||||||
for i, v := range mapping { |
|
||||||
if v != 0 { |
|
||||||
fmt.Printf("\t%d: 0x%04X,\n", i, v) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
|
|
||||||
// Any run of at least separation continuous zero entries in the reverse map will
|
|
||||||
// be a separate encode table.
|
|
||||||
const separation = 1024 |
|
||||||
|
|
||||||
intervals := []interval(nil) |
|
||||||
low, high := -1, -1 |
|
||||||
for i, v := range reverse { |
|
||||||
if v == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
if low < 0 { |
|
||||||
low = i |
|
||||||
} else if i-high >= separation { |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
low = i |
|
||||||
} |
|
||||||
high = i + 1 |
|
||||||
} |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
sort.Sort(byDecreasingLength(intervals)) |
|
||||||
|
|
||||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) |
|
||||||
fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n") |
|
||||||
fmt.Printf("// sorted by decreasing length.\n") |
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) |
|
||||||
} |
|
||||||
fmt.Printf("\n") |
|
||||||
|
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) |
|
||||||
fmt.Printf("var encode%d = [...]uint16{\n", i) |
|
||||||
for j := v.low; j < v.high; j++ { |
|
||||||
x := reverse[j] |
|
||||||
if x == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// interval is a half-open interval [low, high).
|
|
||||||
type interval struct { |
|
||||||
low, high int |
|
||||||
} |
|
||||||
|
|
||||||
func (i interval) len() int { return i.high - i.low } |
|
||||||
|
|
||||||
// byDecreasingLength sorts intervals by decreasing length.
|
|
||||||
type byDecreasingLength []interval |
|
||||||
|
|
||||||
func (b byDecreasingLength) Len() int { return len(b) } |
|
||||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } |
|
||||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } |
|
@ -1,140 +0,0 @@ |
|||||||
// Copyright 2013 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 ignore
|
|
||||||
|
|
||||||
package main |
|
||||||
|
|
||||||
// This program generates tables.go:
|
|
||||||
// go run maketables.go | gofmt > tables.go
|
|
||||||
|
|
||||||
import ( |
|
||||||
"bufio" |
|
||||||
"fmt" |
|
||||||
"log" |
|
||||||
"net/http" |
|
||||||
"sort" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
func main() { |
|
||||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") |
|
||||||
fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n") |
|
||||||
fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n") |
|
||||||
|
|
||||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt") |
|
||||||
if err != nil { |
|
||||||
log.Fatalf("Get: %v", err) |
|
||||||
} |
|
||||||
defer res.Body.Close() |
|
||||||
|
|
||||||
mapping := [65536]uint32{} |
|
||||||
reverse := [65536 * 4]uint16{} |
|
||||||
|
|
||||||
scanner := bufio.NewScanner(res.Body) |
|
||||||
for scanner.Scan() { |
|
||||||
s := strings.TrimSpace(scanner.Text()) |
|
||||||
if s == "" || s[0] == '#' { |
|
||||||
continue |
|
||||||
} |
|
||||||
x, y := uint16(0), uint32(0) |
|
||||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { |
|
||||||
log.Fatalf("could not parse %q", s) |
|
||||||
} |
|
||||||
if x < 0 || 126*157 <= x { |
|
||||||
log.Fatalf("Big5 code %d is out of range", x) |
|
||||||
} |
|
||||||
mapping[x] = y |
|
||||||
|
|
||||||
// The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that
|
|
||||||
// "The index pointer for code point in index is the first pointer
|
|
||||||
// corresponding to code point in index", which would normally mean
|
|
||||||
// that the code below should be guarded by "if reverse[y] == 0", but
|
|
||||||
// last instead of first seems to match the behavior of
|
|
||||||
// "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in
|
|
||||||
// http://encoding.spec.whatwg.org/index-big5.txt, as index 2148
|
|
||||||
// (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc")
|
|
||||||
// and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc".
|
|
||||||
c0, c1 := x/157, x%157 |
|
||||||
if c1 < 0x3f { |
|
||||||
c1 += 0x40 |
|
||||||
} else { |
|
||||||
c1 += 0x62 |
|
||||||
} |
|
||||||
reverse[y] = (0x81+c0)<<8 | c1 |
|
||||||
} |
|
||||||
if err := scanner.Err(); err != nil { |
|
||||||
log.Fatalf("scanner error: %v", err) |
|
||||||
} |
|
||||||
|
|
||||||
fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n") |
|
||||||
fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n") |
|
||||||
fmt.Printf("var decode = [...]uint32{\n") |
|
||||||
for i, v := range mapping { |
|
||||||
if v != 0 { |
|
||||||
fmt.Printf("\t%d: 0x%08X,\n", i, v) |
|
||||||
} |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
|
|
||||||
// Any run of at least separation continuous zero entries in the reverse map will
|
|
||||||
// be a separate encode table.
|
|
||||||
const separation = 1024 |
|
||||||
|
|
||||||
intervals := []interval(nil) |
|
||||||
low, high := -1, -1 |
|
||||||
for i, v := range reverse { |
|
||||||
if v == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
if low < 0 { |
|
||||||
low = i |
|
||||||
} else if i-high >= separation { |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
low = i |
|
||||||
} |
|
||||||
high = i + 1 |
|
||||||
} |
|
||||||
if high >= 0 { |
|
||||||
intervals = append(intervals, interval{low, high}) |
|
||||||
} |
|
||||||
sort.Sort(byDecreasingLength(intervals)) |
|
||||||
|
|
||||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) |
|
||||||
fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n") |
|
||||||
fmt.Printf("// sorted by decreasing length.\n") |
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high) |
|
||||||
} |
|
||||||
fmt.Printf("\n") |
|
||||||
|
|
||||||
for i, v := range intervals { |
|
||||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) |
|
||||||
fmt.Printf("var encode%d = [...]uint16{\n", i) |
|
||||||
for j := v.low; j < v.high; j++ { |
|
||||||
x := reverse[j] |
|
||||||
if x == 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) |
|
||||||
} |
|
||||||
fmt.Printf("}\n\n") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// interval is a half-open interval [low, high).
|
|
||||||
type interval struct { |
|
||||||
low, high int |
|
||||||
} |
|
||||||
|
|
||||||
func (i interval) len() int { return i.high - i.low } |
|
||||||
|
|
||||||
// byDecreasingLength sorts intervals by decreasing length.
|
|
||||||
type byDecreasingLength []interval |
|
||||||
|
|
||||||
func (b byDecreasingLength) Len() int { return len(b) } |
|
||||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } |
|
||||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue