Add format functions
Add functions to go templates such as truncating a field. Also add the table keyword, which, if placed at the beginning of a format string, adds headers to the output Signed-off-by: Ryan Cole <rcyoalne@gmail.com>
This commit is contained in:
parent
6ca462a3b6
commit
08c3d241a4
10 changed files with 298 additions and 1046 deletions
|
@ -1,8 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
is "github.com/containers/image/storage"
|
is "github.com/containers/image/storage"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
|
"github.com/fatih/camelcase"
|
||||||
"github.com/kubernetes-incubator/cri-o/libkpod"
|
"github.com/kubernetes-incubator/cri-o/libkpod"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
@ -53,3 +56,8 @@ func getConfig(c *cli.Context) (*libkpod.Config, error) {
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func splitCamelCase(src string) string {
|
||||||
|
entries := camelcase.Split(src)
|
||||||
|
return strings.Join(entries, " ")
|
||||||
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@ package formats
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer interface for outputs
|
// Writer interface for outputs
|
||||||
|
@ -22,6 +24,7 @@ type JSONstruct struct {
|
||||||
type StdoutTemplate struct {
|
type StdoutTemplate struct {
|
||||||
Output []interface{}
|
Output []interface{}
|
||||||
Template string
|
Template string
|
||||||
|
Fields map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Out method for JSON
|
// Out method for JSON
|
||||||
|
@ -36,14 +39,23 @@ func (j JSONstruct) Out() error {
|
||||||
|
|
||||||
// Out method for Go templates
|
// Out method for Go templates
|
||||||
func (t StdoutTemplate) Out() error {
|
func (t StdoutTemplate) Out() error {
|
||||||
|
if strings.HasPrefix(t.Template, "table") {
|
||||||
tmpl, err := template.New("image").Parse(t.Template)
|
t.Template = strings.TrimSpace(t.Template[5:])
|
||||||
|
headerTmpl, err := template.New("header").Funcs(headerFunctions).Parse(t.Template)
|
||||||
|
if err != nil {
|
||||||
|
errors.Wrapf(err, "Template parsing error")
|
||||||
|
}
|
||||||
|
err = headerTmpl.Execute(os.Stdout, t.Fields)
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("image").Funcs(basicFunctions).Parse(t.Template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "Template parsing error")
|
return errors.Wrapf(err, "Template parsing error")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, img := range t.Output {
|
for _, img := range t.Output {
|
||||||
err = tmpl.Execute(os.Stdout, img)
|
basicTmpl := tmpl.Funcs(basicFunctions)
|
||||||
|
err = basicTmpl.Execute(os.Stdout, img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
78
cmd/kpod/formats/templates.go
Normal file
78
cmd/kpod/formats/templates.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package formats
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// basicFunctions are the set of initial
|
||||||
|
// functions provided to every template.
|
||||||
|
var basicFunctions = template.FuncMap{
|
||||||
|
"json": func(v interface{}) string {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
enc := json.NewEncoder(buf)
|
||||||
|
enc.SetEscapeHTML(false)
|
||||||
|
enc.Encode(v)
|
||||||
|
// Remove the trailing new line added by the encoder
|
||||||
|
return strings.TrimSpace(buf.String())
|
||||||
|
},
|
||||||
|
"split": strings.Split,
|
||||||
|
"join": strings.Join,
|
||||||
|
"title": strings.Title,
|
||||||
|
"lower": strings.ToLower,
|
||||||
|
"upper": strings.ToUpper,
|
||||||
|
"pad": padWithSpace,
|
||||||
|
"truncate": truncateWithLength,
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderFunctions are used to created headers of a table.
|
||||||
|
// This is a replacement of basicFunctions for header generation
|
||||||
|
// because we want the header to remain intact.
|
||||||
|
// Some functions like `split` are irrevelant so not added.
|
||||||
|
var headerFunctions = template.FuncMap{
|
||||||
|
"json": func(v string) string {
|
||||||
|
return v
|
||||||
|
},
|
||||||
|
"title": func(v string) string {
|
||||||
|
return v
|
||||||
|
},
|
||||||
|
"lower": func(v string) string {
|
||||||
|
return v
|
||||||
|
},
|
||||||
|
"upper": func(v string) string {
|
||||||
|
return v
|
||||||
|
},
|
||||||
|
"truncate": func(v string, l int) string {
|
||||||
|
return v
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse creates a new anonymous template with the basic functions
|
||||||
|
// and parses the given format.
|
||||||
|
func Parse(format string) (*template.Template, error) {
|
||||||
|
return NewParse("", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewParse creates a new tagged template with the basic functions
|
||||||
|
// and parses the given format.
|
||||||
|
func NewParse(tag, format string) (*template.Template, error) {
|
||||||
|
return template.New(tag).Funcs(basicFunctions).Parse(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
// padWithSpace adds whitespace to the input if the input is non-empty
|
||||||
|
func padWithSpace(source string, prefix, suffix int) string {
|
||||||
|
if source == "" {
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
return strings.Repeat(" ", prefix) + source + strings.Repeat(" ", suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// truncateWithLength truncates the source string up to the length provided by the input
|
||||||
|
func truncateWithLength(source string, length int) string {
|
||||||
|
if len(source) < length {
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
return source[:length]
|
||||||
|
}
|
|
@ -2,6 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
"github.com/kubernetes-incubator/cri-o/cmd/kpod/formats"
|
"github.com/kubernetes-incubator/cri-o/cmd/kpod/formats"
|
||||||
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
|
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
|
||||||
|
@ -10,14 +13,6 @@ import (
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
type imageOutputParams struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"names"`
|
|
||||||
Digest digest.Digest `json:"digest"`
|
|
||||||
CreatedAt string `json:"created"`
|
|
||||||
Size string `json:"size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
imagesFlags = []cli.Flag{
|
imagesFlags = []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
|
@ -201,9 +196,7 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests
|
||||||
case "json":
|
case "json":
|
||||||
out = formats.JSONstruct{Output: toGeneric(imageOutput)}
|
out = formats.JSONstruct{Output: toGeneric(imageOutput)}
|
||||||
default:
|
default:
|
||||||
// Assuming Go-template
|
out = formats.StdoutTemplate{Output: toGeneric(imageOutput), Template: outputFormat, Fields: imageOutput[0].headerMap()}
|
||||||
out = formats.StdoutTemplate{Output: toGeneric(imageOutput), Template: outputFormat}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
out = stdoutstruct{output: imageOutput, digests: digests, truncate: truncate, quiet: quiet, noheading: noheading}
|
out = stdoutstruct{output: imageOutput, digests: digests, truncate: truncate, quiet: quiet, noheading: noheading}
|
||||||
|
@ -213,3 +206,26 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type imageOutputParams struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"names"`
|
||||||
|
Digest digest.Digest `json:"digest"`
|
||||||
|
CreatedAt string `json:"created"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imageOutputParams) headerMap() map[string]string {
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(i))
|
||||||
|
values := make(map[string]string)
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
key := v.Type().Field(i).Name
|
||||||
|
value := key
|
||||||
|
if value == "ID" || value == "Name" {
|
||||||
|
value = "Image" + value
|
||||||
|
}
|
||||||
|
values[key] = fmt.Sprintf("%s ", strings.ToUpper(splitCamelCase(value)))
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
|
@ -80,3 +80,4 @@ github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
github.com/hpcloud/tail v1.0.0
|
github.com/hpcloud/tail v1.0.0
|
||||||
gopkg.in/fsnotify.v1 v1.4.2
|
gopkg.in/fsnotify.v1 v1.4.2
|
||||||
gopkg.in/tomb.v1 v1
|
gopkg.in/tomb.v1 v1
|
||||||
|
github.com/fatih/camelcase f6a740d52f961c60348ebb109adde9f4635d7540
|
||||||
|
|
934
vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go
generated
vendored
934
vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go
generated
vendored
|
@ -1,934 +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
|
|
||||||
|
|
||||||
/*
|
|
||||||
mksyscall_windows generates windows system call bodies
|
|
||||||
|
|
||||||
It parses all files specified on command line containing function
|
|
||||||
prototypes (like syscall_windows.go) and prints system call bodies
|
|
||||||
to standard output.
|
|
||||||
|
|
||||||
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 from it's winapi dll name,
|
|
||||||
the winapi name could be specified at the end, after "=" sign, like
|
|
||||||
//sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA
|
|
||||||
|
|
||||||
* Each function that returns err needs to supply a condition, that
|
|
||||||
return value of winapi will be tested against to detect failure.
|
|
||||||
This would set err to windows "last-error", otherwise it will be nil.
|
|
||||||
The value can be provided at end of //sys declaration, like
|
|
||||||
//sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA
|
|
||||||
and is [failretval==0] by default.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
mksyscall_windows [flags] [path ...]
|
|
||||||
|
|
||||||
The flags are:
|
|
||||||
-output
|
|
||||||
Specify output file name (outputs to console if blank).
|
|
||||||
-trace
|
|
||||||
Generate print statement after every syscall.
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
|
||||||
printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
|
|
||||||
systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory")
|
|
||||||
)
|
|
||||||
|
|
||||||
func trim(s string) string {
|
|
||||||
return strings.Trim(s, " \t")
|
|
||||||
}
|
|
||||||
|
|
||||||
var packageName string
|
|
||||||
|
|
||||||
func packagename() string {
|
|
||||||
return packageName
|
|
||||||
}
|
|
||||||
|
|
||||||
func syscalldot() string {
|
|
||||||
if packageName == "syscall" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return "syscall."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
fn *Fn
|
|
||||||
tmpVarIdx int
|
|
||||||
}
|
|
||||||
|
|
||||||
// tmpVar returns temp variable name that will be used to represent p during syscall.
|
|
||||||
func (p *Param) tmpVar() string {
|
|
||||||
if p.tmpVarIdx < 0 {
|
|
||||||
p.tmpVarIdx = p.fn.curTmpVarIdx
|
|
||||||
p.fn.curTmpVarIdx++
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("_p%d", p.tmpVarIdx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolTmpVarCode returns source code for bool temp variable.
|
|
||||||
func (p *Param) BoolTmpVarCode() string {
|
|
||||||
const code = `var %s uint32
|
|
||||||
if %s {
|
|
||||||
%s = 1
|
|
||||||
} else {
|
|
||||||
%s = 0
|
|
||||||
}`
|
|
||||||
tmp := p.tmpVar()
|
|
||||||
return fmt.Sprintf(code, tmp, p.Name, tmp, tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SliceTmpVarCode returns source code for slice temp variable.
|
|
||||||
func (p *Param) SliceTmpVarCode() string {
|
|
||||||
const code = `var %s *%s
|
|
||||||
if len(%s) > 0 {
|
|
||||||
%s = &%s[0]
|
|
||||||
}`
|
|
||||||
tmp := p.tmpVar()
|
|
||||||
return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringTmpVarCode returns source code for string temp variable.
|
|
||||||
func (p *Param) StringTmpVarCode() string {
|
|
||||||
errvar := p.fn.Rets.ErrorVarName()
|
|
||||||
if errvar == "" {
|
|
||||||
errvar = "_"
|
|
||||||
}
|
|
||||||
tmp := p.tmpVar()
|
|
||||||
const code = `var %s %s
|
|
||||||
%s, %s = %s(%s)`
|
|
||||||
s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name)
|
|
||||||
if errvar == "-" {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
const morecode = `
|
|
||||||
if %s != nil {
|
|
||||||
return
|
|
||||||
}`
|
|
||||||
return s + fmt.Sprintf(morecode, errvar)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TmpVarCode returns source code for temp variable.
|
|
||||||
func (p *Param) TmpVarCode() string {
|
|
||||||
switch {
|
|
||||||
case p.Type == "bool":
|
|
||||||
return p.BoolTmpVarCode()
|
|
||||||
case strings.HasPrefix(p.Type, "[]"):
|
|
||||||
return p.SliceTmpVarCode()
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TmpVarHelperCode returns source code for helper's temp variable.
|
|
||||||
func (p *Param) TmpVarHelperCode() string {
|
|
||||||
if p.Type != "string" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return p.StringTmpVarCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyscallArgList returns source code fragments representing p parameter
|
|
||||||
// in syscall. Slices are translated into 2 syscall parameters: pointer to
|
|
||||||
// the first element and length.
|
|
||||||
func (p *Param) SyscallArgList() []string {
|
|
||||||
t := p.HelperType()
|
|
||||||
var s string
|
|
||||||
switch {
|
|
||||||
case t[0] == '*':
|
|
||||||
s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
|
|
||||||
case t == "bool":
|
|
||||||
s = p.tmpVar()
|
|
||||||
case strings.HasPrefix(t, "[]"):
|
|
||||||
return []string{
|
|
||||||
fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
|
|
||||||
fmt.Sprintf("uintptr(len(%s))", p.Name),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
s = p.Name
|
|
||||||
}
|
|
||||||
return []string{fmt.Sprintf("uintptr(%s)", s)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsError determines if p parameter is used to return error.
|
|
||||||
func (p *Param) IsError() bool {
|
|
||||||
return p.Name == "err" && p.Type == "error"
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperType returns type of parameter p used in helper function.
|
|
||||||
func (p *Param) HelperType() string {
|
|
||||||
if p.Type == "string" {
|
|
||||||
return p.fn.StrconvType()
|
|
||||||
}
|
|
||||||
return p.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// join concatenates parameters ps into a string with sep separator.
|
|
||||||
// Each parameter is converted into string by applying fn to it
|
|
||||||
// before conversion.
|
|
||||||
func join(ps []*Param, fn func(*Param) string, sep string) string {
|
|
||||||
if len(ps) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
a := make([]string, 0)
|
|
||||||
for _, p := range ps {
|
|
||||||
a = append(a, fn(p))
|
|
||||||
}
|
|
||||||
return strings.Join(a, sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rets describes function return parameters.
|
|
||||||
type Rets struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
ReturnsError bool
|
|
||||||
FailCond string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorVarName returns error variable name for r.
|
|
||||||
func (r *Rets) ErrorVarName() string {
|
|
||||||
if r.ReturnsError {
|
|
||||||
return "err"
|
|
||||||
}
|
|
||||||
if r.Type == "error" {
|
|
||||||
return r.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToParams converts r into slice of *Param.
|
|
||||||
func (r *Rets) ToParams() []*Param {
|
|
||||||
ps := make([]*Param, 0)
|
|
||||||
if len(r.Name) > 0 {
|
|
||||||
ps = append(ps, &Param{Name: r.Name, Type: r.Type})
|
|
||||||
}
|
|
||||||
if r.ReturnsError {
|
|
||||||
ps = append(ps, &Param{Name: "err", Type: "error"})
|
|
||||||
}
|
|
||||||
return ps
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns source code of syscall return parameters.
|
|
||||||
func (r *Rets) List() string {
|
|
||||||
s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
||||||
if len(s) > 0 {
|
|
||||||
s = "(" + s + ")"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrintList returns source code of trace printing part correspondent
|
|
||||||
// to syscall return values.
|
|
||||||
func (r *Rets) PrintList() string {
|
|
||||||
return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetReturnValuesCode returns source code that accepts syscall return values.
|
|
||||||
func (r *Rets) SetReturnValuesCode() string {
|
|
||||||
if r.Name == "" && !r.ReturnsError {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
retvar := "r0"
|
|
||||||
if r.Name == "" {
|
|
||||||
retvar = "r1"
|
|
||||||
}
|
|
||||||
errvar := "_"
|
|
||||||
if r.ReturnsError {
|
|
||||||
errvar = "e1"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s, _, %s := ", retvar, errvar)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rets) useLongHandleErrorCode(retvar string) string {
|
|
||||||
const code = `if %s {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = %sEINVAL
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
cond := retvar + " == 0"
|
|
||||||
if r.FailCond != "" {
|
|
||||||
cond = strings.Replace(r.FailCond, "failretval", retvar, 1)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(code, cond, syscalldot())
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetErrorCode returns source code that sets return parameters.
|
|
||||||
func (r *Rets) SetErrorCode() string {
|
|
||||||
const code = `if r0 != 0 {
|
|
||||||
%s = %sErrno(r0)
|
|
||||||
}`
|
|
||||||
const hrCode = `if int32(r0) < 0 {
|
|
||||||
%s = %sErrno(win32FromHresult(r0))
|
|
||||||
}`
|
|
||||||
if r.Name == "" && !r.ReturnsError {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if r.Name == "" {
|
|
||||||
return r.useLongHandleErrorCode("r1")
|
|
||||||
}
|
|
||||||
if r.Type == "error" {
|
|
||||||
if r.Name == "hr" {
|
|
||||||
return fmt.Sprintf(hrCode, r.Name, syscalldot())
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf(code, r.Name, syscalldot())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s := ""
|
|
||||||
switch {
|
|
||||||
case r.Type[0] == '*':
|
|
||||||
s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
|
|
||||||
case r.Type == "bool":
|
|
||||||
s = fmt.Sprintf("%s = r0 != 0", r.Name)
|
|
||||||
default:
|
|
||||||
s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
|
|
||||||
}
|
|
||||||
if !r.ReturnsError {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return s + "\n\t" + r.useLongHandleErrorCode(r.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fn describes syscall function.
|
|
||||||
type Fn struct {
|
|
||||||
Name string
|
|
||||||
Params []*Param
|
|
||||||
Rets *Rets
|
|
||||||
PrintTrace bool
|
|
||||||
confirmproc bool
|
|
||||||
dllname string
|
|
||||||
dllfuncname string
|
|
||||||
src string
|
|
||||||
// TODO: get rid of this field and just use parameter index instead
|
|
||||||
curTmpVarIdx int // insure tmp variables have uniq names
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractParams parses s to extract function parameters.
|
|
||||||
func extractParams(s string, f *Fn) ([]*Param, error) {
|
|
||||||
s = trim(s)
|
|
||||||
if s == "" {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
a := strings.Split(s, ",")
|
|
||||||
ps := make([]*Param, len(a))
|
|
||||||
for i := range ps {
|
|
||||||
s2 := trim(a[i])
|
|
||||||
b := strings.Split(s2, " ")
|
|
||||||
if len(b) != 2 {
|
|
||||||
b = strings.Split(s2, "\t")
|
|
||||||
if len(b) != 2 {
|
|
||||||
return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ps[i] = &Param{
|
|
||||||
Name: trim(b[0]),
|
|
||||||
Type: trim(b[1]),
|
|
||||||
fn: f,
|
|
||||||
tmpVarIdx: -1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ps, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractSection extracts text out of string s starting after start
|
|
||||||
// and ending just before end. found return value will indicate success,
|
|
||||||
// and prefix, body and suffix will contain correspondent parts of string s.
|
|
||||||
func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) {
|
|
||||||
s = trim(s)
|
|
||||||
if strings.HasPrefix(s, string(start)) {
|
|
||||||
// no prefix
|
|
||||||
body = s[1:]
|
|
||||||
} else {
|
|
||||||
a := strings.SplitN(s, string(start), 2)
|
|
||||||
if len(a) != 2 {
|
|
||||||
return "", "", s, false
|
|
||||||
}
|
|
||||||
prefix = a[0]
|
|
||||||
body = a[1]
|
|
||||||
}
|
|
||||||
a := strings.SplitN(body, string(end), 2)
|
|
||||||
if len(a) != 2 {
|
|
||||||
return "", "", "", false
|
|
||||||
}
|
|
||||||
return prefix, a[0], a[1], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// newFn parses string s and return created function Fn.
|
|
||||||
func newFn(s string) (*Fn, error) {
|
|
||||||
s = trim(s)
|
|
||||||
f := &Fn{
|
|
||||||
Rets: &Rets{},
|
|
||||||
src: s,
|
|
||||||
PrintTrace: *printTraceFlag,
|
|
||||||
}
|
|
||||||
// function name and args
|
|
||||||
prefix, body, s, found := extractSection(s, '(', ')')
|
|
||||||
if !found || prefix == "" {
|
|
||||||
return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
f.Name = prefix
|
|
||||||
var err error
|
|
||||||
f.Params, err = extractParams(body, f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// return values
|
|
||||||
_, body, s, found = extractSection(s, '(', ')')
|
|
||||||
if found {
|
|
||||||
r, err := extractParams(body, f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch len(r) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
if r[0].IsError() {
|
|
||||||
f.Rets.ReturnsError = true
|
|
||||||
} else {
|
|
||||||
f.Rets.Name = r[0].Name
|
|
||||||
f.Rets.Type = r[0].Type
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
if !r[1].IsError() {
|
|
||||||
return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
f.Rets.ReturnsError = true
|
|
||||||
f.Rets.Name = r[0].Name
|
|
||||||
f.Rets.Type = r[0].Type
|
|
||||||
default:
|
|
||||||
return nil, errors.New("Too many return values in \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fail condition
|
|
||||||
_, body, s, found = extractSection(s, '[', ']')
|
|
||||||
if found {
|
|
||||||
f.Rets.FailCond = body
|
|
||||||
}
|
|
||||||
// dll and dll function names
|
|
||||||
s = trim(s)
|
|
||||||
if s == "" {
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(s, "=") {
|
|
||||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
s = trim(s[1:])
|
|
||||||
a := strings.Split(s, ".")
|
|
||||||
switch len(a) {
|
|
||||||
case 1:
|
|
||||||
f.dllfuncname = a[0]
|
|
||||||
case 2:
|
|
||||||
f.dllname = a[0]
|
|
||||||
f.dllfuncname = a[1]
|
|
||||||
default:
|
|
||||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
if f.dllfuncname[len(f.dllfuncname)-1] == '?' {
|
|
||||||
f.confirmproc = true
|
|
||||||
f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1]
|
|
||||||
}
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DLLName returns DLL name for function f.
|
|
||||||
func (f *Fn) DLLName() string {
|
|
||||||
if f.dllname == "" {
|
|
||||||
return "kernel32"
|
|
||||||
}
|
|
||||||
return f.dllname
|
|
||||||
}
|
|
||||||
|
|
||||||
// DLLName returns DLL function name for function f.
|
|
||||||
func (f *Fn) DLLFuncName() string {
|
|
||||||
if f.dllfuncname == "" {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
return f.dllfuncname
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Fn) ConfirmProc() bool {
|
|
||||||
return f.confirmproc
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamList returns source code for function f parameters.
|
|
||||||
func (f *Fn) ParamList() string {
|
|
||||||
return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperParamList returns source code for helper function f parameters.
|
|
||||||
func (f *Fn) HelperParamList() string {
|
|
||||||
return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamPrintList returns source code of trace printing part correspondent
|
|
||||||
// to syscall input parameters.
|
|
||||||
func (f *Fn) ParamPrintList() string {
|
|
||||||
return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamCount return number of syscall parameters for function f.
|
|
||||||
func (f *Fn) ParamCount() int {
|
|
||||||
n := 0
|
|
||||||
for _, p := range f.Params {
|
|
||||||
n += len(p.SyscallArgList())
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/...
|
|
||||||
// to use. It returns parameter count for correspondent SyscallX function.
|
|
||||||
func (f *Fn) SyscallParamCount() int {
|
|
||||||
n := f.ParamCount()
|
|
||||||
switch {
|
|
||||||
case n <= 3:
|
|
||||||
return 3
|
|
||||||
case n <= 6:
|
|
||||||
return 6
|
|
||||||
case n <= 9:
|
|
||||||
return 9
|
|
||||||
case n <= 12:
|
|
||||||
return 12
|
|
||||||
case n <= 15:
|
|
||||||
return 15
|
|
||||||
default:
|
|
||||||
panic("too many arguments to system call")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syscall determines which SyscallX function to use for function f.
|
|
||||||
func (f *Fn) Syscall() string {
|
|
||||||
c := f.SyscallParamCount()
|
|
||||||
if c == 3 {
|
|
||||||
return syscalldot() + "Syscall"
|
|
||||||
}
|
|
||||||
return syscalldot() + "Syscall" + strconv.Itoa(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyscallParamList returns source code for SyscallX parameters for function f.
|
|
||||||
func (f *Fn) SyscallParamList() string {
|
|
||||||
a := make([]string, 0)
|
|
||||||
for _, p := range f.Params {
|
|
||||||
a = append(a, p.SyscallArgList()...)
|
|
||||||
}
|
|
||||||
for len(a) < f.SyscallParamCount() {
|
|
||||||
a = append(a, "0")
|
|
||||||
}
|
|
||||||
return strings.Join(a, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperCallParamList returns source code of call into function f helper.
|
|
||||||
func (f *Fn) HelperCallParamList() string {
|
|
||||||
a := make([]string, 0, len(f.Params))
|
|
||||||
for _, p := range f.Params {
|
|
||||||
s := p.Name
|
|
||||||
if p.Type == "string" {
|
|
||||||
s = p.tmpVar()
|
|
||||||
}
|
|
||||||
a = append(a, s)
|
|
||||||
}
|
|
||||||
return strings.Join(a, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUTF16 is true, if f is W (utf16) function. It is false
|
|
||||||
// for all A (ascii) functions.
|
|
||||||
func (_ *Fn) IsUTF16() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrconvFunc returns name of Go string to OS string function for f.
|
|
||||||
func (f *Fn) StrconvFunc() string {
|
|
||||||
if f.IsUTF16() {
|
|
||||||
return syscalldot() + "UTF16PtrFromString"
|
|
||||||
}
|
|
||||||
return syscalldot() + "BytePtrFromString"
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrconvType returns Go type name used for OS string for f.
|
|
||||||
func (f *Fn) StrconvType() string {
|
|
||||||
if f.IsUTF16() {
|
|
||||||
return "*uint16"
|
|
||||||
}
|
|
||||||
return "*byte"
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasStringParam is true, if f has at least one string parameter.
|
|
||||||
// Otherwise it is false.
|
|
||||||
func (f *Fn) HasStringParam() bool {
|
|
||||||
for _, p := range f.Params {
|
|
||||||
if p.Type == "string" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var uniqDllFuncName = make(map[string]bool)
|
|
||||||
|
|
||||||
// IsNotDuplicate is true if f is not a duplicated function
|
|
||||||
func (f *Fn) IsNotDuplicate() bool {
|
|
||||||
funcName := f.DLLFuncName()
|
|
||||||
if uniqDllFuncName[funcName] == false {
|
|
||||||
uniqDllFuncName[funcName] = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperName returns name of function f helper.
|
|
||||||
func (f *Fn) HelperName() string {
|
|
||||||
if !f.HasStringParam() {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
return "_" + f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Source files and functions.
|
|
||||||
type Source struct {
|
|
||||||
Funcs []*Fn
|
|
||||||
Files []string
|
|
||||||
StdLibImports []string
|
|
||||||
ExternalImports []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (src *Source) Import(pkg string) {
|
|
||||||
src.StdLibImports = append(src.StdLibImports, pkg)
|
|
||||||
sort.Strings(src.StdLibImports)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (src *Source) ExternalImport(pkg string) {
|
|
||||||
src.ExternalImports = append(src.ExternalImports, pkg)
|
|
||||||
sort.Strings(src.ExternalImports)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFiles parses files listed in fs and extracts all syscall
|
|
||||||
// functions listed in sys comments. It returns source files
|
|
||||||
// and functions collection *Source if successful.
|
|
||||||
func ParseFiles(fs []string) (*Source, error) {
|
|
||||||
src := &Source{
|
|
||||||
Funcs: make([]*Fn, 0),
|
|
||||||
Files: make([]string, 0),
|
|
||||||
StdLibImports: []string{
|
|
||||||
"unsafe",
|
|
||||||
},
|
|
||||||
ExternalImports: make([]string, 0),
|
|
||||||
}
|
|
||||||
for _, file := range fs {
|
|
||||||
if err := src.ParseFile(file); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return src, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DLLs return dll names for a source set src.
|
|
||||||
func (src *Source) DLLs() []string {
|
|
||||||
uniq := make(map[string]bool)
|
|
||||||
r := make([]string, 0)
|
|
||||||
for _, f := range src.Funcs {
|
|
||||||
name := f.DLLName()
|
|
||||||
if _, found := uniq[name]; !found {
|
|
||||||
uniq[name] = true
|
|
||||||
r = append(r, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFile adds additional file path to a source set src.
|
|
||||||
func (src *Source) ParseFile(path string) error {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := trim(s.Text())
|
|
||||||
if len(t) < 7 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(t, "//sys") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t = t[5:]
|
|
||||||
if !(t[0] == ' ' || t[0] == '\t') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f, err := newFn(t[1:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
src.Funcs = append(src.Funcs, f)
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
src.Files = append(src.Files, path)
|
|
||||||
|
|
||||||
// get package name
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
_, err = file.Seek(0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
packageName = pkg.Name.Name
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStdRepo returns true if src is part of standard library.
|
|
||||||
func (src *Source) IsStdRepo() (bool, error) {
|
|
||||||
if len(src.Files) == 0 {
|
|
||||||
return false, errors.New("no input files provided")
|
|
||||||
}
|
|
||||||
abspath, err := filepath.Abs(src.Files[0])
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
goroot := runtime.GOROOT()
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
abspath = strings.ToLower(abspath)
|
|
||||||
goroot = strings.ToLower(goroot)
|
|
||||||
}
|
|
||||||
sep := string(os.PathSeparator)
|
|
||||||
if !strings.HasSuffix(goroot, sep) {
|
|
||||||
goroot += sep
|
|
||||||
}
|
|
||||||
return strings.HasPrefix(abspath, goroot), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate output source file from a source set src.
|
|
||||||
func (src *Source) Generate(w io.Writer) error {
|
|
||||||
const (
|
|
||||||
pkgStd = iota // any package in std library
|
|
||||||
pkgXSysWindows // x/sys/windows package
|
|
||||||
pkgOther
|
|
||||||
)
|
|
||||||
isStdRepo, err := src.IsStdRepo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var pkgtype int
|
|
||||||
switch {
|
|
||||||
case isStdRepo:
|
|
||||||
pkgtype = pkgStd
|
|
||||||
case packageName == "windows":
|
|
||||||
// TODO: this needs better logic than just using package name
|
|
||||||
pkgtype = pkgXSysWindows
|
|
||||||
default:
|
|
||||||
pkgtype = pkgOther
|
|
||||||
}
|
|
||||||
if *systemDLL {
|
|
||||||
switch pkgtype {
|
|
||||||
case pkgStd:
|
|
||||||
src.Import("internal/syscall/windows/sysdll")
|
|
||||||
case pkgXSysWindows:
|
|
||||||
default:
|
|
||||||
src.ExternalImport("golang.org/x/sys/windows")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
src.ExternalImport("github.com/Microsoft/go-winio")
|
|
||||||
if packageName != "syscall" {
|
|
||||||
src.Import("syscall")
|
|
||||||
}
|
|
||||||
funcMap := template.FuncMap{
|
|
||||||
"packagename": packagename,
|
|
||||||
"syscalldot": syscalldot,
|
|
||||||
"newlazydll": func(dll string) string {
|
|
||||||
arg := "\"" + dll + ".dll\""
|
|
||||||
if !*systemDLL {
|
|
||||||
return syscalldot() + "NewLazyDLL(" + arg + ")"
|
|
||||||
}
|
|
||||||
switch pkgtype {
|
|
||||||
case pkgStd:
|
|
||||||
return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))"
|
|
||||||
case pkgXSysWindows:
|
|
||||||
return "NewLazySystemDLL(" + arg + ")"
|
|
||||||
default:
|
|
||||||
return "windows.NewLazySystemDLL(" + arg + ")"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
|
|
||||||
err = t.Execute(w, src)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("Failed to execute template: " + err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n")
|
|
||||||
flag.PrintDefaults()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
src, err := ParseFiles(flag.Args())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := src.Generate(&buf); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := format.Source(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if *filename == "" {
|
|
||||||
_, err = os.Stdout.Write(data)
|
|
||||||
} else {
|
|
||||||
err = ioutil.WriteFile(*filename, data, 0644)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: use println instead to print in the following template
|
|
||||||
const srcTemplate = `
|
|
||||||
|
|
||||||
{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
|
||||||
|
|
||||||
package {{packagename}}
|
|
||||||
|
|
||||||
import (
|
|
||||||
{{range .StdLibImports}}"{{.}}"
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{range .ExternalImports}}"{{.}}"
|
|
||||||
{{end}}
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ unsafe.Pointer
|
|
||||||
|
|
||||||
// Do the interface allocations only once for common
|
|
||||||
// Errno values.
|
|
||||||
const (
|
|
||||||
errnoERROR_IO_PENDING = 997
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errERROR_IO_PENDING error = {{syscalldot}}Errno(errnoERROR_IO_PENDING)
|
|
||||||
)
|
|
||||||
|
|
||||||
// errnoErr returns common boxed Errno values, to prevent
|
|
||||||
// allocations at runtime.
|
|
||||||
func errnoErr(e {{syscalldot}}Errno) error {
|
|
||||||
switch e {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case errnoERROR_IO_PENDING:
|
|
||||||
return errERROR_IO_PENDING
|
|
||||||
}
|
|
||||||
// TODO: add more here, after collecting data on the common
|
|
||||||
// error values see on Windows. (perhaps when running
|
|
||||||
// all.bat?)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
{{template "dlls" .}}
|
|
||||||
{{template "funcnames" .}})
|
|
||||||
{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{/* help functions */}}
|
|
||||||
|
|
||||||
{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "funcnames"}}{{range .Funcs}}{{if .IsNotDuplicate}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}"){{end}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "helperbody"}}
|
|
||||||
func {{.Name}}({{.ParamList}}) {{template "results" .}}{
|
|
||||||
{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "funcbody"}}
|
|
||||||
func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
|
|
||||||
{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}}
|
|
||||||
{{template "seterror" .}}{{template "printtrace" .}} return
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
|
|
||||||
{{end}}{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
|
|
||||||
{{end}}{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
|
|
||||||
|
|
||||||
{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
|
|
||||||
{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
`
|
|
97
vendor/github.com/containers/storage/pkg/archive/example_changes.go
generated
vendored
97
vendor/github.com/containers/storage/pkg/archive/example_changes.go
generated
vendored
|
@ -1,97 +0,0 @@
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// Simple tool to create an archive stream from an old and new directory
|
|
||||||
//
|
|
||||||
// By default it will stream the comparison of two temporary directories with junk files
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/containers/storage/pkg/archive"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
flDebug = flag.Bool("D", false, "debugging output")
|
|
||||||
flNewDir = flag.String("newdir", "", "")
|
|
||||||
flOldDir = flag.String("olddir", "", "")
|
|
||||||
log = logrus.New()
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = func() {
|
|
||||||
fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
|
|
||||||
fmt.Printf("%s [OPTIONS]\n", os.Args[0])
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
|
||||||
flag.Parse()
|
|
||||||
log.Out = os.Stderr
|
|
||||||
if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
|
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
|
||||||
}
|
|
||||||
var newDir, oldDir string
|
|
||||||
|
|
||||||
if len(*flNewDir) == 0 {
|
|
||||||
var err error
|
|
||||||
newDir, err = ioutil.TempDir("", "storage-test-newDir")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(newDir)
|
|
||||||
if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newDir = *flNewDir
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*flOldDir) == 0 {
|
|
||||||
oldDir, err := ioutil.TempDir("", "storage-test-oldDir")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(oldDir)
|
|
||||||
} else {
|
|
||||||
oldDir = *flOldDir
|
|
||||||
}
|
|
||||||
|
|
||||||
changes, err := archive.ChangesDirs(newDir, oldDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
a, err := archive.ExportChanges(newDir, changes)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer a.Close()
|
|
||||||
|
|
||||||
i, err := io.Copy(os.Stdout, a)
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
|
|
||||||
fileData := []byte("fooo")
|
|
||||||
for n := 0; n < numberOfFiles; n++ {
|
|
||||||
fileName := fmt.Sprintf("file-%d", n)
|
|
||||||
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if makeLinks {
|
|
||||||
if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
totalSize := numberOfFiles * len(fileData)
|
|
||||||
return totalSize, nil
|
|
||||||
}
|
|
20
vendor/github.com/fatih/camelcase/LICENSE.md
generated
vendored
Normal file
20
vendor/github.com/fatih/camelcase/LICENSE.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Fatih Arslan
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
58
vendor/github.com/fatih/camelcase/README.md
generated
vendored
Normal file
58
vendor/github.com/fatih/camelcase/README.md
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# CamelCase [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/camelcase) [![Build Status](http://img.shields.io/travis/fatih/camelcase.svg?style=flat-square)](https://travis-ci.org/fatih/camelcase)
|
||||||
|
|
||||||
|
CamelCase is a Golang (Go) package to split the words of a camelcase type
|
||||||
|
string into a slice of words. It can be used to convert a camelcase word (lower
|
||||||
|
or upper case) into any type of word.
|
||||||
|
|
||||||
|
## Splitting rules:
|
||||||
|
|
||||||
|
1. If string is not valid UTF-8, return it without splitting as
|
||||||
|
single item array.
|
||||||
|
2. Assign all unicode characters into one of 4 sets: lower case
|
||||||
|
letters, upper case letters, numbers, and all other characters.
|
||||||
|
3. Iterate through characters of string, introducing splits
|
||||||
|
between adjacent characters that belong to different sets.
|
||||||
|
4. Iterate through array of split strings, and if a given string
|
||||||
|
is upper case:
|
||||||
|
* if subsequent string is lower case:
|
||||||
|
* move last character of upper case string to beginning of
|
||||||
|
lower case string
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get github.com/fatih/camelcase
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage and examples
|
||||||
|
|
||||||
|
```go
|
||||||
|
splitted := camelcase.Split("GolangPackage")
|
||||||
|
|
||||||
|
fmt.Println(splitted[0], splitted[1]) // prints: "Golang", "Package"
|
||||||
|
```
|
||||||
|
|
||||||
|
Both lower camel case and upper camel case are supported. For more info please
|
||||||
|
check: [http://en.wikipedia.org/wiki/CamelCase](http://en.wikipedia.org/wiki/CamelCase)
|
||||||
|
|
||||||
|
Below are some example cases:
|
||||||
|
|
||||||
|
```
|
||||||
|
"" => []
|
||||||
|
"lowercase" => ["lowercase"]
|
||||||
|
"Class" => ["Class"]
|
||||||
|
"MyClass" => ["My", "Class"]
|
||||||
|
"MyC" => ["My", "C"]
|
||||||
|
"HTML" => ["HTML"]
|
||||||
|
"PDFLoader" => ["PDF", "Loader"]
|
||||||
|
"AString" => ["A", "String"]
|
||||||
|
"SimpleXMLParser" => ["Simple", "XML", "Parser"]
|
||||||
|
"vimRPCPlugin" => ["vim", "RPC", "Plugin"]
|
||||||
|
"GL11Version" => ["GL", "11", "Version"]
|
||||||
|
"99Bottles" => ["99", "Bottles"]
|
||||||
|
"May5" => ["May", "5"]
|
||||||
|
"BFG9000" => ["BFG", "9000"]
|
||||||
|
"BöseÜberraschung" => ["Böse", "Überraschung"]
|
||||||
|
"Two spaces" => ["Two", " ", "spaces"]
|
||||||
|
"BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"]
|
||||||
|
```
|
90
vendor/github.com/fatih/camelcase/camelcase.go
generated
vendored
Normal file
90
vendor/github.com/fatih/camelcase/camelcase.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Package camelcase is a micro package to split the words of a camelcase type
|
||||||
|
// string into a slice of words.
|
||||||
|
package camelcase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Split splits the camelcase word and returns a list of words. It also
|
||||||
|
// supports digits. Both lower camel case and upper camel case are supported.
|
||||||
|
// For more info please check: http://en.wikipedia.org/wiki/CamelCase
|
||||||
|
//
|
||||||
|
// Examples
|
||||||
|
//
|
||||||
|
// "" => [""]
|
||||||
|
// "lowercase" => ["lowercase"]
|
||||||
|
// "Class" => ["Class"]
|
||||||
|
// "MyClass" => ["My", "Class"]
|
||||||
|
// "MyC" => ["My", "C"]
|
||||||
|
// "HTML" => ["HTML"]
|
||||||
|
// "PDFLoader" => ["PDF", "Loader"]
|
||||||
|
// "AString" => ["A", "String"]
|
||||||
|
// "SimpleXMLParser" => ["Simple", "XML", "Parser"]
|
||||||
|
// "vimRPCPlugin" => ["vim", "RPC", "Plugin"]
|
||||||
|
// "GL11Version" => ["GL", "11", "Version"]
|
||||||
|
// "99Bottles" => ["99", "Bottles"]
|
||||||
|
// "May5" => ["May", "5"]
|
||||||
|
// "BFG9000" => ["BFG", "9000"]
|
||||||
|
// "BöseÜberraschung" => ["Böse", "Überraschung"]
|
||||||
|
// "Two spaces" => ["Two", " ", "spaces"]
|
||||||
|
// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"]
|
||||||
|
//
|
||||||
|
// Splitting rules
|
||||||
|
//
|
||||||
|
// 1) If string is not valid UTF-8, return it without splitting as
|
||||||
|
// single item array.
|
||||||
|
// 2) Assign all unicode characters into one of 4 sets: lower case
|
||||||
|
// letters, upper case letters, numbers, and all other characters.
|
||||||
|
// 3) Iterate through characters of string, introducing splits
|
||||||
|
// between adjacent characters that belong to different sets.
|
||||||
|
// 4) Iterate through array of split strings, and if a given string
|
||||||
|
// is upper case:
|
||||||
|
// if subsequent string is lower case:
|
||||||
|
// move last character of upper case string to beginning of
|
||||||
|
// lower case string
|
||||||
|
func Split(src string) (entries []string) {
|
||||||
|
// don't split invalid utf8
|
||||||
|
if !utf8.ValidString(src) {
|
||||||
|
return []string{src}
|
||||||
|
}
|
||||||
|
entries = []string{}
|
||||||
|
var runes [][]rune
|
||||||
|
lastClass := 0
|
||||||
|
class := 0
|
||||||
|
// split into fields based on class of unicode character
|
||||||
|
for _, r := range src {
|
||||||
|
switch true {
|
||||||
|
case unicode.IsLower(r):
|
||||||
|
class = 1
|
||||||
|
case unicode.IsUpper(r):
|
||||||
|
class = 2
|
||||||
|
case unicode.IsDigit(r):
|
||||||
|
class = 3
|
||||||
|
default:
|
||||||
|
class = 4
|
||||||
|
}
|
||||||
|
if class == lastClass {
|
||||||
|
runes[len(runes)-1] = append(runes[len(runes)-1], r)
|
||||||
|
} else {
|
||||||
|
runes = append(runes, []rune{r})
|
||||||
|
}
|
||||||
|
lastClass = class
|
||||||
|
}
|
||||||
|
// handle upper case -> lower case sequences, e.g.
|
||||||
|
// "PDFL", "oader" -> "PDF", "Loader"
|
||||||
|
for i := 0; i < len(runes)-1; i++ {
|
||||||
|
if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) {
|
||||||
|
runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
|
||||||
|
runes[i] = runes[i][:len(runes[i])-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// construct []string from results
|
||||||
|
for _, s := range runes {
|
||||||
|
if len(s) > 0 {
|
||||||
|
entries = append(entries, string(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in a new issue