1) Change default gofmt default settings for

parsing and printing to new syntax.

   Use -oldparser to parse the old syntax,
   use -oldprinter to print the old syntax.

2) Change default gofmt formatting settings
   to use tabs for indentation only and to use
   spaces for alignment. This will make the code
   alignment insensitive to an editor's tabwidth.

   Use -spaces=false to use tabs for alignment.

3) Manually changed src/exp/parser/parser_test.go
   so that it doesn't try to parse the parser's
   source files using the old syntax (they have
   new syntax now).

4) gofmt -w src misc test/bench

4th set of files.

R=rsc
CC=golang-dev
https://golang.org/cl/180049
This commit is contained in:
Robert Griesemer 2009-12-15 15:40:16 -08:00
parent a3d1045fb7
commit d65a5cce89
119 changed files with 14325 additions and 14325 deletions

View File

@ -9,8 +9,8 @@ package once
import "sync" import "sync"
type job struct { type job struct {
done bool; done bool
sync.Mutex; // should probably be sync.Notification or some such sync.Mutex // should probably be sync.Notification or some such
} }
var jobs = make(map[func()]*job) var jobs = make(map[func()]*job)
@ -37,23 +37,23 @@ var joblock sync.Mutex
// because the func() expression in the first creates a new // because the func() expression in the first creates a new
// func each time f runs, and each of those funcs is run once. // func each time f runs, and each of those funcs is run once.
func Do(f func()) { func Do(f func()) {
joblock.Lock(); joblock.Lock()
j, present := jobs[f]; j, present := jobs[f]
if !present { if !present {
// run it // run it
j = new(job); j = new(job)
j.Lock(); j.Lock()
jobs[f] = j; jobs[f] = j
joblock.Unlock(); joblock.Unlock()
f(); f()
j.done = true; j.done = true
j.Unlock(); j.Unlock()
} else { } else {
// wait for it // wait for it
joblock.Unlock(); joblock.Unlock()
if j.done != true { if j.done != true {
j.Lock(); j.Lock()
j.Unlock(); j.Unlock()
} }
} }
} }

View File

@ -5,25 +5,25 @@
package once_test package once_test
import ( import (
"once"; "once"
"testing"; "testing"
) )
var ncall int var ncall int
func call() { ncall++ } func call() { ncall++ }
func TestDo(t *testing.T) { func TestDo(t *testing.T) {
ncall = 0; ncall = 0
once.Do(call); once.Do(call)
if ncall != 1 { if ncall != 1 {
t.Fatalf("once.Do(call) didn't call(): ncall=%d", ncall) t.Fatalf("once.Do(call) didn't call(): ncall=%d", ncall)
} }
once.Do(call); once.Do(call)
if ncall != 1 { if ncall != 1 {
t.Fatalf("second once.Do(call) did call(): ncall=%d", ncall) t.Fatalf("second once.Do(call) did call(): ncall=%d", ncall)
} }
once.Do(call); once.Do(call)
if ncall != 1 { if ncall != 1 {
t.Fatalf("third once.Do(call) did call(): ncall=%d", ncall) t.Fatalf("third once.Do(call) did call(): ncall=%d", ncall)
} }

View File

@ -5,12 +5,12 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
// Readdirnames reads the contents of the directory associated with file and // Readdirnames reads the contents of the directory associated with file and
@ -21,59 +21,59 @@ const (
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.bufp = 0; d.bufp = 0
// Final argument is (basep *uintptr) and the syscall doesn't take nil. // Final argument is (basep *uintptr) and the syscall doesn't take nil.
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr))
if errno != 0 { if errno != 0 {
d.nbuf = 0; d.nbuf = 0
return names, NewSyscallError("getdirentries", errno); return names, NewSyscallError("getdirentries", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
if dirent.Reclen == 0 { if dirent.Reclen == 0 {
d.bufp = d.nbuf; d.bufp = d.nbuf
break; break
} }
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Ino == 0 { // File absent in directory. if dirent.Ino == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:dirent.Namlen]); var name = string(bytes[0:dirent.Namlen])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }

View File

@ -5,70 +5,70 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.bufp = 0; d.bufp = 0
// Final argument is (basep *uintptr) and the syscall doesn't take nil. // Final argument is (basep *uintptr) and the syscall doesn't take nil.
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr))
if errno != 0 { if errno != 0 {
d.nbuf = 0; d.nbuf = 0
return names, NewSyscallError("getdirentries", errno); return names, NewSyscallError("getdirentries", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
if dirent.Reclen == 0 { if dirent.Reclen == 0 {
d.bufp = d.nbuf; d.bufp = d.nbuf
break; break
} }
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Fileno == 0 { // File absent in directory. if dirent.Fileno == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:dirent.Namlen]); var name = string(bytes[0:dirent.Namlen])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }

View File

@ -5,12 +5,12 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
func clen(n []byte) int { func clen(n []byte) int {
@ -19,59 +19,59 @@ func clen(n []byte) int {
return i return i
} }
} }
return len(n); return len(n)
} }
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.nbuf, errno = syscall.Getdents(file.fd, d.buf); d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
if errno != 0 { if errno != 0 {
return names, NewSyscallError("getdents", errno) return names, NewSyscallError("getdents", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
d.bufp = 0; d.bufp = 0
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Ino == 0 { // File absent in directory. if dirent.Ino == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:clen(bytes)]); var name = string(bytes[0:clen(bytes)])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }

View File

@ -5,12 +5,12 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
func clen(n []byte) int { func clen(n []byte) int {
@ -19,59 +19,59 @@ func clen(n []byte) int {
return i return i
} }
} }
return len(n); return len(n)
} }
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.nbuf, errno = syscall.Getdents(file.fd, d.buf); d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
if errno != 0 { if errno != 0 {
return names, NewSyscallError("getdents", errno) return names, NewSyscallError("getdents", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
d.bufp = 0; d.bufp = 0
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Ino == 0 { // File absent in directory. if dirent.Ino == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:clen(bytes)]); var name = string(bytes[0:clen(bytes)])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }

View File

@ -7,7 +7,7 @@
package os package os
import ( import (
"once"; "once"
) )
// ENOENV is the Error indicating that an environment variable does not exist. // ENOENV is the Error indicating that an environment variable does not exist.
@ -17,12 +17,12 @@ var env map[string]string
func copyenv() { func copyenv() {
env = make(map[string]string); env = make(map[string]string)
for _, s := range Envs { for _, s := range Envs {
for j := 0; j < len(s); j++ { for j := 0; j < len(s); j++ {
if s[j] == '=' { if s[j] == '=' {
env[s[0:j]] = s[j+1:]; env[s[0:j]] = s[j+1:]
break; break
} }
} }
} }
@ -31,56 +31,56 @@ func copyenv() {
// Getenverror retrieves the value of the environment variable named by the key. // Getenverror retrieves the value of the environment variable named by the key.
// It returns the value and an error, if any. // It returns the value and an error, if any.
func Getenverror(key string) (value string, err Error) { func Getenverror(key string) (value string, err Error) {
once.Do(copyenv); once.Do(copyenv)
if len(key) == 0 { if len(key) == 0 {
return "", EINVAL return "", EINVAL
} }
v, ok := env[key]; v, ok := env[key]
if !ok { if !ok {
return "", ENOENV return "", ENOENV
} }
return v, nil; return v, nil
} }
// Getenv retrieves the value of the environment variable named by the key. // Getenv retrieves the value of the environment variable named by the key.
// It returns the value, which will be empty if the variable is not present. // It returns the value, which will be empty if the variable is not present.
func Getenv(key string) string { func Getenv(key string) string {
v, _ := Getenverror(key); v, _ := Getenverror(key)
return v; return v
} }
// Setenv sets the value of the environment variable named by the key. // Setenv sets the value of the environment variable named by the key.
// It returns an Error, if any. // It returns an Error, if any.
func Setenv(key, value string) Error { func Setenv(key, value string) Error {
once.Do(copyenv); once.Do(copyenv)
if len(key) == 0 { if len(key) == 0 {
return EINVAL return EINVAL
} }
env[key] = value; env[key] = value
return nil; return nil
} }
// Clearenv deletes all environment variables. // Clearenv deletes all environment variables.
func Clearenv() { func Clearenv() {
once.Do(copyenv); // prevent copyenv in Getenv/Setenv once.Do(copyenv) // prevent copyenv in Getenv/Setenv
env = make(map[string]string); env = make(map[string]string)
} }
// Environ returns an array of strings representing the environment, // Environ returns an array of strings representing the environment,
// in the form "key=value". // in the form "key=value".
func Environ() []string { func Environ() []string {
once.Do(copyenv); once.Do(copyenv)
a := make([]string, len(env)); a := make([]string, len(env))
i := 0; i := 0
for k, v := range env { for k, v := range env {
// check i < len(a) for safety, // check i < len(a) for safety,
// in case env is changing underfoot. // in case env is changing underfoot.
if i < len(a) { if i < len(a) {
a[i] = k + "=" + v; a[i] = k + "=" + v
i++; i++
} }
} }
return a[0:i]; return a[0:i]
} }

View File

@ -8,85 +8,85 @@ import syscall "syscall"
// An Error can represent any printable error condition. // An Error can represent any printable error condition.
type Error interface { type Error interface {
String() string; String() string
} }
// A helper type that can be embedded or wrapped to simplify satisfying // A helper type that can be embedded or wrapped to simplify satisfying
// Error. // Error.
type ErrorString string type ErrorString string
func (e ErrorString) String() string { return string(e) } func (e ErrorString) String() string { return string(e) }
// Note: If the name of the function NewError changes, // Note: If the name of the function NewError changes,
// pkg/go/doc/doc.go should be adjusted since it hardwires // pkg/go/doc/doc.go should be adjusted since it hardwires
// this name in a heuristic. // this name in a heuristic.
// NewError converts s to an ErrorString, which satisfies the Error interface. // NewError converts s to an ErrorString, which satisfies the Error interface.
func NewError(s string) Error { return ErrorString(s) } func NewError(s string) Error { return ErrorString(s) }
// Errno is the Unix error number. Names such as EINVAL are simple // Errno is the Unix error number. Names such as EINVAL are simple
// wrappers to convert the error number into an Error. // wrappers to convert the error number into an Error.
type Errno int64 type Errno int64
func (e Errno) String() string { return syscall.Errstr(int(e)) } func (e Errno) String() string { return syscall.Errstr(int(e)) }
// Commonly known Unix errors. // Commonly known Unix errors.
var ( var (
EPERM Error = Errno(syscall.EPERM); EPERM Error = Errno(syscall.EPERM)
ENOENT Error = Errno(syscall.ENOENT); ENOENT Error = Errno(syscall.ENOENT)
ESRCH Error = Errno(syscall.ESRCH); ESRCH Error = Errno(syscall.ESRCH)
EINTR Error = Errno(syscall.EINTR); EINTR Error = Errno(syscall.EINTR)
EIO Error = Errno(syscall.EIO); EIO Error = Errno(syscall.EIO)
ENXIO Error = Errno(syscall.ENXIO); ENXIO Error = Errno(syscall.ENXIO)
E2BIG Error = Errno(syscall.E2BIG); E2BIG Error = Errno(syscall.E2BIG)
ENOEXEC Error = Errno(syscall.ENOEXEC); ENOEXEC Error = Errno(syscall.ENOEXEC)
EBADF Error = Errno(syscall.EBADF); EBADF Error = Errno(syscall.EBADF)
ECHILD Error = Errno(syscall.ECHILD); ECHILD Error = Errno(syscall.ECHILD)
EDEADLK Error = Errno(syscall.EDEADLK); EDEADLK Error = Errno(syscall.EDEADLK)
ENOMEM Error = Errno(syscall.ENOMEM); ENOMEM Error = Errno(syscall.ENOMEM)
EACCES Error = Errno(syscall.EACCES); EACCES Error = Errno(syscall.EACCES)
EFAULT Error = Errno(syscall.EFAULT); EFAULT Error = Errno(syscall.EFAULT)
EBUSY Error = Errno(syscall.EBUSY); EBUSY Error = Errno(syscall.EBUSY)
EEXIST Error = Errno(syscall.EEXIST); EEXIST Error = Errno(syscall.EEXIST)
EXDEV Error = Errno(syscall.EXDEV); EXDEV Error = Errno(syscall.EXDEV)
ENODEV Error = Errno(syscall.ENODEV); ENODEV Error = Errno(syscall.ENODEV)
ENOTDIR Error = Errno(syscall.ENOTDIR); ENOTDIR Error = Errno(syscall.ENOTDIR)
EISDIR Error = Errno(syscall.EISDIR); EISDIR Error = Errno(syscall.EISDIR)
EINVAL Error = Errno(syscall.EINVAL); EINVAL Error = Errno(syscall.EINVAL)
ENFILE Error = Errno(syscall.ENFILE); ENFILE Error = Errno(syscall.ENFILE)
EMFILE Error = Errno(syscall.EMFILE); EMFILE Error = Errno(syscall.EMFILE)
ENOTTY Error = Errno(syscall.ENOTTY); ENOTTY Error = Errno(syscall.ENOTTY)
EFBIG Error = Errno(syscall.EFBIG); EFBIG Error = Errno(syscall.EFBIG)
ENOSPC Error = Errno(syscall.ENOSPC); ENOSPC Error = Errno(syscall.ENOSPC)
ESPIPE Error = Errno(syscall.ESPIPE); ESPIPE Error = Errno(syscall.ESPIPE)
EROFS Error = Errno(syscall.EROFS); EROFS Error = Errno(syscall.EROFS)
EMLINK Error = Errno(syscall.EMLINK); EMLINK Error = Errno(syscall.EMLINK)
EPIPE Error = Errno(syscall.EPIPE); EPIPE Error = Errno(syscall.EPIPE)
EAGAIN Error = Errno(syscall.EAGAIN); EAGAIN Error = Errno(syscall.EAGAIN)
EDOM Error = Errno(syscall.EDOM); EDOM Error = Errno(syscall.EDOM)
ERANGE Error = Errno(syscall.ERANGE); ERANGE Error = Errno(syscall.ERANGE)
EADDRINUSE Error = Errno(syscall.EADDRINUSE); EADDRINUSE Error = Errno(syscall.EADDRINUSE)
ECONNREFUSED Error = Errno(syscall.ECONNREFUSED); ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG); ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT); EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
) )
// PathError records an error and the operation and file path that caused it. // PathError records an error and the operation and file path that caused it.
type PathError struct { type PathError struct {
Op string; Op string
Path string; Path string
Error Error; Error Error
} }
func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() } func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
// SyscallError records an error from a specific system call. // SyscallError records an error from a specific system call.
type SyscallError struct { type SyscallError struct {
Syscall string; Syscall string
Errno Errno; Errno Errno
} }
func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() } func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
// Note: If the name of the function NewSyscallError changes, // Note: If the name of the function NewSyscallError changes,
// pkg/go/doc/doc.go should be adjusted since it hardwires // pkg/go/doc/doc.go should be adjusted since it hardwires
@ -99,5 +99,5 @@ func NewSyscallError(syscall string, errno int) Error {
if errno == 0 { if errno == 0 {
return nil return nil
} }
return &SyscallError{syscall, Errno(errno)}; return &SyscallError{syscall, Errno(errno)}
} }

View File

@ -5,7 +5,7 @@
package os package os
import ( import (
"syscall"; "syscall"
) )
// ForkExec forks the current process and invokes Exec with the file, arguments, // ForkExec forks the current process and invokes Exec with the file, arguments,
@ -17,7 +17,7 @@ import (
// If dir is not empty, the child chdirs into the directory before execing the program. // If dir is not empty, the child chdirs into the directory before execing the program.
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) { func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
// Create array of integer (system) fds. // Create array of integer (system) fds.
intfd := make([]int, len(fd)); intfd := make([]int, len(fd))
for i, f := range fd { for i, f := range fd {
if f == nil { if f == nil {
intfd[i] = -1 intfd[i] = -1
@ -26,11 +26,11 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File
} }
} }
p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd); p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd)
if e != 0 { if e != 0 {
return 0, &PathError{"fork/exec", argv0, Errno(e)} return 0, &PathError{"fork/exec", argv0, Errno(e)}
} }
return p, nil; return p, nil
} }
// Exec replaces the current process with an execution of the program // Exec replaces the current process with an execution of the program
@ -41,11 +41,11 @@ func Exec(argv0 string, argv []string, envv []string) Error {
if envv == nil { if envv == nil {
envv = Environ() envv = Environ()
} }
e := syscall.Exec(argv0, argv, envv); e := syscall.Exec(argv0, argv, envv)
if e != 0 { if e != 0 {
return &PathError{"exec", argv0, Errno(e)} return &PathError{"exec", argv0, Errno(e)}
} }
return nil; return nil
} }
// TODO(rsc): Should os implement its own syscall.WaitStatus // TODO(rsc): Should os implement its own syscall.WaitStatus
@ -57,17 +57,17 @@ func Exec(argv0 string, argv []string, envv []string) Error {
// Waitmsg stores the information about an exited process as reported by Wait. // Waitmsg stores the information about an exited process as reported by Wait.
type Waitmsg struct { type Waitmsg struct {
Pid int; // The process's id. Pid int // The process's id.
syscall.WaitStatus; // System-dependent status info. syscall.WaitStatus // System-dependent status info.
Rusage *syscall.Rusage; // System-dependent resource usage info. Rusage *syscall.Rusage // System-dependent resource usage info.
} }
// Options for Wait. // Options for Wait.
const ( const (
WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited. WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported. WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
WUNTRACED = WSTOPPED; WUNTRACED = WSTOPPED
WRUSAGE = 1 << 20; // Record resource usage. WRUSAGE = 1 << 20 // Record resource usage.
) )
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's // WRUSAGE must not be too high a bit, to avoid clashing with Linux's
@ -78,21 +78,21 @@ const (
// Waitmsg describing its status and an Error, if any. The options // Waitmsg describing its status and an Error, if any. The options
// (WNOHANG etc.) affect the behavior of the Wait call. // (WNOHANG etc.) affect the behavior of the Wait call.
func Wait(pid int, options int) (w *Waitmsg, err Error) { func Wait(pid int, options int) (w *Waitmsg, err Error) {
var status syscall.WaitStatus; var status syscall.WaitStatus
var rusage *syscall.Rusage; var rusage *syscall.Rusage
if options&WRUSAGE != 0 { if options&WRUSAGE != 0 {
rusage = new(syscall.Rusage); rusage = new(syscall.Rusage)
options ^= WRUSAGE; options ^= WRUSAGE
} }
pid1, e := syscall.Wait4(pid, &status, options, rusage); pid1, e := syscall.Wait4(pid, &status, options, rusage)
if e != 0 { if e != 0 {
return nil, NewSyscallError("wait", e) return nil, NewSyscallError("wait", e)
} }
w = new(Waitmsg); w = new(Waitmsg)
w.Pid = pid1; w.Pid = pid1
w.WaitStatus = status; w.WaitStatus = status
w.Rusage = rusage; w.Rusage = rusage
return w, nil; return w, nil
} }
// Convert i to decimal string. // Convert i to decimal string.
@ -101,37 +101,37 @@ func itod(i int) string {
return "0" return "0"
} }
u := uint64(i); u := uint64(i)
if i < 0 { if i < 0 {
u = -u u = -u
} }
// Assemble decimal in reverse order. // Assemble decimal in reverse order.
var b [32]byte; var b [32]byte
bp := len(b); bp := len(b)
for ; u > 0; u /= 10 { for ; u > 0; u /= 10 {
bp--; bp--
b[bp] = byte(u%10) + '0'; b[bp] = byte(u%10) + '0'
} }
if i < 0 { if i < 0 {
bp--; bp--
b[bp] = '-'; b[bp] = '-'
} }
return string(b[bp:]); return string(b[bp:])
} }
func (w Waitmsg) String() string { func (w Waitmsg) String() string {
// TODO(austin) Use signal names when possible? // TODO(austin) Use signal names when possible?
res := ""; res := ""
switch { switch {
case w.Exited(): case w.Exited():
res = "exit status " + itod(w.ExitStatus()) res = "exit status " + itod(w.ExitStatus())
case w.Signaled(): case w.Signaled():
res = "signal " + itod(w.Signal()) res = "signal " + itod(w.Signal())
case w.Stopped(): case w.Stopped():
res = "stop signal " + itod(w.StopSignal()); res = "stop signal " + itod(w.StopSignal())
if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 { if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
res += " (trap " + itod(w.TrapCause()) + ")" res += " (trap " + itod(w.TrapCause()) + ")"
} }
@ -141,11 +141,11 @@ func (w Waitmsg) String() string {
if w.CoreDump() { if w.CoreDump() {
res += " (core dumped)" res += " (core dumped)"
} }
return res; return res
} }
// Getpid returns the process id of the caller. // Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() } func Getpid() int { return syscall.Getpid() }
// Getppid returns the process id of the caller's parent. // Getppid returns the process id of the caller's parent.
func Getppid() int { return syscall.Getppid() } func Getppid() int { return syscall.Getppid() }

View File

@ -7,80 +7,80 @@
package os package os
import ( import (
"syscall"; "syscall"
) )
// Auxiliary information if the File describes a directory // Auxiliary information if the File describes a directory
type dirInfo struct { type dirInfo struct {
buf []byte; // buffer for directory I/O buf []byte // buffer for directory I/O
nbuf int; // length of buf; return value from Getdirentries nbuf int // length of buf; return value from Getdirentries
bufp int; // location of next record in buf. bufp int // location of next record in buf.
} }
// File represents an open file descriptor. // File represents an open file descriptor.
type File struct { type File struct {
fd int; fd int
name string; name string
dirinfo *dirInfo; // nil unless directory being read dirinfo *dirInfo // nil unless directory being read
nepipe int; // number of consecutive EPIPE in Write nepipe int // number of consecutive EPIPE in Write
} }
// Fd returns the integer Unix file descriptor referencing the open file. // Fd returns the integer Unix file descriptor referencing the open file.
func (file *File) Fd() int { return file.fd } func (file *File) Fd() int { return file.fd }
// Name returns the name of the file as presented to Open. // Name returns the name of the file as presented to Open.
func (file *File) Name() string { return file.name } func (file *File) Name() string { return file.name }
// NewFile returns a new File with the given file descriptor and name. // NewFile returns a new File with the given file descriptor and name.
func NewFile(fd int, name string) *File { func NewFile(fd int, name string) *File {
if fd < 0 { if fd < 0 {
return nil return nil
} }
return &File{fd, name, nil, 0}; return &File{fd, name, nil, 0}
} }
// Stdin, Stdout, and Stderr are open Files pointing to the standard input, // Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors. // standard output, and standard error file descriptors.
var ( var (
Stdin = NewFile(0, "/dev/stdin"); Stdin = NewFile(0, "/dev/stdin")
Stdout = NewFile(1, "/dev/stdout"); Stdout = NewFile(1, "/dev/stdout")
Stderr = NewFile(2, "/dev/stderr"); Stderr = NewFile(2, "/dev/stderr")
) )
// Flags to Open wrapping those of the underlying system. Not all flags // Flags to Open wrapping those of the underlying system. Not all flags
// may be implemented on a given system. // may be implemented on a given system.
const ( const (
O_RDONLY = syscall.O_RDONLY; // open the file read-only. O_RDONLY = syscall.O_RDONLY // open the file read-only.
O_WRONLY = syscall.O_WRONLY; // open the file write-only. O_WRONLY = syscall.O_WRONLY // open the file write-only.
O_RDWR = syscall.O_RDWR; // open the file read-write. O_RDWR = syscall.O_RDWR // open the file read-write.
O_APPEND = syscall.O_APPEND; // open the file append-only. O_APPEND = syscall.O_APPEND // open the file append-only.
O_ASYNC = syscall.O_ASYNC; // generate a signal when I/O is available. O_ASYNC = syscall.O_ASYNC // generate a signal when I/O is available.
O_CREAT = syscall.O_CREAT; // create a new file if none exists. O_CREAT = syscall.O_CREAT // create a new file if none exists.
O_EXCL = syscall.O_EXCL; // used with O_CREAT, file must not exist O_EXCL = syscall.O_EXCL // used with O_CREAT, file must not exist
O_NOCTTY = syscall.O_NOCTTY; // do not make file the controlling tty. O_NOCTTY = syscall.O_NOCTTY // do not make file the controlling tty.
O_NONBLOCK = syscall.O_NONBLOCK; // open in non-blocking mode. O_NONBLOCK = syscall.O_NONBLOCK // open in non-blocking mode.
O_NDELAY = O_NONBLOCK; // synonym for O_NONBLOCK O_NDELAY = O_NONBLOCK // synonym for O_NONBLOCK
O_SYNC = syscall.O_SYNC; // open for synchronous I/O. O_SYNC = syscall.O_SYNC // open for synchronous I/O.
O_TRUNC = syscall.O_TRUNC; // if possible, truncate file when opened. O_TRUNC = syscall.O_TRUNC // if possible, truncate file when opened.
O_CREATE = O_CREAT; // create a new file if none exists. O_CREATE = O_CREAT // create a new file if none exists.
) )
// Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.) // Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
// if applicable. If successful, methods on the returned File can be used for I/O. // if applicable. If successful, methods on the returned File can be used for I/O.
// It returns the File and an Error, if any. // It returns the File and an Error, if any.
func Open(name string, flag int, perm int) (file *File, err Error) { func Open(name string, flag int, perm int) (file *File, err Error) {
r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm); r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
if e != 0 { if e != 0 {
return nil, &PathError{"open", name, Errno(e)} return nil, &PathError{"open", name, Errno(e)}
} }
// There's a race here with fork/exec, which we are // There's a race here with fork/exec, which we are
// content to live with. See ../syscall/exec.go // content to live with. See ../syscall/exec.go
if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported
syscall.CloseOnExec(r) syscall.CloseOnExec(r)
} }
return NewFile(r, name), nil; return NewFile(r, name), nil
} }
// Close closes the File, rendering it unusable for I/O. // Close closes the File, rendering it unusable for I/O.
@ -89,17 +89,17 @@ func (file *File) Close() Error {
if file == nil { if file == nil {
return EINVAL return EINVAL
} }
var err Error; var err Error
if e := syscall.Close(file.fd); e != 0 { if e := syscall.Close(file.fd); e != 0 {
err = &PathError{"close", file.name, Errno(e)} err = &PathError{"close", file.name, Errno(e)}
} }
file.fd = -1; // so it can't be closed again file.fd = -1 // so it can't be closed again
return err; return err
} }
type eofError int type eofError int
func (eofError) String() string { return "EOF" } func (eofError) String() string { return "EOF" }
// EOF is the Error returned by Read when no more input is available. // EOF is the Error returned by Read when no more input is available.
// Functions should return EOF only to signal a graceful end of input. // Functions should return EOF only to signal a graceful end of input.
@ -115,7 +115,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
if file == nil { if file == nil {
return 0, EINVAL return 0, EINVAL
} }
n, e := syscall.Read(file.fd, b); n, e := syscall.Read(file.fd, b)
if n < 0 { if n < 0 {
n = 0 n = 0
} }
@ -125,7 +125,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
if e != 0 { if e != 0 {
err = &PathError{"read", file.name, Errno(e)} err = &PathError{"read", file.name, Errno(e)}
} }
return n, err; return n, err
} }
// ReadAt reads len(b) bytes from the File starting at byte offset off. // ReadAt reads len(b) bytes from the File starting at byte offset off.
@ -137,19 +137,19 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
return 0, EINVAL return 0, EINVAL
} }
for len(b) > 0 { for len(b) > 0 {
m, e := syscall.Pread(file.fd, b, off); m, e := syscall.Pread(file.fd, b, off)
if m == 0 && e == 0 { if m == 0 && e == 0 {
return n, EOF return n, EOF
} }
if e != 0 { if e != 0 {
err = &PathError{"read", file.name, Errno(e)}; err = &PathError{"read", file.name, Errno(e)}
break; break
} }
n += m; n += m
b = b[m:]; b = b[m:]
off += int64(m); off += int64(m)
} }
return; return
} }
// Write writes len(b) bytes to the File. // Write writes len(b) bytes to the File.
@ -159,12 +159,12 @@ func (file *File) Write(b []byte) (n int, err Error) {
if file == nil { if file == nil {
return 0, EINVAL return 0, EINVAL
} }
n, e := syscall.Write(file.fd, b); n, e := syscall.Write(file.fd, b)
if n < 0 { if n < 0 {
n = 0 n = 0
} }
if e == syscall.EPIPE { if e == syscall.EPIPE {
file.nepipe++; file.nepipe++
if file.nepipe >= 10 { if file.nepipe >= 10 {
Exit(syscall.EPIPE) Exit(syscall.EPIPE)
} }
@ -174,7 +174,7 @@ func (file *File) Write(b []byte) (n int, err Error) {
if e != 0 { if e != 0 {
err = &PathError{"write", file.name, Errno(e)} err = &PathError{"write", file.name, Errno(e)}
} }
return n, err; return n, err
} }
// WriteAt writes len(b) bytes to the File starting at byte offset off. // WriteAt writes len(b) bytes to the File starting at byte offset off.
@ -185,16 +185,16 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
return 0, EINVAL return 0, EINVAL
} }
for len(b) > 0 { for len(b) > 0 {
m, e := syscall.Pwrite(file.fd, b, off); m, e := syscall.Pwrite(file.fd, b, off)
if e != 0 { if e != 0 {
err = &PathError{"write", file.name, Errno(e)}; err = &PathError{"write", file.name, Errno(e)}
break; break
} }
n += m; n += m
b = b[m:]; b = b[m:]
off += int64(m); off += int64(m)
} }
return; return
} }
// Seek sets the offset for the next Read or Write on file to offset, interpreted // Seek sets the offset for the next Read or Write on file to offset, interpreted
@ -202,14 +202,14 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
// relative to the current offset, and 2 means relative to the end. // relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an Error, if any. // It returns the new offset and an Error, if any.
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) { func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
r, e := syscall.Seek(file.fd, offset, whence); r, e := syscall.Seek(file.fd, offset, whence)
if e == 0 && file.dirinfo != nil && r != 0 { if e == 0 && file.dirinfo != nil && r != 0 {
e = syscall.EISDIR e = syscall.EISDIR
} }
if e != 0 { if e != 0 {
return 0, &PathError{"seek", file.name, Errno(e)} return 0, &PathError{"seek", file.name, Errno(e)}
} }
return r, nil; return r, nil
} }
// WriteString is like Write, but writes the contents of string s rather than // WriteString is like Write, but writes the contents of string s rather than
@ -218,38 +218,38 @@ func (file *File) WriteString(s string) (ret int, err Error) {
if file == nil { if file == nil {
return 0, EINVAL return 0, EINVAL
} }
b := syscall.StringByteSlice(s); b := syscall.StringByteSlice(s)
b = b[0 : len(b)-1]; b = b[0 : len(b)-1]
return file.Write(b); return file.Write(b)
} }
// Pipe returns a connected pair of Files; reads from r return bytes written to w. // Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an Error, if any. // It returns the files and an Error, if any.
func Pipe() (r *File, w *File, err Error) { func Pipe() (r *File, w *File, err Error) {
var p [2]int; var p [2]int
// See ../syscall/exec.go for description of lock. // See ../syscall/exec.go for description of lock.
syscall.ForkLock.RLock(); syscall.ForkLock.RLock()
e := syscall.Pipe(&p); e := syscall.Pipe(&p)
if e != 0 { if e != 0 {
syscall.ForkLock.RUnlock(); syscall.ForkLock.RUnlock()
return nil, nil, NewSyscallError("pipe", e); return nil, nil, NewSyscallError("pipe", e)
} }
syscall.CloseOnExec(p[0]); syscall.CloseOnExec(p[0])
syscall.CloseOnExec(p[1]); syscall.CloseOnExec(p[1])
syscall.ForkLock.RUnlock(); syscall.ForkLock.RUnlock()
return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil; return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
} }
// Mkdir creates a new directory with the specified name and permission bits. // Mkdir creates a new directory with the specified name and permission bits.
// It returns an error, if any. // It returns an error, if any.
func Mkdir(name string, perm int) Error { func Mkdir(name string, perm int) Error {
e := syscall.Mkdir(name, perm); e := syscall.Mkdir(name, perm)
if e != 0 { if e != 0 {
return &PathError{"mkdir", name, Errno(e)} return &PathError{"mkdir", name, Errno(e)}
} }
return nil; return nil
} }
// Stat returns a Dir structure describing the named file and an error, if any. // Stat returns a Dir structure describing the named file and an error, if any.
@ -258,42 +258,42 @@ func Mkdir(name string, perm int) Error {
// If name names an invalid symbolic link, the returned Dir describes // If name names an invalid symbolic link, the returned Dir describes
// the link itself and has dir.FollowedSymlink set to false. // the link itself and has dir.FollowedSymlink set to false.
func Stat(name string) (dir *Dir, err Error) { func Stat(name string) (dir *Dir, err Error) {
var lstat, stat syscall.Stat_t; var lstat, stat syscall.Stat_t
e := syscall.Lstat(name, &lstat); e := syscall.Lstat(name, &lstat)
if e != 0 { if e != 0 {
return nil, &PathError{"stat", name, Errno(e)} return nil, &PathError{"stat", name, Errno(e)}
} }
statp := &lstat; statp := &lstat
if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK { if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
e := syscall.Stat(name, &stat); e := syscall.Stat(name, &stat)
if e == 0 { if e == 0 {
statp = &stat statp = &stat
} }
} }
return dirFromStat(name, new(Dir), &lstat, statp), nil; return dirFromStat(name, new(Dir), &lstat, statp), nil
} }
// Stat returns the Dir structure describing file. // Stat returns the Dir structure describing file.
// It returns the Dir and an error, if any. // It returns the Dir and an error, if any.
func (file *File) Stat() (dir *Dir, err Error) { func (file *File) Stat() (dir *Dir, err Error) {
var stat syscall.Stat_t; var stat syscall.Stat_t
e := syscall.Fstat(file.fd, &stat); e := syscall.Fstat(file.fd, &stat)
if e != 0 { if e != 0 {
return nil, &PathError{"stat", file.name, Errno(e)} return nil, &PathError{"stat", file.name, Errno(e)}
} }
return dirFromStat(file.name, new(Dir), &stat, &stat), nil; return dirFromStat(file.name, new(Dir), &stat, &stat), nil
} }
// Lstat returns the Dir structure describing the named file and an error, if any. // Lstat returns the Dir structure describing the named file and an error, if any.
// If the file is a symbolic link, the returned Dir describes the // If the file is a symbolic link, the returned Dir describes the
// symbolic link. Lstat makes no attempt to follow the link. // symbolic link. Lstat makes no attempt to follow the link.
func Lstat(name string) (dir *Dir, err Error) { func Lstat(name string) (dir *Dir, err Error) {
var stat syscall.Stat_t; var stat syscall.Stat_t
e := syscall.Lstat(name, &stat); e := syscall.Lstat(name, &stat)
if e != 0 { if e != 0 {
return nil, &PathError{"lstat", name, Errno(e)} return nil, &PathError{"lstat", name, Errno(e)}
} }
return dirFromStat(name, new(Dir), &stat, &stat), nil; return dirFromStat(name, new(Dir), &stat, &stat), nil
} }
// Readdir reads the contents of the directory associated with file and // Readdir reads the contents of the directory associated with file and
@ -302,25 +302,25 @@ func Lstat(name string) (dir *Dir, err Error) {
// A negative count means to read until EOF. // A negative count means to read until EOF.
// Readdir returns the array and an Error, if any. // Readdir returns the array and an Error, if any.
func (file *File) Readdir(count int) (dirs []Dir, err Error) { func (file *File) Readdir(count int) (dirs []Dir, err Error) {
dirname := file.name; dirname := file.name
if dirname == "" { if dirname == "" {
dirname = "." dirname = "."
} }
dirname += "/"; dirname += "/"
names, err1 := file.Readdirnames(count); names, err1 := file.Readdirnames(count)
if err1 != nil { if err1 != nil {
return nil, err1 return nil, err1
} }
dirs = make([]Dir, len(names)); dirs = make([]Dir, len(names))
for i, filename := range names { for i, filename := range names {
dirp, err := Lstat(dirname + filename); dirp, err := Lstat(dirname + filename)
if dirp == nil || err != nil { if dirp == nil || err != nil {
dirs[i].Name = filename // rest is already zeroed out dirs[i].Name = filename // rest is already zeroed out
} else { } else {
dirs[i] = *dirp dirs[i] = *dirp
} }
} }
return; return
} }
// Chdir changes the current working directory to the named directory. // Chdir changes the current working directory to the named directory.
@ -328,7 +328,7 @@ func Chdir(dir string) Error {
if e := syscall.Chdir(dir); e != 0 { if e := syscall.Chdir(dir); e != 0 {
return &PathError{"chdir", dir, Errno(e)} return &PathError{"chdir", dir, Errno(e)}
} }
return nil; return nil
} }
// Chdir changes the current working directory to the file, // Chdir changes the current working directory to the file,
@ -337,7 +337,7 @@ func (f *File) Chdir() Error {
if e := syscall.Fchdir(f.fd); e != 0 { if e := syscall.Fchdir(f.fd); e != 0 {
return &PathError{"chdir", f.name, Errno(e)} return &PathError{"chdir", f.name, Errno(e)}
} }
return nil; return nil
} }
// Remove removes the named file or directory. // Remove removes the named file or directory.
@ -346,11 +346,11 @@ func Remove(name string) Error {
// whether name is a file or directory. // whether name is a file or directory.
// Try both: it is cheaper on average than // Try both: it is cheaper on average than
// doing a Stat plus the right one. // doing a Stat plus the right one.
e := syscall.Unlink(name); e := syscall.Unlink(name)
if e == 0 { if e == 0 {
return nil return nil
} }
e1 := syscall.Rmdir(name); e1 := syscall.Rmdir(name)
if e1 == 0 { if e1 == 0 {
return nil return nil
} }
@ -367,16 +367,16 @@ func Remove(name string) Error {
if e1 != syscall.ENOTDIR { if e1 != syscall.ENOTDIR {
e = e1 e = e1
} }
return &PathError{"remove", name, Errno(e)}; return &PathError{"remove", name, Errno(e)}
} }
// LinkError records an error during a link or symlink or rename // LinkError records an error during a link or symlink or rename
// system call and the paths that caused it. // system call and the paths that caused it.
type LinkError struct { type LinkError struct {
Op string; Op string
Old string; Old string
New string; New string
Error Error; Error Error
} }
func (e *LinkError) String() string { func (e *LinkError) String() string {
@ -385,28 +385,28 @@ func (e *LinkError) String() string {
// Link creates a hard link. // Link creates a hard link.
func Link(oldname, newname string) Error { func Link(oldname, newname string) Error {
e := syscall.Link(oldname, newname); e := syscall.Link(oldname, newname)
if e != 0 { if e != 0 {
return &LinkError{"link", oldname, newname, Errno(e)} return &LinkError{"link", oldname, newname, Errno(e)}
} }
return nil; return nil
} }
// Symlink creates a symbolic link. // Symlink creates a symbolic link.
func Symlink(oldname, newname string) Error { func Symlink(oldname, newname string) Error {
e := syscall.Symlink(oldname, newname); e := syscall.Symlink(oldname, newname)
if e != 0 { if e != 0 {
return &LinkError{"symlink", oldname, newname, Errno(e)} return &LinkError{"symlink", oldname, newname, Errno(e)}
} }
return nil; return nil
} }
// Readlink reads the contents of a symbolic link: the destination of // Readlink reads the contents of a symbolic link: the destination of
// the link. It returns the contents and an Error, if any. // the link. It returns the contents and an Error, if any.
func Readlink(name string) (string, Error) { func Readlink(name string) (string, Error) {
for len := 128; ; len *= 2 { for len := 128; ; len *= 2 {
b := make([]byte, len); b := make([]byte, len)
n, e := syscall.Readlink(name, b); n, e := syscall.Readlink(name, b)
if e != 0 { if e != 0 {
return "", &PathError{"readlink", name, Errno(e)} return "", &PathError{"readlink", name, Errno(e)}
} }
@ -415,16 +415,16 @@ func Readlink(name string) (string, Error) {
} }
} }
// Silence 6g. // Silence 6g.
return "", nil; return "", nil
} }
// Rename renames a file. // Rename renames a file.
func Rename(oldname, newname string) Error { func Rename(oldname, newname string) Error {
e := syscall.Rename(oldname, newname); e := syscall.Rename(oldname, newname)
if e != 0 { if e != 0 {
return &LinkError{"rename", oldname, newname, Errno(e)} return &LinkError{"rename", oldname, newname, Errno(e)}
} }
return nil; return nil
} }
// Chmod changes the mode of the named file to mode. // Chmod changes the mode of the named file to mode.
@ -433,7 +433,7 @@ func Chmod(name string, mode int) Error {
if e := syscall.Chmod(name, mode); e != 0 { if e := syscall.Chmod(name, mode); e != 0 {
return &PathError{"chmod", name, Errno(e)} return &PathError{"chmod", name, Errno(e)}
} }
return nil; return nil
} }
// Chmod changes the mode of the file to mode. // Chmod changes the mode of the file to mode.
@ -441,7 +441,7 @@ func (f *File) Chmod(mode int) Error {
if e := syscall.Fchmod(f.fd, mode); e != 0 { if e := syscall.Fchmod(f.fd, mode); e != 0 {
return &PathError{"chmod", f.name, Errno(e)} return &PathError{"chmod", f.name, Errno(e)}
} }
return nil; return nil
} }
// Chown changes the numeric uid and gid of the named file. // Chown changes the numeric uid and gid of the named file.
@ -450,7 +450,7 @@ func Chown(name string, uid, gid int) Error {
if e := syscall.Chown(name, uid, gid); e != 0 { if e := syscall.Chown(name, uid, gid); e != 0 {
return &PathError{"chown", name, Errno(e)} return &PathError{"chown", name, Errno(e)}
} }
return nil; return nil
} }
// Lchown changes the numeric uid and gid of the named file. // Lchown changes the numeric uid and gid of the named file.
@ -459,7 +459,7 @@ func Lchown(name string, uid, gid int) Error {
if e := syscall.Lchown(name, uid, gid); e != 0 { if e := syscall.Lchown(name, uid, gid); e != 0 {
return &PathError{"lchown", name, Errno(e)} return &PathError{"lchown", name, Errno(e)}
} }
return nil; return nil
} }
// Chown changes the numeric uid and gid of the named file. // Chown changes the numeric uid and gid of the named file.
@ -467,7 +467,7 @@ func (f *File) Chown(uid, gid int) Error {
if e := syscall.Fchown(f.fd, uid, gid); e != 0 { if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
return &PathError{"chown", f.name, Errno(e)} return &PathError{"chown", f.name, Errno(e)}
} }
return nil; return nil
} }
// Truncate changes the size of the named file. // Truncate changes the size of the named file.
@ -476,7 +476,7 @@ func Truncate(name string, size int64) Error {
if e := syscall.Truncate(name, size); e != 0 { if e := syscall.Truncate(name, size); e != 0 {
return &PathError{"truncate", name, Errno(e)} return &PathError{"truncate", name, Errno(e)}
} }
return nil; return nil
} }
// Truncate changes the size of the file. // Truncate changes the size of the file.
@ -485,5 +485,5 @@ func (f *File) Truncate(size int64) Error {
if e := syscall.Ftruncate(f.fd, size); e != 0 { if e := syscall.Ftruncate(f.fd, size); e != 0 {
return &PathError{"truncate", f.name, Errno(e)} return &PathError{"truncate", f.name, Errno(e)}
} }
return nil; return nil
} }

View File

@ -5,7 +5,7 @@
package os package os
import ( import (
"syscall"; "syscall"
) )
// Getwd returns a rooted path name corresponding to the // Getwd returns a rooted path name corresponding to the
@ -15,21 +15,21 @@ import (
func Getwd() (string, Error) { func Getwd() (string, Error) {
// If the operating system provides a Getwd call, use it. // If the operating system provides a Getwd call, use it.
if syscall.ImplementsGetwd { if syscall.ImplementsGetwd {
s, e := syscall.Getwd(); s, e := syscall.Getwd()
return s, NewSyscallError("getwd", e); return s, NewSyscallError("getwd", e)
} }
// Otherwise, we're trying to find our way back to ".". // Otherwise, we're trying to find our way back to ".".
dot, err := Stat("."); dot, err := Stat(".")
if err != nil { if err != nil {
return "", err return "", err
} }
// Clumsy but widespread kludge: // Clumsy but widespread kludge:
// if $PWD is set and matches ".", use it. // if $PWD is set and matches ".", use it.
pwd := Getenv("PWD"); pwd := Getenv("PWD")
if len(pwd) > 0 && pwd[0] == '/' { if len(pwd) > 0 && pwd[0] == '/' {
d, err := Stat(pwd); d, err := Stat(pwd)
if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino { if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino {
return pwd, nil return pwd, nil
} }
@ -37,7 +37,7 @@ func Getwd() (string, Error) {
// Root is a special case because it has no parent // Root is a special case because it has no parent
// and ends in a slash. // and ends in a slash.
root, err := Stat("/"); root, err := Stat("/")
if err != nil { if err != nil {
// Can't stat root - no hope. // Can't stat root - no hope.
return "", err return "", err
@ -49,44 +49,44 @@ func Getwd() (string, Error) {
// General algorithm: find name in parent // General algorithm: find name in parent
// and then find name of parent. Each iteration // and then find name of parent. Each iteration
// adds /name to the beginning of pwd. // adds /name to the beginning of pwd.
pwd = ""; pwd = ""
for parent := ".."; ; parent = "../" + parent { for parent := ".."; ; parent = "../" + parent {
if len(parent) >= 1024 { // Sanity check if len(parent) >= 1024 { // Sanity check
return "", ENAMETOOLONG return "", ENAMETOOLONG
} }
fd, err := Open(parent, O_RDONLY, 0); fd, err := Open(parent, O_RDONLY, 0)
if err != nil { if err != nil {
return "", err return "", err
} }
for { for {
names, err := fd.Readdirnames(100); names, err := fd.Readdirnames(100)
if err != nil { if err != nil {
fd.Close(); fd.Close()
return "", err; return "", err
} }
for _, name := range names { for _, name := range names {
d, _ := Lstat(parent + "/" + name); d, _ := Lstat(parent + "/" + name)
if d.Dev == dot.Dev && d.Ino == dot.Ino { if d.Dev == dot.Dev && d.Ino == dot.Ino {
pwd = "/" + name + pwd; pwd = "/" + name + pwd
goto Found; goto Found
} }
} }
} }
fd.Close(); fd.Close()
return "", ENOENT; return "", ENOENT
Found: Found:
pd, err := fd.Stat(); pd, err := fd.Stat()
if err != nil { if err != nil {
return "", err return "", err
} }
fd.Close(); fd.Close()
if pd.Dev == root.Dev && pd.Ino == root.Ino { if pd.Dev == root.Dev && pd.Ino == root.Ino {
break break
} }
// Set up for next round. // Set up for next round.
dot = pd; dot = pd
} }
return pwd, nil; return pwd, nil
} }

View File

@ -5,13 +5,13 @@
package os_test package os_test
import ( import (
"bytes"; "bytes"
"fmt"; "fmt"
"io"; "io"
"io/ioutil"; "io/ioutil"
. "os"; . "os"
"strings"; "strings"
"testing"; "testing"
) )
var dot = []string{ var dot = []string{
@ -34,16 +34,16 @@ var etc = []string{
} }
func size(name string, t *testing.T) uint64 { func size(name string, t *testing.T) uint64 {
file, err := Open(name, O_RDONLY, 0); file, err := Open(name, O_RDONLY, 0)
defer file.Close(); defer file.Close()
if err != nil { if err != nil {
t.Fatal("open failed:", err) t.Fatal("open failed:", err)
} }
var buf [100]byte; var buf [100]byte
len := 0; len := 0
for { for {
n, e := file.Read(&buf); n, e := file.Read(&buf)
len += n; len += n
if e == EOF { if e == EOF {
break break
} }
@ -51,68 +51,68 @@ func size(name string, t *testing.T) uint64 {
t.Fatal("read failed:", err) t.Fatal("read failed:", err)
} }
} }
return uint64(len); return uint64(len)
} }
func TestStat(t *testing.T) { func TestStat(t *testing.T) {
dir, err := Stat("/etc/passwd"); dir, err := Stat("/etc/passwd")
if err != nil { if err != nil {
t.Fatal("stat failed:", err) t.Fatal("stat failed:", err)
} }
if dir.Name != "passwd" { if dir.Name != "passwd" {
t.Error("name should be passwd; is", dir.Name) t.Error("name should be passwd; is", dir.Name)
} }
filesize := size("/etc/passwd", t); filesize := size("/etc/passwd", t)
if dir.Size != filesize { if dir.Size != filesize {
t.Error("size should be", filesize, "; is", dir.Size) t.Error("size should be", filesize, "; is", dir.Size)
} }
} }
func TestFstat(t *testing.T) { func TestFstat(t *testing.T) {
file, err1 := Open("/etc/passwd", O_RDONLY, 0); file, err1 := Open("/etc/passwd", O_RDONLY, 0)
defer file.Close(); defer file.Close()
if err1 != nil { if err1 != nil {
t.Fatal("open failed:", err1) t.Fatal("open failed:", err1)
} }
dir, err2 := file.Stat(); dir, err2 := file.Stat()
if err2 != nil { if err2 != nil {
t.Fatal("fstat failed:", err2) t.Fatal("fstat failed:", err2)
} }
if dir.Name != "passwd" { if dir.Name != "passwd" {
t.Error("name should be passwd; is", dir.Name) t.Error("name should be passwd; is", dir.Name)
} }
filesize := size("/etc/passwd", t); filesize := size("/etc/passwd", t)
if dir.Size != filesize { if dir.Size != filesize {
t.Error("size should be", filesize, "; is", dir.Size) t.Error("size should be", filesize, "; is", dir.Size)
} }
} }
func TestLstat(t *testing.T) { func TestLstat(t *testing.T) {
dir, err := Lstat("/etc/passwd"); dir, err := Lstat("/etc/passwd")
if err != nil { if err != nil {
t.Fatal("lstat failed:", err) t.Fatal("lstat failed:", err)
} }
if dir.Name != "passwd" { if dir.Name != "passwd" {
t.Error("name should be passwd; is", dir.Name) t.Error("name should be passwd; is", dir.Name)
} }
filesize := size("/etc/passwd", t); filesize := size("/etc/passwd", t)
if dir.Size != filesize { if dir.Size != filesize {
t.Error("size should be", filesize, "; is", dir.Size) t.Error("size should be", filesize, "; is", dir.Size)
} }
} }
func testReaddirnames(dir string, contents []string, t *testing.T) { func testReaddirnames(dir string, contents []string, t *testing.T) {
file, err := Open(dir, O_RDONLY, 0); file, err := Open(dir, O_RDONLY, 0)
defer file.Close(); defer file.Close()
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", dir, err) t.Fatalf("open %q failed: %v", dir, err)
} }
s, err2 := file.Readdirnames(-1); s, err2 := file.Readdirnames(-1)
if err2 != nil { if err2 != nil {
t.Fatalf("readdirnames %q failed: %v", err2) t.Fatalf("readdirnames %q failed: %v", err2)
} }
for _, m := range contents { for _, m := range contents {
found := false; found := false
for _, n := range s { for _, n := range s {
if n == "." || n == ".." { if n == "." || n == ".." {
t.Errorf("got %s in directory", n) t.Errorf("got %s in directory", n)
@ -121,7 +121,7 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
if found { if found {
t.Error("present twice:", m) t.Error("present twice:", m)
} }
found = true; found = true
} }
} }
if !found { if !found {
@ -131,23 +131,23 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
} }
func testReaddir(dir string, contents []string, t *testing.T) { func testReaddir(dir string, contents []string, t *testing.T) {
file, err := Open(dir, O_RDONLY, 0); file, err := Open(dir, O_RDONLY, 0)
defer file.Close(); defer file.Close()
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", dir, err) t.Fatalf("open %q failed: %v", dir, err)
} }
s, err2 := file.Readdir(-1); s, err2 := file.Readdir(-1)
if err2 != nil { if err2 != nil {
t.Fatalf("readdir %q failed: %v", dir, err2) t.Fatalf("readdir %q failed: %v", dir, err2)
} }
for _, m := range contents { for _, m := range contents {
found := false; found := false
for _, n := range s { for _, n := range s {
if m == n.Name { if m == n.Name {
if found { if found {
t.Error("present twice:", m) t.Error("present twice:", m)
} }
found = true; found = true
} }
} }
if !found { if !found {
@ -157,51 +157,51 @@ func testReaddir(dir string, contents []string, t *testing.T) {
} }
func TestReaddirnames(t *testing.T) { func TestReaddirnames(t *testing.T) {
testReaddirnames(".", dot, t); testReaddirnames(".", dot, t)
testReaddirnames("/etc", etc, t); testReaddirnames("/etc", etc, t)
} }
func TestReaddir(t *testing.T) { func TestReaddir(t *testing.T) {
testReaddir(".", dot, t); testReaddir(".", dot, t)
testReaddir("/etc", etc, t); testReaddir("/etc", etc, t)
} }
// Read the directory one entry at a time. // Read the directory one entry at a time.
func smallReaddirnames(file *File, length int, t *testing.T) []string { func smallReaddirnames(file *File, length int, t *testing.T) []string {
names := make([]string, length); names := make([]string, length)
count := 0; count := 0
for { for {
d, err := file.Readdirnames(1); d, err := file.Readdirnames(1)
if err != nil { if err != nil {
t.Fatalf("readdir %q failed: %v", file.Name(), err) t.Fatalf("readdir %q failed: %v", file.Name(), err)
} }
if len(d) == 0 { if len(d) == 0 {
break break
} }
names[count] = d[0]; names[count] = d[0]
count++; count++
} }
return names[0:count]; return names[0:count]
} }
// Check that reading a directory one entry at a time gives the same result // Check that reading a directory one entry at a time gives the same result
// as reading it all at once. // as reading it all at once.
func TestReaddirnamesOneAtATime(t *testing.T) { func TestReaddirnamesOneAtATime(t *testing.T) {
dir := "/usr/bin"; // big directory that doesn't change often. dir := "/usr/bin" // big directory that doesn't change often.
file, err := Open(dir, O_RDONLY, 0); file, err := Open(dir, O_RDONLY, 0)
defer file.Close(); defer file.Close()
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", dir, err) t.Fatalf("open %q failed: %v", dir, err)
} }
all, err1 := file.Readdirnames(-1); all, err1 := file.Readdirnames(-1)
if err1 != nil { if err1 != nil {
t.Fatalf("readdirnames %q failed: %v", dir, err1) t.Fatalf("readdirnames %q failed: %v", dir, err1)
} }
file1, err2 := Open(dir, O_RDONLY, 0); file1, err2 := Open(dir, O_RDONLY, 0)
if err2 != nil { if err2 != nil {
t.Fatalf("open %q failed: %v", dir, err2) t.Fatalf("open %q failed: %v", dir, err2)
} }
small := smallReaddirnames(file1, len(all)+100, t); // +100 in case we screw up small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
for i, n := range all { for i, n := range all {
if small[i] != n { if small[i] != n {
t.Errorf("small read %q %q mismatch: %v", small[i], n) t.Errorf("small read %q %q mismatch: %v", small[i], n)
@ -210,26 +210,26 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
} }
func TestHardLink(t *testing.T) { func TestHardLink(t *testing.T) {
from, to := "hardlinktestfrom", "hardlinktestto"; from, to := "hardlinktestfrom", "hardlinktestto"
Remove(from); // Just in case. Remove(from) // Just in case.
file, err := Open(to, O_CREAT|O_WRONLY, 0666); file, err := Open(to, O_CREAT|O_WRONLY, 0666)
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", to, err) t.Fatalf("open %q failed: %v", to, err)
} }
defer Remove(to); defer Remove(to)
if err = file.Close(); err != nil { if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", to, err) t.Errorf("close %q failed: %v", to, err)
} }
err = Link(to, from); err = Link(to, from)
if err != nil { if err != nil {
t.Fatalf("link %q, %q failed: %v", to, from, err) t.Fatalf("link %q, %q failed: %v", to, from, err)
} }
defer Remove(from); defer Remove(from)
tostat, err := Stat(to); tostat, err := Stat(to)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", to, err) t.Fatalf("stat %q failed: %v", to, err)
} }
fromstat, err := Stat(from); fromstat, err := Stat(from)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", from, err) t.Fatalf("stat %q failed: %v", from, err)
} }
@ -239,74 +239,74 @@ func TestHardLink(t *testing.T) {
} }
func TestSymLink(t *testing.T) { func TestSymLink(t *testing.T) {
from, to := "symlinktestfrom", "symlinktestto"; from, to := "symlinktestfrom", "symlinktestto"
Remove(from); // Just in case. Remove(from) // Just in case.
file, err := Open(to, O_CREAT|O_WRONLY, 0666); file, err := Open(to, O_CREAT|O_WRONLY, 0666)
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", to, err) t.Fatalf("open %q failed: %v", to, err)
} }
defer Remove(to); defer Remove(to)
if err = file.Close(); err != nil { if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", to, err) t.Errorf("close %q failed: %v", to, err)
} }
err = Symlink(to, from); err = Symlink(to, from)
if err != nil { if err != nil {
t.Fatalf("symlink %q, %q failed: %v", to, from, err) t.Fatalf("symlink %q, %q failed: %v", to, from, err)
} }
defer Remove(from); defer Remove(from)
tostat, err := Stat(to); tostat, err := Stat(to)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", to, err) t.Fatalf("stat %q failed: %v", to, err)
} }
if tostat.FollowedSymlink { if tostat.FollowedSymlink {
t.Fatalf("stat %q claims to have followed a symlink", to) t.Fatalf("stat %q claims to have followed a symlink", to)
} }
fromstat, err := Stat(from); fromstat, err := Stat(from)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", from, err) t.Fatalf("stat %q failed: %v", from, err)
} }
if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino { if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
t.Errorf("symlink %q, %q did not create symlink", to, from) t.Errorf("symlink %q, %q did not create symlink", to, from)
} }
fromstat, err = Lstat(from); fromstat, err = Lstat(from)
if err != nil { if err != nil {
t.Fatalf("lstat %q failed: %v", from, err) t.Fatalf("lstat %q failed: %v", from, err)
} }
if !fromstat.IsSymlink() { if !fromstat.IsSymlink() {
t.Fatalf("symlink %q, %q did not create symlink", to, from) t.Fatalf("symlink %q, %q did not create symlink", to, from)
} }
fromstat, err = Stat(from); fromstat, err = Stat(from)
if err != nil { if err != nil {
t.Fatalf("stat %q failed: %v", from, err) t.Fatalf("stat %q failed: %v", from, err)
} }
if !fromstat.FollowedSymlink { if !fromstat.FollowedSymlink {
t.Fatalf("stat %q did not follow symlink") t.Fatalf("stat %q did not follow symlink")
} }
s, err := Readlink(from); s, err := Readlink(from)
if err != nil { if err != nil {
t.Fatalf("readlink %q failed: %v", from, err) t.Fatalf("readlink %q failed: %v", from, err)
} }
if s != to { if s != to {
t.Fatalf("after symlink %q != %q", s, to) t.Fatalf("after symlink %q != %q", s, to)
} }
file, err = Open(from, O_RDONLY, 0); file, err = Open(from, O_RDONLY, 0)
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", from, err) t.Fatalf("open %q failed: %v", from, err)
} }
file.Close(); file.Close()
} }
func TestLongSymlink(t *testing.T) { func TestLongSymlink(t *testing.T) {
s := "0123456789abcdef"; s := "0123456789abcdef"
// Long, but not too long: a common limit is 255. // Long, but not too long: a common limit is 255.
s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s; s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
from := "longsymlinktestfrom"; from := "longsymlinktestfrom"
err := Symlink(s, from); err := Symlink(s, from)
if err != nil { if err != nil {
t.Fatalf("symlink %q, %q failed: %v", s, from, err) t.Fatalf("symlink %q, %q failed: %v", s, from, err)
} }
defer Remove(from); defer Remove(from)
r, err := Readlink(from); r, err := Readlink(from)
if err != nil { if err != nil {
t.Fatalf("readlink %q failed: %v", from, err) t.Fatalf("readlink %q failed: %v", from, err)
} }
@ -316,49 +316,49 @@ func TestLongSymlink(t *testing.T) {
} }
func TestRename(t *testing.T) { func TestRename(t *testing.T) {
from, to := "renamefrom", "renameto"; from, to := "renamefrom", "renameto"
Remove(to); // Just in case. Remove(to) // Just in case.
file, err := Open(from, O_CREAT|O_WRONLY, 0666); file, err := Open(from, O_CREAT|O_WRONLY, 0666)
if err != nil { if err != nil {
t.Fatalf("open %q failed: %v", to, err) t.Fatalf("open %q failed: %v", to, err)
} }
if err = file.Close(); err != nil { if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", to, err) t.Errorf("close %q failed: %v", to, err)
} }
err = Rename(from, to); err = Rename(from, to)
if err != nil { if err != nil {
t.Fatalf("rename %q, %q failed: %v", to, from, err) t.Fatalf("rename %q, %q failed: %v", to, from, err)
} }
defer Remove(to); defer Remove(to)
_, err = Stat(to); _, err = Stat(to)
if err != nil { if err != nil {
t.Errorf("stat %q failed: %v", to, err) t.Errorf("stat %q failed: %v", to, err)
} }
} }
func TestForkExec(t *testing.T) { func TestForkExec(t *testing.T) {
r, w, err := Pipe(); r, w, err := Pipe()
if err != nil { if err != nil {
t.Fatalf("Pipe: %v", err) t.Fatalf("Pipe: %v", err)
} }
pid, err := ForkExec("/bin/pwd", []string{"pwd"}, nil, "/", []*File{nil, w, Stderr}); pid, err := ForkExec("/bin/pwd", []string{"pwd"}, nil, "/", []*File{nil, w, Stderr})
if err != nil { if err != nil {
t.Fatalf("ForkExec: %v", err) t.Fatalf("ForkExec: %v", err)
} }
w.Close(); w.Close()
var b bytes.Buffer; var b bytes.Buffer
io.Copy(&b, r); io.Copy(&b, r)
output := b.String(); output := b.String()
expect := "/\n"; expect := "/\n"
if output != expect { if output != expect {
t.Errorf("exec /bin/pwd returned %q wanted %q", output, expect) t.Errorf("exec /bin/pwd returned %q wanted %q", output, expect)
} }
Wait(pid, 0); Wait(pid, 0)
} }
func checkMode(t *testing.T, path string, mode uint32) { func checkMode(t *testing.T, path string, mode uint32) {
dir, err := Stat(path); dir, err := Stat(path)
if err != nil { if err != nil {
t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err) t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
} }
@ -368,9 +368,9 @@ func checkMode(t *testing.T, path string, mode uint32) {
} }
func TestChmod(t *testing.T) { func TestChmod(t *testing.T) {
MkdirAll("_obj", 0777); MkdirAll("_obj", 0777)
const Path = "_obj/_TestChmod_"; const Path = "_obj/_TestChmod_"
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666); fd, err := Open(Path, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %s: %s", Path, err) t.Fatalf("create %s: %s", Path, err)
} }
@ -378,19 +378,19 @@ func TestChmod(t *testing.T) {
if err = Chmod(Path, 0456); err != nil { if err = Chmod(Path, 0456); err != nil {
t.Fatalf("chmod %s 0456: %s", Path, err) t.Fatalf("chmod %s 0456: %s", Path, err)
} }
checkMode(t, Path, 0456); checkMode(t, Path, 0456)
if err = fd.Chmod(0123); err != nil { if err = fd.Chmod(0123); err != nil {
t.Fatalf("fchmod %s 0123: %s", Path, err) t.Fatalf("fchmod %s 0123: %s", Path, err)
} }
checkMode(t, Path, 0123); checkMode(t, Path, 0123)
fd.Close(); fd.Close()
Remove(Path); Remove(Path)
} }
func checkUidGid(t *testing.T, path string, uid, gid int) { func checkUidGid(t *testing.T, path string, uid, gid int) {
dir, err := Stat(path); dir, err := Stat(path)
if err != nil { if err != nil {
t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err) t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
} }
@ -408,49 +408,49 @@ func TestChown(t *testing.T) {
// on the file. If _obj is on NFS, the Getgroups groups are // on the file. If _obj is on NFS, the Getgroups groups are
// basically useless. // basically useless.
const Path = "/tmp/_TestChown_"; const Path = "/tmp/_TestChown_"
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666); fd, err := Open(Path, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %s: %s", Path, err) t.Fatalf("create %s: %s", Path, err)
} }
dir, err := fd.Stat(); dir, err := fd.Stat()
if err != nil { if err != nil {
t.Fatalf("fstat %s: %s", Path, err) t.Fatalf("fstat %s: %s", Path, err)
} }
defer fd.Close(); defer fd.Close()
defer Remove(Path); defer Remove(Path)
// Can't change uid unless root, but can try // Can't change uid unless root, but can try
// changing the group id. First try our current group. // changing the group id. First try our current group.
gid := Getgid(); gid := Getgid()
t.Log("gid:", gid); t.Log("gid:", gid)
if err = Chown(Path, -1, gid); err != nil { if err = Chown(Path, -1, gid); err != nil {
t.Fatalf("chown %s -1 %d: %s", Path, gid, err) t.Fatalf("chown %s -1 %d: %s", Path, gid, err)
} }
checkUidGid(t, Path, int(dir.Uid), gid); checkUidGid(t, Path, int(dir.Uid), gid)
// Then try all the auxiliary groups. // Then try all the auxiliary groups.
groups, err := Getgroups(); groups, err := Getgroups()
if err != nil { if err != nil {
t.Fatalf("getgroups: %s", err) t.Fatalf("getgroups: %s", err)
} }
t.Log("groups: ", groups); t.Log("groups: ", groups)
for _, g := range groups { for _, g := range groups {
if err = Chown(Path, -1, g); err != nil { if err = Chown(Path, -1, g); err != nil {
t.Fatalf("chown %s -1 %d: %s", Path, g, err) t.Fatalf("chown %s -1 %d: %s", Path, g, err)
} }
checkUidGid(t, Path, int(dir.Uid), g); checkUidGid(t, Path, int(dir.Uid), g)
// change back to gid to test fd.Chown // change back to gid to test fd.Chown
if err = fd.Chown(-1, gid); err != nil { if err = fd.Chown(-1, gid); err != nil {
t.Fatalf("fchown %s -1 %d: %s", Path, gid, err) t.Fatalf("fchown %s -1 %d: %s", Path, gid, err)
} }
checkUidGid(t, Path, int(dir.Uid), gid); checkUidGid(t, Path, int(dir.Uid), gid)
} }
} }
func checkSize(t *testing.T, path string, size uint64) { func checkSize(t *testing.T, path string, size uint64) {
dir, err := Stat(path); dir, err := Stat(path)
if err != nil { if err != nil {
t.Fatalf("Stat %q (looking for size %d): %s", path, size, err) t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
} }
@ -460,73 +460,73 @@ func checkSize(t *testing.T, path string, size uint64) {
} }
func TestTruncate(t *testing.T) { func TestTruncate(t *testing.T) {
MkdirAll("_obj", 0777); MkdirAll("_obj", 0777)
const Path = "_obj/_TestTruncate_"; const Path = "_obj/_TestTruncate_"
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666); fd, err := Open(Path, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %s: %s", Path, err) t.Fatalf("create %s: %s", Path, err)
} }
checkSize(t, Path, 0); checkSize(t, Path, 0)
fd.Write(strings.Bytes("hello, world\n")); fd.Write(strings.Bytes("hello, world\n"))
checkSize(t, Path, 13); checkSize(t, Path, 13)
fd.Truncate(10); fd.Truncate(10)
checkSize(t, Path, 10); checkSize(t, Path, 10)
fd.Truncate(1024); fd.Truncate(1024)
checkSize(t, Path, 1024); checkSize(t, Path, 1024)
fd.Truncate(0); fd.Truncate(0)
checkSize(t, Path, 0); checkSize(t, Path, 0)
fd.Write(strings.Bytes("surprise!")); fd.Write(strings.Bytes("surprise!"))
checkSize(t, Path, 13+9); // wrote at offset past where hello, world was. checkSize(t, Path, 13+9) // wrote at offset past where hello, world was.
fd.Close(); fd.Close()
Remove(Path); Remove(Path)
} }
func TestChdirAndGetwd(t *testing.T) { func TestChdirAndGetwd(t *testing.T) {
fd, err := Open(".", O_RDONLY, 0); fd, err := Open(".", O_RDONLY, 0)
if err != nil { if err != nil {
t.Fatalf("Open .: %s", err) t.Fatalf("Open .: %s", err)
} }
// These are chosen carefully not to be symlinks on a Mac // These are chosen carefully not to be symlinks on a Mac
// (unlike, say, /var, /etc, and /tmp). // (unlike, say, /var, /etc, and /tmp).
dirs := []string{"/bin", "/", "/usr/bin"}; dirs := []string{"/bin", "/", "/usr/bin"}
for mode := 0; mode < 2; mode++ { for mode := 0; mode < 2; mode++ {
for _, d := range dirs { for _, d := range dirs {
if mode == 0 { if mode == 0 {
err = Chdir(d) err = Chdir(d)
} else { } else {
fd1, err := Open(d, O_RDONLY, 0); fd1, err := Open(d, O_RDONLY, 0)
if err != nil { if err != nil {
t.Errorf("Open %s: %s", d, err); t.Errorf("Open %s: %s", d, err)
continue; continue
} }
err = fd1.Chdir(); err = fd1.Chdir()
fd1.Close(); fd1.Close()
} }
pwd, err1 := Getwd(); pwd, err1 := Getwd()
err2 := fd.Chdir(); err2 := fd.Chdir()
if err2 != nil { if err2 != nil {
// We changed the current directory and cannot go back. // We changed the current directory and cannot go back.
// Don't let the tests continue; they'll scribble // Don't let the tests continue; they'll scribble
// all over some other directory. // all over some other directory.
fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2); fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
Exit(1); Exit(1)
} }
if err != nil { if err != nil {
fd.Close(); fd.Close()
t.Fatalf("Chdir %s: %s", d, err); t.Fatalf("Chdir %s: %s", d, err)
} }
if err1 != nil { if err1 != nil {
fd.Close(); fd.Close()
t.Fatalf("Getwd in %s: %s", d, err1); t.Fatalf("Getwd in %s: %s", d, err1)
} }
if pwd != d { if pwd != d {
fd.Close(); fd.Close()
t.Fatalf("Getwd returned %q want %q", pwd, d); t.Fatalf("Getwd returned %q want %q", pwd, d)
} }
} }
} }
fd.Close(); fd.Close()
} }
func TestTime(t *testing.T) { func TestTime(t *testing.T) {
@ -536,25 +536,25 @@ func TestTime(t *testing.T) {
// filling in the structure passed to the system call. // filling in the structure passed to the system call.
// Too bad the compiler doesn't know that // Too bad the compiler doesn't know that
// 365.24*86400 is an integer. // 365.24*86400 is an integer.
sec, nsec, err := Time(); sec, nsec, err := Time()
if sec < (2009-1970)*36524*864 { if sec < (2009-1970)*36524*864 {
t.Errorf("Time() = %d, %d, %s; not plausible", sec, nsec, err) t.Errorf("Time() = %d, %d, %s; not plausible", sec, nsec, err)
} }
} }
func TestSeek(t *testing.T) { func TestSeek(t *testing.T) {
f, err := Open("_obj/seektest", O_CREAT|O_RDWR|O_TRUNC, 0666); f, err := Open("_obj/seektest", O_CREAT|O_RDWR|O_TRUNC, 0666)
if err != nil { if err != nil {
t.Fatalf("open _obj/seektest: %s", err) t.Fatalf("open _obj/seektest: %s", err)
} }
const data = "hello, world\n"; const data = "hello, world\n"
io.WriteString(f, data); io.WriteString(f, data)
type test struct { type test struct {
in int64; in int64
whence int; whence int
out int64; out int64
} }
var tests = []test{ var tests = []test{
test{0, 1, int64(len(data))}, test{0, 1, int64(len(data))},
@ -565,25 +565,25 @@ func TestSeek(t *testing.T) {
test{-1, 2, int64(len(data)) - 1}, test{-1, 2, int64(len(data)) - 1},
test{1 << 33, 0, 1 << 33}, test{1 << 33, 0, 1 << 33},
test{1 << 33, 2, 1<<33 + int64(len(data))}, test{1 << 33, 2, 1<<33 + int64(len(data))},
}; }
for i, tt := range tests { for i, tt := range tests {
off, err := f.Seek(tt.in, tt.whence); off, err := f.Seek(tt.in, tt.whence)
if off != tt.out || err != nil { if off != tt.out || err != nil {
if e, ok := err.(*PathError); ok && e.Error == EINVAL && tt.out > 1<<32 { if e, ok := err.(*PathError); ok && e.Error == EINVAL && tt.out > 1<<32 {
// Reiserfs rejects the big seeks. // Reiserfs rejects the big seeks.
// http://code.google.com/p/go/issues/detail?id=91 // http://code.google.com/p/go/issues/detail?id=91
break break
} }
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out); t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
} }
} }
f.Close(); f.Close()
} }
type openErrorTest struct { type openErrorTest struct {
path string; path string
mode int; mode int
error string; error string
} }
var openErrorTests = []openErrorTest{ var openErrorTests = []openErrorTest{
@ -606,11 +606,11 @@ var openErrorTests = []openErrorTest{
func TestOpenError(t *testing.T) { func TestOpenError(t *testing.T) {
for _, tt := range openErrorTests { for _, tt := range openErrorTests {
f, err := Open(tt.path, tt.mode, 0); f, err := Open(tt.path, tt.mode, 0)
if err == nil { if err == nil {
t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode); t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
f.Close(); f.Close()
continue; continue
} }
if s := err.String(); s != tt.error { if s := err.String(); s != tt.error {
t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, s, tt.error) t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, s, tt.error)
@ -620,20 +620,20 @@ func TestOpenError(t *testing.T) {
func run(t *testing.T, cmd []string) string { func run(t *testing.T, cmd []string) string {
// Run /bin/hostname and collect output. // Run /bin/hostname and collect output.
r, w, err := Pipe(); r, w, err := Pipe()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr}); pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
w.Close(); w.Close()
var b bytes.Buffer; var b bytes.Buffer
io.Copy(&b, r); io.Copy(&b, r)
Wait(pid, 0); Wait(pid, 0)
output := b.String(); output := b.String()
if n := len(output); n > 0 && output[n-1] == '\n' { if n := len(output); n > 0 && output[n-1] == '\n' {
output = output[0 : n-1] output = output[0 : n-1]
} }
@ -641,32 +641,32 @@ func run(t *testing.T, cmd []string) string {
t.Fatalf("%v produced no output", cmd) t.Fatalf("%v produced no output", cmd)
} }
return output; return output
} }
func TestHostname(t *testing.T) { func TestHostname(t *testing.T) {
// Check internal Hostname() against the output of /bin/hostname. // Check internal Hostname() against the output of /bin/hostname.
hostname, err := Hostname(); hostname, err := Hostname()
if err != nil { if err != nil {
t.Fatalf("%v", err) t.Fatalf("%v", err)
} }
want := run(t, []string{"/bin/hostname"}); want := run(t, []string{"/bin/hostname"})
if hostname != want { if hostname != want {
t.Errorf("Hostname() = %q, want %q", hostname, want) t.Errorf("Hostname() = %q, want %q", hostname, want)
} }
} }
func TestReadAt(t *testing.T) { func TestReadAt(t *testing.T) {
f, err := Open("_obj/readtest", O_CREAT|O_RDWR|O_TRUNC, 0666); f, err := Open("_obj/readtest", O_CREAT|O_RDWR|O_TRUNC, 0666)
if err != nil { if err != nil {
t.Fatalf("open _obj/readtest: %s", err) t.Fatalf("open _obj/readtest: %s", err)
} }
const data = "hello, world\n"; const data = "hello, world\n"
io.WriteString(f, data); io.WriteString(f, data)
b := make([]byte, 5); b := make([]byte, 5)
n, err := f.ReadAt(b, 7); n, err := f.ReadAt(b, 7)
if err != nil || n != len(b) { if err != nil || n != len(b) {
t.Fatalf("ReadAt 7: %d, %r", n, err) t.Fatalf("ReadAt 7: %d, %r", n, err)
} }
@ -676,19 +676,19 @@ func TestReadAt(t *testing.T) {
} }
func TestWriteAt(t *testing.T) { func TestWriteAt(t *testing.T) {
f, err := Open("_obj/writetest", O_CREAT|O_RDWR|O_TRUNC, 0666); f, err := Open("_obj/writetest", O_CREAT|O_RDWR|O_TRUNC, 0666)
if err != nil { if err != nil {
t.Fatalf("open _obj/writetest: %s", err) t.Fatalf("open _obj/writetest: %s", err)
} }
const data = "hello, world\n"; const data = "hello, world\n"
io.WriteString(f, data); io.WriteString(f, data)
n, err := f.WriteAt(strings.Bytes("WORLD"), 7); n, err := f.WriteAt(strings.Bytes("WORLD"), 7)
if err != nil || n != 5 { if err != nil || n != 5 {
t.Fatalf("WriteAt 7: %d, %v", n, err) t.Fatalf("WriteAt 7: %d, %v", n, err)
} }
b, err := ioutil.ReadFile("_obj/writetest"); b, err := ioutil.ReadFile("_obj/writetest")
if err != nil { if err != nil {
t.Fatalf("ReadFile _obj/writetest: %v", err) t.Fatalf("ReadFile _obj/writetest: %v", err)
} }

View File

@ -14,45 +14,45 @@ package os
// and returns nil. // and returns nil.
func MkdirAll(path string, perm int) Error { func MkdirAll(path string, perm int) Error {
// If path exists, stop with success or error. // If path exists, stop with success or error.
dir, err := Lstat(path); dir, err := Lstat(path)
if err == nil { if err == nil {
if dir.IsDirectory() { if dir.IsDirectory() {
return nil return nil
} }
return &PathError{"mkdir", path, ENOTDIR}; return &PathError{"mkdir", path, ENOTDIR}
} }
// Doesn't already exist; make sure parent does. // Doesn't already exist; make sure parent does.
i := len(path); i := len(path)
for i > 0 && path[i-1] == '/' { // Skip trailing slashes. for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
i-- i--
} }
j := i; j := i
for j > 0 && path[j-1] != '/' { // Scan backward over element. for j > 0 && path[j-1] != '/' { // Scan backward over element.
j-- j--
} }
if j > 0 { if j > 0 {
// Create parent // Create parent
err = MkdirAll(path[0:j-1], perm); err = MkdirAll(path[0:j-1], perm)
if err != nil { if err != nil {
return err return err
} }
} }
// Now parent exists, try to create. // Now parent exists, try to create.
err = Mkdir(path, perm); err = Mkdir(path, perm)
if err != nil { if err != nil {
// Handle arguments like "foo/." by // Handle arguments like "foo/." by
// double-checking that directory doesn't exist. // double-checking that directory doesn't exist.
dir, err1 := Lstat(path); dir, err1 := Lstat(path)
if err1 == nil && dir.IsDirectory() { if err1 == nil && dir.IsDirectory() {
return nil return nil
} }
return err; return err
} }
return nil; return nil
} }
// RemoveAll removes path and any children it contains. // RemoveAll removes path and any children it contains.
@ -61,18 +61,18 @@ func MkdirAll(path string, perm int) Error {
// returns nil (no error). // returns nil (no error).
func RemoveAll(path string) Error { func RemoveAll(path string) Error {
// Simple case: if Remove works, we're done. // Simple case: if Remove works, we're done.
err := Remove(path); err := Remove(path)
if err == nil { if err == nil {
return nil return nil
} }
// Otherwise, is this a directory we need to recurse into? // Otherwise, is this a directory we need to recurse into?
dir, serr := Lstat(path); dir, serr := Lstat(path)
if serr != nil { if serr != nil {
if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT { if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT {
return nil return nil
} }
return serr; return serr
} }
if !dir.IsDirectory() { if !dir.IsDirectory() {
// Not a directory; return the error from Remove. // Not a directory; return the error from Remove.
@ -80,18 +80,18 @@ func RemoveAll(path string) Error {
} }
// Directory. // Directory.
fd, err := Open(path, O_RDONLY, 0); fd, err := Open(path, O_RDONLY, 0)
if err != nil { if err != nil {
return err return err
} }
defer fd.Close(); defer fd.Close()
// Remove contents & return first error. // Remove contents & return first error.
err = nil; err = nil
for { for {
names, err1 := fd.Readdirnames(100); names, err1 := fd.Readdirnames(100)
for _, name := range names { for _, name := range names {
err1 := RemoveAll(path + "/" + name); err1 := RemoveAll(path + "/" + name)
if err == nil { if err == nil {
err = err1 err = err1
} }
@ -106,9 +106,9 @@ func RemoveAll(path string) Error {
} }
// Remove directory. // Remove directory.
err1 := Remove(path); err1 := Remove(path)
if err == nil { if err == nil {
err = err1 err = err1
} }
return err; return err
} }

View File

@ -5,38 +5,38 @@
package os_test package os_test
import ( import (
. "os"; . "os"
"testing"; "testing"
) )
func TestMkdirAll(t *testing.T) { func TestMkdirAll(t *testing.T) {
// Create new dir, in _obj so it will get // Create new dir, in _obj so it will get
// cleaned up by make if not by us. // cleaned up by make if not by us.
path := "_obj/_TestMkdirAll_/dir/./dir2"; path := "_obj/_TestMkdirAll_/dir/./dir2"
err := MkdirAll(path, 0777); err := MkdirAll(path, 0777)
if err != nil { if err != nil {
t.Fatalf("MkdirAll %q: %s", path, err) t.Fatalf("MkdirAll %q: %s", path, err)
} }
// Already exists, should succeed. // Already exists, should succeed.
err = MkdirAll(path, 0777); err = MkdirAll(path, 0777)
if err != nil { if err != nil {
t.Fatalf("MkdirAll %q (second time): %s", path, err) t.Fatalf("MkdirAll %q (second time): %s", path, err)
} }
// Make file. // Make file.
fpath := path + "/file"; fpath := path + "/file"
_, err = Open(fpath, O_WRONLY|O_CREAT, 0666); _, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
// Can't make directory named after file. // Can't make directory named after file.
err = MkdirAll(fpath, 0777); err = MkdirAll(fpath, 0777)
if err == nil { if err == nil {
t.Fatalf("MkdirAll %q: no error") t.Fatalf("MkdirAll %q: no error")
} }
perr, ok := err.(*PathError); perr, ok := err.(*PathError)
if !ok { if !ok {
t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err) t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
} }
@ -45,12 +45,12 @@ func TestMkdirAll(t *testing.T) {
} }
// Can't make subdirectory of file. // Can't make subdirectory of file.
ffpath := fpath + "/subdir"; ffpath := fpath + "/subdir"
err = MkdirAll(ffpath, 0777); err = MkdirAll(ffpath, 0777)
if err == nil { if err == nil {
t.Fatalf("MkdirAll %q: no error") t.Fatalf("MkdirAll %q: no error")
} }
perr, ok = err.(*PathError); perr, ok = err.(*PathError)
if !ok { if !ok {
t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err) t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
} }
@ -58,24 +58,24 @@ func TestMkdirAll(t *testing.T) {
t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath) t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
} }
RemoveAll("_obj/_TestMkdirAll_"); RemoveAll("_obj/_TestMkdirAll_")
} }
func TestRemoveAll(t *testing.T) { func TestRemoveAll(t *testing.T) {
// Work directory. // Work directory.
path := "_obj/_TestRemoveAll_"; path := "_obj/_TestRemoveAll_"
fpath := path + "/file"; fpath := path + "/file"
dpath := path + "/dir"; dpath := path + "/dir"
// Make directory with 1 file and remove. // Make directory with 1 file and remove.
if err := MkdirAll(path, 0777); err != nil { if err := MkdirAll(path, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", path, err) t.Fatalf("MkdirAll %q: %s", path, err)
} }
fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666); fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
fd.Close(); fd.Close()
if err = RemoveAll(path); err != nil { if err = RemoveAll(path); err != nil {
t.Fatalf("RemoveAll %q (first): %s", path, err) t.Fatalf("RemoveAll %q (first): %s", path, err)
} }
@ -87,16 +87,16 @@ func TestRemoveAll(t *testing.T) {
if err = MkdirAll(dpath, 0777); err != nil { if err = MkdirAll(dpath, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", dpath, err) t.Fatalf("MkdirAll %q: %s", dpath, err)
} }
fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666); fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
fd.Close(); fd.Close()
fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666); fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
fd.Close(); fd.Close()
if err = RemoveAll(path); err != nil { if err = RemoveAll(path); err != nil {
t.Fatalf("RemoveAll %q (second): %s", path, err) t.Fatalf("RemoveAll %q (second): %s", path, err)
} }
@ -104,30 +104,30 @@ func TestRemoveAll(t *testing.T) {
t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path) t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
} }
if Getuid() != 0 { // Test fails as root if Getuid() != 0 { // Test fails as root
// Make directory with file and subdirectory and trigger error. // Make directory with file and subdirectory and trigger error.
if err = MkdirAll(dpath, 0777); err != nil { if err = MkdirAll(dpath, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", dpath, err) t.Fatalf("MkdirAll %q: %s", dpath, err)
} }
for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} { for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
fd, err = Open(s, O_WRONLY|O_CREAT, 0666); fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", s, err) t.Fatalf("create %q: %s", s, err)
} }
fd.Close(); fd.Close()
} }
if err = Chmod(dpath, 0); err != nil { if err = Chmod(dpath, 0); err != nil {
t.Fatalf("Chmod %q 0: %s", dpath, err) t.Fatalf("Chmod %q 0: %s", dpath, err)
} }
if err = RemoveAll(path); err == nil { if err = RemoveAll(path); err == nil {
_, err := Lstat(path); _, err := Lstat(path)
if err == nil { if err == nil {
t.Errorf("Can lstat %q after supposed RemoveAll", path) t.Errorf("Can lstat %q after supposed RemoveAll", path)
} }
t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err); t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err)
} }
perr, ok := err.(*PathError); perr, ok := err.(*PathError)
if !ok { if !ok {
t.Fatalf("RemoveAll %q returned %T not *PathError", path, err) t.Fatalf("RemoveAll %q returned %T not *PathError", path, err)
} }

View File

@ -8,28 +8,28 @@ package os
import "syscall" import "syscall"
var Args []string // provided by runtime var Args []string // provided by runtime
var Envs []string // provided by runtime var Envs []string // provided by runtime
// Getuid returns the numeric user id of the caller. // Getuid returns the numeric user id of the caller.
func Getuid() int { return syscall.Getuid() } func Getuid() int { return syscall.Getuid() }
// Geteuid returns the numeric effective user id of the caller. // Geteuid returns the numeric effective user id of the caller.
func Geteuid() int { return syscall.Geteuid() } func Geteuid() int { return syscall.Geteuid() }
// Getgid returns the numeric group id of the caller. // Getgid returns the numeric group id of the caller.
func Getgid() int { return syscall.Getgid() } func Getgid() int { return syscall.Getgid() }
// Getegid returns the numeric effective group id of the caller. // Getegid returns the numeric effective group id of the caller.
func Getegid() int { return syscall.Getegid() } func Getegid() int { return syscall.Getegid() }
// Getgroups returns a list of the numeric ids of groups that the caller belongs to. // Getgroups returns a list of the numeric ids of groups that the caller belongs to.
func Getgroups() ([]int, Error) { func Getgroups() ([]int, Error) {
gids, errno := syscall.Getgroups(); gids, errno := syscall.Getgroups()
return gids, NewSyscallError("getgroups", errno); return gids, NewSyscallError("getgroups", errno)
} }
// Exit causes the current program to exit with the given status code. // Exit causes the current program to exit with the given status code.
// Conventionally, code zero indicates success, non-zero an error. // Conventionally, code zero indicates success, non-zero an error.
func Exit(code int) { syscall.Exit(code) } func Exit(code int) { syscall.Exit(code) }

View File

@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = uint64(stat.Dev); dir.Dev = uint64(stat.Dev)
dir.Ino = stat.Ino; dir.Ino = stat.Ino
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = uint32(stat.Mode); dir.Mode = uint32(stat.Mode)
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = uint64(stat.Rdev); dir.Rdev = uint64(stat.Rdev)
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec))
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec))
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec))
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }

View File

@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = uint64(stat.Dev); dir.Dev = uint64(stat.Dev)
dir.Ino = uint64(stat.Ino); dir.Ino = uint64(stat.Ino)
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = uint32(stat.Mode); dir.Mode = uint32(stat.Mode)
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = uint64(stat.Rdev); dir.Rdev = uint64(stat.Rdev)
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec))
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec))
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec))
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }

View File

@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = stat.Dev; dir.Dev = stat.Dev
dir.Ino = uint64(stat.Ino); dir.Ino = uint64(stat.Ino)
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = stat.Mode; dir.Mode = stat.Mode
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = stat.Rdev; dir.Rdev = stat.Rdev
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim)); dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim))
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim)); dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim))
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim)); dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim))
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }

View File

@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = uint64(stat.Dev); dir.Dev = uint64(stat.Dev)
dir.Ino = uint64(stat.Ino); dir.Ino = uint64(stat.Ino)
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = stat.Mode; dir.Mode = stat.Mode
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = uint64(stat.Rdev); dir.Rdev = uint64(stat.Rdev)
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(stat.Atime) * 1e9; dir.Atime_ns = uint64(stat.Atime) * 1e9
dir.Mtime_ns = uint64(stat.Mtime) * 1e9; dir.Mtime_ns = uint64(stat.Mtime) * 1e9
dir.Ctime_ns = uint64(stat.Ctime) * 1e9; dir.Ctime_ns = uint64(stat.Ctime) * 1e9
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }

View File

@ -9,10 +9,10 @@ package os
import "syscall" import "syscall"
func Hostname() (name string, err Error) { func Hostname() (name string, err Error) {
var errno int; var errno int
name, errno = syscall.Sysctl("kern.hostname"); name, errno = syscall.Sysctl("kern.hostname")
if errno != 0 { if errno != 0 {
return "", NewSyscallError("sysctl kern.hostname", errno) return "", NewSyscallError("sysctl kern.hostname", errno)
} }
return name, nil; return name, nil
} }

View File

@ -7,10 +7,10 @@ package os
import "syscall" import "syscall"
func Hostname() (name string, err Error) { func Hostname() (name string, err Error) {
var errno int; var errno int
name, errno = syscall.Sysctl("kern.hostname"); name, errno = syscall.Sysctl("kern.hostname")
if errno != 0 { if errno != 0 {
return "", NewSyscallError("sysctl kern.hostname", errno) return "", NewSyscallError("sysctl kern.hostname", errno)
} }
return name, nil; return name, nil
} }

View File

@ -9,14 +9,14 @@ package os
// Hostname returns the host name reported by the kernel. // Hostname returns the host name reported by the kernel.
func Hostname() (name string, err Error) { func Hostname() (name string, err Error) {
f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0); f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0)
if err != nil { if err != nil {
return "", err return "", err
} }
defer f.Close(); defer f.Close()
var buf [512]byte; // Enough for a DNS name. var buf [512]byte // Enough for a DNS name.
n, err := f.Read(&buf); n, err := f.Read(&buf)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -24,5 +24,5 @@ func Hostname() (name string, err Error) {
if n > 0 && buf[n-1] == '\n' { if n > 0 && buf[n-1] == '\n' {
n-- n--
} }
return string(buf[0:n]), nil; return string(buf[0:n]), nil
} }

View File

@ -4,4 +4,4 @@
package os package os
func Hostname() (name string, err Error) { return "nacl", nil } func Hostname() (name string, err Error) { return "nacl", nil }

View File

@ -12,9 +12,9 @@ import "syscall"
// time is thus 1e9*sec+nsec, in nanoseconds. The zero of // time is thus 1e9*sec+nsec, in nanoseconds. The zero of
// time is the Unix epoch. // time is the Unix epoch.
func Time() (sec int64, nsec int64, err Error) { func Time() (sec int64, nsec int64, err Error) {
var tv syscall.Timeval; var tv syscall.Timeval
if errno := syscall.Gettimeofday(&tv); errno != 0 { if errno := syscall.Gettimeofday(&tv); errno != 0 {
return 0, 0, NewSyscallError("gettimeofday", errno) return 0, 0, NewSyscallError("gettimeofday", errno)
} }
return int64(tv.Sec), int64(tv.Usec) * 1000, err; return int64(tv.Sec), int64(tv.Usec) * 1000, err
} }

View File

@ -10,47 +10,47 @@ import "syscall"
// OS-specific routines in this directory convert the OS-local versions to these. // OS-specific routines in this directory convert the OS-local versions to these.
// Getpagesize returns the underlying system's memory page size. // Getpagesize returns the underlying system's memory page size.
func Getpagesize() int { return syscall.Getpagesize() } func Getpagesize() int { return syscall.Getpagesize() }
// A Dir describes a file and is returned by Stat, Fstat, and Lstat // A Dir describes a file and is returned by Stat, Fstat, and Lstat
type Dir struct { type Dir struct {
Dev uint64; // device number of file system holding file. Dev uint64 // device number of file system holding file.
Ino uint64; // inode number. Ino uint64 // inode number.
Nlink uint64; // number of hard links. Nlink uint64 // number of hard links.
Mode uint32; // permission and mode bits. Mode uint32 // permission and mode bits.
Uid uint32; // user id of owner. Uid uint32 // user id of owner.
Gid uint32; // group id of owner. Gid uint32 // group id of owner.
Rdev uint64; // device type for special file. Rdev uint64 // device type for special file.
Size uint64; // length in bytes. Size uint64 // length in bytes.
Blksize uint64; // size of blocks, in bytes. Blksize uint64 // size of blocks, in bytes.
Blocks uint64; // number of blocks allocated for file. Blocks uint64 // number of blocks allocated for file.
Atime_ns uint64; // access time; nanoseconds since epoch. Atime_ns uint64 // access time; nanoseconds since epoch.
Mtime_ns uint64; // modified time; nanoseconds since epoch. Mtime_ns uint64 // modified time; nanoseconds since epoch.
Ctime_ns uint64; // status change time; nanoseconds since epoch. Ctime_ns uint64 // status change time; nanoseconds since epoch.
Name string; // name of file as presented to Open. Name string // name of file as presented to Open.
FollowedSymlink bool; // followed a symlink to get this information FollowedSymlink bool // followed a symlink to get this information
} }
// IsFifo reports whether the Dir describes a FIFO file. // IsFifo reports whether the Dir describes a FIFO file.
func (dir *Dir) IsFifo() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFIFO } func (dir *Dir) IsFifo() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFIFO }
// IsChar reports whether the Dir describes a character special file. // IsChar reports whether the Dir describes a character special file.
func (dir *Dir) IsChar() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFCHR } func (dir *Dir) IsChar() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFCHR }
// IsDirectory reports whether the Dir describes a directory. // IsDirectory reports whether the Dir describes a directory.
func (dir *Dir) IsDirectory() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFDIR } func (dir *Dir) IsDirectory() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFDIR }
// IsBlock reports whether the Dir describes a block special file. // IsBlock reports whether the Dir describes a block special file.
func (dir *Dir) IsBlock() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFBLK } func (dir *Dir) IsBlock() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFBLK }
// IsRegular reports whether the Dir describes a regular file. // IsRegular reports whether the Dir describes a regular file.
func (dir *Dir) IsRegular() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFREG } func (dir *Dir) IsRegular() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFREG }
// IsSymlink reports whether the Dir describes a symbolic link. // IsSymlink reports whether the Dir describes a symbolic link.
func (dir *Dir) IsSymlink() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFLNK } func (dir *Dir) IsSymlink() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFLNK }
// IsSocket reports whether the Dir describes a socket. // IsSocket reports whether the Dir describes a socket.
func (dir *Dir) IsSocket() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFSOCK } func (dir *Dir) IsSocket() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFSOCK }
// Permission returns the file permission bits. // Permission returns the file permission bits.
func (dir *Dir) Permission() int { return int(dir.Mode & 0777) } func (dir *Dir) Permission() int { return int(dir.Mode & 0777) }

View File

@ -8,11 +8,11 @@ import "os"
// An Op is a single operation to execute to apply a patch. // An Op is a single operation to execute to apply a patch.
type Op struct { type Op struct {
Verb Verb; // action Verb Verb // action
Src string; // source file Src string // source file
Dst string; // destination file Dst string // destination file
Mode int; // mode for destination (if non-zero) Mode int // mode for destination (if non-zero)
Data []byte; // data for destination (if non-nil) Data []byte // data for destination (if non-nil)
} }
// Apply applies the patch set to the files named in the patch set, // Apply applies the patch set to the files named in the patch set,
@ -24,31 +24,31 @@ type Op struct {
// Typically this function will be io.ReadFile. // Typically this function will be io.ReadFile.
// //
func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) { func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) {
op := make([]Op, len(set.File)); op := make([]Op, len(set.File))
for i, f := range set.File { for i, f := range set.File {
o := &op[i]; o := &op[i]
o.Verb = f.Verb; o.Verb = f.Verb
o.Src = f.Src; o.Src = f.Src
o.Dst = f.Dst; o.Dst = f.Dst
o.Mode = f.NewMode; o.Mode = f.NewMode
if f.Diff != NoDiff || o.Verb != Edit { if f.Diff != NoDiff || o.Verb != Edit {
// Clients assume o.Data == nil means no data diff. // Clients assume o.Data == nil means no data diff.
// Start with a non-nil data. // Start with a non-nil data.
var old []byte = make([]byte, 0); // not nil var old []byte = make([]byte, 0) // not nil
var err os.Error; var err os.Error
if f.Src != "" { if f.Src != "" {
old, err = readFile(f.Src); old, err = readFile(f.Src)
if err != nil { if err != nil {
return nil, &os.PathError{string(f.Verb), f.Src, err} return nil, &os.PathError{string(f.Verb), f.Src, err}
} }
} }
o.Data, err = f.Diff.Apply(old); o.Data, err = f.Diff.Apply(old)
if err != nil { if err != nil {
return nil, &os.PathError{string(f.Verb), f.Src, err} return nil, &os.PathError{string(f.Verb), f.Src, err}
} }
} }
} }
return op, nil; return op, nil
} }

View File

@ -5,13 +5,13 @@
package patch package patch
import ( import (
"bytes"; "bytes"
"compress/zlib"; "compress/zlib"
"crypto/sha1"; "crypto/sha1"
"encoding/git85"; "encoding/git85"
"fmt"; "fmt"
"io"; "io"
"os"; "os"
) )
func gitSHA1(data []byte) []byte { func gitSHA1(data []byte) []byte {
@ -19,18 +19,18 @@ func gitSHA1(data []byte) []byte {
// special case: 0 length is all zeros sum // special case: 0 length is all zeros sum
return make([]byte, 20) return make([]byte, 20)
} }
h := sha1.New(); h := sha1.New()
fmt.Fprintf(h, "blob %d\x00", len(data)); fmt.Fprintf(h, "blob %d\x00", len(data))
h.Write(data); h.Write(data)
return h.Sum(); return h.Sum()
} }
// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals. // BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
// GitBinaryLiteral represents a Git binary literal diff. // GitBinaryLiteral represents a Git binary literal diff.
type GitBinaryLiteral struct { type GitBinaryLiteral struct {
OldSHA1 []byte; // if non-empty, the SHA1 hash of the original OldSHA1 []byte // if non-empty, the SHA1 hash of the original
New []byte; // the new contents New []byte // the new contents
} }
// Apply implements the Diff interface's Apply method. // Apply implements the Diff interface's Apply method.
@ -38,7 +38,7 @@ func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, os.Error) {
if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) { if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
return nil, ErrPatchFailure return nil, ErrPatchFailure
} }
return d.New, nil; return d.New, nil
} }
func unhex(c byte) uint8 { func unhex(c byte) uint8 {
@ -50,60 +50,60 @@ func unhex(c byte) uint8 {
case 'A' <= c && c <= 'F': case 'A' <= c && c <= 'F':
return c - 'A' + 10 return c - 'A' + 10
} }
return 255; return 255
} }
func getHex(s []byte) (data []byte, rest []byte) { func getHex(s []byte) (data []byte, rest []byte) {
n := 0; n := 0
for n < len(s) && unhex(s[n]) != 255 { for n < len(s) && unhex(s[n]) != 255 {
n++ n++
} }
n &^= 1; // Only take an even number of hex digits. n &^= 1 // Only take an even number of hex digits.
data = make([]byte, n/2); data = make([]byte, n/2)
for i := range data { for i := range data {
data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1]) data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
} }
rest = s[n:]; rest = s[n:]
return; return
} }
// ParseGitBinary parses raw as a Git binary patch. // ParseGitBinary parses raw as a Git binary patch.
func ParseGitBinary(raw []byte) (Diff, os.Error) { func ParseGitBinary(raw []byte) (Diff, os.Error) {
var oldSHA1, newSHA1 []byte; var oldSHA1, newSHA1 []byte
var sawBinary bool; var sawBinary bool
for { for {
var first []byte; var first []byte
first, raw, _ = getLine(raw, 1); first, raw, _ = getLine(raw, 1)
first = bytes.TrimSpace(first); first = bytes.TrimSpace(first)
if s, ok := skip(first, "index "); ok { if s, ok := skip(first, "index "); ok {
oldSHA1, s = getHex(s); oldSHA1, s = getHex(s)
if s, ok = skip(s, ".."); !ok { if s, ok = skip(s, ".."); !ok {
continue continue
} }
newSHA1, s = getHex(s); newSHA1, s = getHex(s)
continue; continue
} }
if _, ok := skip(first, "GIT binary patch"); ok { if _, ok := skip(first, "GIT binary patch"); ok {
sawBinary = true; sawBinary = true
continue; continue
} }
if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary { if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
data := make([]byte, n); data := make([]byte, n)
d := git85.NewDecoder(bytes.NewBuffer(raw)); d := git85.NewDecoder(bytes.NewBuffer(raw))
z, err := zlib.NewInflater(d); z, err := zlib.NewInflater(d)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer z.Close(); defer z.Close()
if _, err = io.ReadFull(z, data); err != nil { if _, err = io.ReadFull(z, data); err != nil {
if err == os.EOF { if err == os.EOF {
err = io.ErrUnexpectedEOF err = io.ErrUnexpectedEOF
} }
return nil, err; return nil, err
} }
var buf [1]byte; var buf [1]byte
m, err := z.Read(&buf); m, err := z.Read(&buf)
if m != 0 || err != os.EOF { if m != 0 || err != os.EOF {
return nil, os.NewError("Git binary literal longer than expected") return nil, os.NewError("Git binary literal longer than expected")
} }
@ -111,11 +111,11 @@ func ParseGitBinary(raw []byte) (Diff, os.Error) {
if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) { if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
return nil, os.NewError("Git binary literal SHA1 mismatch") return nil, os.NewError("Git binary literal SHA1 mismatch")
} }
return &GitBinaryLiteral{oldSHA1, data}, nil; return &GitBinaryLiteral{oldSHA1, data}, nil
} }
if !sawBinary { if !sawBinary {
return nil, os.NewError("unexpected Git patch header: " + string(first)) return nil, os.NewError("unexpected Git patch header: " + string(first))
} }
} }
panic("unreachable"); panic("unreachable")
} }

View File

@ -8,37 +8,37 @@
package patch package patch
import ( import (
"bytes"; "bytes"
"os"; "os"
"path"; "path"
"strings"; "strings"
) )
// A Set represents a set of patches to be applied as a single atomic unit. // A Set represents a set of patches to be applied as a single atomic unit.
// Patch sets are often preceded by a descriptive header. // Patch sets are often preceded by a descriptive header.
type Set struct { type Set struct {
Header string; // free-form text Header string // free-form text
File []*File; File []*File
} }
// A File represents a collection of changes to be made to a single file. // A File represents a collection of changes to be made to a single file.
type File struct { type File struct {
Verb Verb; Verb Verb
Src string; // source for Verb == Copy, Verb == Rename Src string // source for Verb == Copy, Verb == Rename
Dst string; Dst string
OldMode, NewMode int; // 0 indicates not used OldMode, NewMode int // 0 indicates not used
Diff; // changes to data; == NoDiff if operation does not edit file Diff // changes to data; == NoDiff if operation does not edit file
} }
// A Verb is an action performed on a file. // A Verb is an action performed on a file.
type Verb string type Verb string
const ( const (
Add Verb = "add"; Add Verb = "add"
Copy Verb = "copy"; Copy Verb = "copy"
Delete Verb = "delete"; Delete Verb = "delete"
Edit Verb = "edit"; Edit Verb = "edit"
Rename Verb = "rename"; Rename Verb = "rename"
) )
// A Diff is any object that describes changes to transform // A Diff is any object that describes changes to transform
@ -47,7 +47,7 @@ type Diff interface {
// Apply applies the changes listed in the diff // Apply applies the changes listed in the diff
// to the string s, returning the new version of the string. // to the string s, returning the new version of the string.
// Note that the string s need not be a text string. // Note that the string s need not be a text string.
Apply(old []byte) (new []byte, err os.Error); Apply(old []byte) (new []byte, err os.Error)
} }
// NoDiff is a no-op Diff implementation: it passes the // NoDiff is a no-op Diff implementation: it passes the
@ -63,7 +63,7 @@ func (noDiffType) Apply(old []byte) ([]byte, os.Error) {
// A SyntaxError represents a syntax error encountered while parsing a patch. // A SyntaxError represents a syntax error encountered while parsing a patch.
type SyntaxError string type SyntaxError string
func (e SyntaxError) String() string { return string(e) } func (e SyntaxError) String() string { return string(e) }
var newline = []byte{'\n'} var newline = []byte{'\n'}
@ -82,37 +82,37 @@ func Parse(text []byte) (*Set, os.Error) {
// diff [--git] a/file/path b/file/path. // diff [--git] a/file/path b/file/path.
// //
// First look for Index: lines. If none, fall back on diff lines. // First look for Index: lines. If none, fall back on diff lines.
text, files := sections(text, "Index: "); text, files := sections(text, "Index: ")
if len(files) == 0 { if len(files) == 0 {
text, files = sections(text, "diff ") text, files = sections(text, "diff ")
} }
set := &Set{string(text), make([]*File, len(files))}; set := &Set{string(text), make([]*File, len(files))}
// Parse file header and then // Parse file header and then
// parse files into patch chunks. // parse files into patch chunks.
// Each chunk begins with @@. // Each chunk begins with @@.
for i, raw := range files { for i, raw := range files {
p := new(File); p := new(File)
set.File[i] = p; set.File[i] = p
// First line of hdr is the Index: that // First line of hdr is the Index: that
// begins the section. After that is the file name. // begins the section. After that is the file name.
s, raw, _ := getLine(raw, 1); s, raw, _ := getLine(raw, 1)
if hasPrefix(s, "Index: ") { if hasPrefix(s, "Index: ") {
p.Dst = string(bytes.TrimSpace(s[7:])); p.Dst = string(bytes.TrimSpace(s[7:]))
goto HaveName; goto HaveName
} else if hasPrefix(s, "diff ") { } else if hasPrefix(s, "diff ") {
str := string(bytes.TrimSpace(s)); str := string(bytes.TrimSpace(s))
i := strings.LastIndex(str, " b/"); i := strings.LastIndex(str, " b/")
if i >= 0 { if i >= 0 {
p.Dst = str[i+3:]; p.Dst = str[i+3:]
goto HaveName; goto HaveName
} }
} }
return nil, SyntaxError("unexpected patch header line: " + string(s)); return nil, SyntaxError("unexpected patch header line: " + string(s))
HaveName: HaveName:
p.Dst = path.Clean(p.Dst); p.Dst = path.Clean(p.Dst)
if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") { if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
return nil, SyntaxError("invalid path: " + p.Dst) return nil, SyntaxError("invalid path: " + p.Dst)
} }
@ -126,55 +126,55 @@ func Parse(text []byte) (*Set, os.Error) {
// rename to %s // rename to %s
// copy from %s - file copied from other file // copy from %s - file copied from other file
// copy to %s // copy to %s
p.Verb = Edit; p.Verb = Edit
for len(raw) > 0 { for len(raw) > 0 {
oldraw := raw; oldraw := raw
var l []byte; var l []byte
l, raw, _ = getLine(raw, 1); l, raw, _ = getLine(raw, 1)
l = bytes.TrimSpace(l); l = bytes.TrimSpace(l)
if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
p.NewMode = m; p.NewMode = m
p.Verb = Add; p.Verb = Add
continue; continue
} }
if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
p.OldMode = m; p.OldMode = m
p.Verb = Delete; p.Verb = Delete
p.Src = p.Dst; p.Src = p.Dst
p.Dst = ""; p.Dst = ""
continue; continue
} }
if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
// usually implies p.Verb = "rename" or "copy" // usually implies p.Verb = "rename" or "copy"
// but we'll get that from the rename or copy line. // but we'll get that from the rename or copy line.
p.OldMode = m; p.OldMode = m
continue; continue
} }
if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
p.OldMode = m; p.OldMode = m
continue; continue
} }
if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
p.NewMode = m; p.NewMode = m
continue; continue
} }
if s, ok := skip(l, "rename from "); ok && len(s) > 0 { if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
p.Src = string(s); p.Src = string(s)
p.Verb = Rename; p.Verb = Rename
continue; continue
} }
if s, ok := skip(l, "rename to "); ok && len(s) > 0 { if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
p.Verb = Rename; p.Verb = Rename
continue; continue
} }
if s, ok := skip(l, "copy from "); ok && len(s) > 0 { if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
p.Src = string(s); p.Src = string(s)
p.Verb = Copy; p.Verb = Copy
continue; continue
} }
if s, ok := skip(l, "copy to "); ok && len(s) > 0 { if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
p.Verb = Copy; p.Verb = Copy
continue; continue
} }
if s, ok := skip(l, "Binary file "); ok && len(s) > 0 { if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
// Hg prints // Hg prints
@ -200,22 +200,22 @@ func Parse(text []byte) (*Set, os.Error) {
continue continue
} }
if hasPrefix(l, "@@ -") { if hasPrefix(l, "@@ -") {
diff, err := ParseTextDiff(oldraw); diff, err := ParseTextDiff(oldraw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.Diff = diff; p.Diff = diff
break; break
} }
if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") { if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") {
diff, err := ParseGitBinary(oldraw); diff, err := ParseGitBinary(oldraw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.Diff = diff; p.Diff = diff
break; break
} }
return nil, SyntaxError("unexpected patch header line: " + string(l)); return nil, SyntaxError("unexpected patch header line: " + string(l))
} }
if p.Diff == nil { if p.Diff == nil {
p.Diff = NoDiff p.Diff = NoDiff
@ -225,25 +225,25 @@ func Parse(text []byte) (*Set, os.Error) {
} }
} }
return set, nil; return set, nil
} }
// getLine returns the first n lines of data and the remainder. // getLine returns the first n lines of data and the remainder.
// If data has no newline, getLine returns data, nil, false // If data has no newline, getLine returns data, nil, false
func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) { func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
rest = data; rest = data
ok = true; ok = true
for ; n > 0; n-- { for ; n > 0; n-- {
nl := bytes.Index(rest, newline); nl := bytes.Index(rest, newline)
if nl < 0 { if nl < 0 {
rest = nil; rest = nil
ok = false; ok = false
break; break
} }
rest = rest[nl+1:]; rest = rest[nl+1:]
} }
first = data[0 : len(data)-len(rest)]; first = data[0 : len(data)-len(rest)]
return; return
} }
// sections returns a collection of file sections, // sections returns a collection of file sections,
@ -251,34 +251,34 @@ func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
// text before the first instance of such a line is // text before the first instance of such a line is
// returned separately. // returned separately.
func sections(text []byte, prefix string) ([]byte, [][]byte) { func sections(text []byte, prefix string) ([]byte, [][]byte) {
n := 0; n := 0
for b := text; ; { for b := text; ; {
if hasPrefix(b, prefix) { if hasPrefix(b, prefix) {
n++ n++
} }
nl := bytes.Index(b, newline); nl := bytes.Index(b, newline)
if nl < 0 { if nl < 0 {
break break
} }
b = b[nl+1:]; b = b[nl+1:]
} }
sect := make([][]byte, n+1); sect := make([][]byte, n+1)
n = 0; n = 0
for b := text; ; { for b := text; ; {
if hasPrefix(b, prefix) { if hasPrefix(b, prefix) {
sect[n] = text[0 : len(text)-len(b)]; sect[n] = text[0 : len(text)-len(b)]
n++; n++
text = b; text = b
} }
nl := bytes.Index(b, newline); nl := bytes.Index(b, newline)
if nl < 0 { if nl < 0 {
sect[n] = text; sect[n] = text
break; break
} }
b = b[nl+1:]; b = b[nl+1:]
} }
return sect[0], sect[1:]; return sect[0], sect[1:]
} }
// if s begins with the prefix t, skip returns // if s begins with the prefix t, skip returns
@ -287,7 +287,7 @@ func skip(s []byte, t string) (ss []byte, ok bool) {
if len(s) < len(t) || string(s[0:len(t)]) != t { if len(s) < len(t) || string(s[0:len(t)]) != t {
return nil, false return nil, false
} }
return s[len(t):], true; return s[len(t):], true
} }
// if s begins with the prefix t and then is a sequence // if s begins with the prefix t and then is a sequence
@ -298,22 +298,22 @@ func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
if s, ok = skip(s, t); !ok { if s, ok = skip(s, t); !ok {
return return
} }
var i int; var i int
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ { for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
n = n*base + int(s[i]-'0') n = n*base + int(s[i]-'0')
} }
if i == 0 { if i == 0 {
return return
} }
return n, s[i:], true; return n, s[i:], true
} }
// hasPrefix returns true if s begins with t. // hasPrefix returns true if s begins with t.
func hasPrefix(s []byte, t string) bool { func hasPrefix(s []byte, t string) bool {
_, ok := skip(s, t); _, ok := skip(s, t)
return ok; return ok
} }
// splitLines returns the result of splitting s into lines. // splitLines returns the result of splitting s into lines.
// The \n on each line is preserved. // The \n on each line is preserved.
func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline, 0) } func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline, 0) }

View File

@ -7,31 +7,31 @@ package patch
// TODO(rsc): test Apply // TODO(rsc): test Apply
import ( import (
"strings"; "strings"
"testing"; "testing"
) )
type Test struct { type Test struct {
in string; in string
out string; out string
diff string; diff string
} }
func TestFileApply(t *testing.T) { func TestFileApply(t *testing.T) {
for i, test := range tests { for i, test := range tests {
set, err := Parse(strings.Bytes(test.diff)); set, err := Parse(strings.Bytes(test.diff))
if err != nil { if err != nil {
t.Errorf("#%d: Parse: %s", i, err); t.Errorf("#%d: Parse: %s", i, err)
continue; continue
} }
if len(set.File) != 1 { if len(set.File) != 1 {
t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File)); t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File))
continue; continue
} }
new, err := set.File[0].Apply(strings.Bytes(test.in)); new, err := set.File[0].Apply(strings.Bytes(test.in))
if err != nil { if err != nil {
t.Errorf("#%d: Apply: %s", i, err); t.Errorf("#%d: Apply: %s", i, err)
continue; continue
} }
if s := string(new); s != test.out { if s := string(new); s != test.out {
t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out) t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)

View File

@ -1,8 +1,8 @@
package patch package patch
import ( import (
"bytes"; "bytes"
"os"; "os"
) )
type TextDiff []TextChunk type TextDiff []TextChunk
@ -11,25 +11,25 @@ type TextDiff []TextChunk
// the text beginning at Line, which should be exactly Old, // the text beginning at Line, which should be exactly Old,
// is to be replaced with New. // is to be replaced with New.
type TextChunk struct { type TextChunk struct {
Line int; Line int
Old []byte; Old []byte
New []byte; New []byte
} }
func ParseTextDiff(raw []byte) (TextDiff, os.Error) { func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
// Copy raw so it is safe to keep references to slices. // Copy raw so it is safe to keep references to slices.
_, chunks := sections(raw, "@@ -"); _, chunks := sections(raw, "@@ -")
delta := 0; delta := 0
diff := make(TextDiff, len(chunks)); diff := make(TextDiff, len(chunks))
for i, raw := range chunks { for i, raw := range chunks {
c := &diff[i]; c := &diff[i]
// Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk // Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
chunk := splitLines(raw); chunk := splitLines(raw)
chunkHeader := chunk[0]; chunkHeader := chunk[0]
var ok bool; var ok bool
var oldLine, oldCount, newLine, newCount int; var oldLine, oldCount, newLine, newCount int
s := chunkHeader; s := chunkHeader
if oldLine, s, ok = atoi(s, "@@ -", 10); !ok { if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
ErrChunkHdr: ErrChunkHdr:
return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader)) return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
@ -61,16 +61,16 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
} }
// Count lines in text // Count lines in text
var dropOldNL, dropNewNL bool; var dropOldNL, dropNewNL bool
var nold, nnew int; var nold, nnew int
var lastch byte; var lastch byte
chunk = chunk[1:]; chunk = chunk[1:]
for _, l := range chunk { for _, l := range chunk {
if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') { if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
if len(bytes.TrimSpace(l)) != 0 { if len(bytes.TrimSpace(l)) != 0 {
return nil, SyntaxError("too many chunk lines") return nil, SyntaxError("too many chunk lines")
} }
continue; continue
} }
if len(l) == 0 { if len(l) == 0 {
return nil, SyntaxError("empty chunk line") return nil, SyntaxError("empty chunk line")
@ -81,8 +81,8 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
case '-': case '-':
nold++ nold++
case ' ': case ' ':
nnew++; nnew++
nold++; nold++
case '\\': case '\\':
if _, ok := skip(l, "\\ No newline at end of file"); ok { if _, ok := skip(l, "\\ No newline at end of file"); ok {
switch lastch { switch lastch {
@ -91,18 +91,18 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
case '+': case '+':
dropNewNL = true dropNewNL = true
case ' ': case ' ':
dropOldNL = true; dropOldNL = true
dropNewNL = true; dropNewNL = true
default: default:
return nil, SyntaxError("message `\\ No newline at end of file' out of context") return nil, SyntaxError("message `\\ No newline at end of file' out of context")
} }
break; break
} }
fallthrough; fallthrough
default: default:
return nil, SyntaxError("unexpected chunk line: " + string(l)) return nil, SyntaxError("unexpected chunk line: " + string(l))
} }
lastch = l[0]; lastch = l[0]
} }
// Does it match the header? // Does it match the header?
@ -112,31 +112,31 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
if oldLine+delta != newLine { if oldLine+delta != newLine {
return nil, SyntaxError("chunk delta is out of sync with previous chunks") return nil, SyntaxError("chunk delta is out of sync with previous chunks")
} }
delta += nnew - nold; delta += nnew - nold
c.Line = oldLine; c.Line = oldLine
var old, new bytes.Buffer; var old, new bytes.Buffer
nold = 0; nold = 0
nnew = 0; nnew = 0
for _, l := range chunk { for _, l := range chunk {
if nold == oldCount && nnew == newCount { if nold == oldCount && nnew == newCount {
break break
} }
ch, l := l[0], l[1:]; ch, l := l[0], l[1:]
if ch == '\\' { if ch == '\\' {
continue continue
} }
if ch != '+' { if ch != '+' {
old.Write(l); old.Write(l)
nold++; nold++
} }
if ch != '-' { if ch != '-' {
new.Write(l); new.Write(l)
nnew++; nnew++
} }
} }
c.Old = old.Bytes(); c.Old = old.Bytes()
c.New = new.Bytes(); c.New = new.Bytes()
if dropOldNL { if dropOldNL {
c.Old = c.Old[0 : len(c.Old)-1] c.Old = c.Old[0 : len(c.Old)-1]
} }
@ -144,7 +144,7 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
c.New = c.New[0 : len(c.New)-1] c.New = c.New[0 : len(c.New)-1]
} }
} }
return diff, nil; return diff, nil
} }
var ErrPatchFailure = os.NewError("patch did not apply cleanly") var ErrPatchFailure = os.NewError("patch did not apply cleanly")
@ -152,20 +152,20 @@ var ErrPatchFailure = os.NewError("patch did not apply cleanly")
// Apply applies the changes listed in the diff // Apply applies the changes listed in the diff
// to the data, returning the new version. // to the data, returning the new version.
func (d TextDiff) Apply(data []byte) ([]byte, os.Error) { func (d TextDiff) Apply(data []byte) ([]byte, os.Error) {
var buf bytes.Buffer; var buf bytes.Buffer
line := 1; line := 1
for _, c := range d { for _, c := range d {
var ok bool; var ok bool
var prefix []byte; var prefix []byte
prefix, data, ok = getLine(data, c.Line-line); prefix, data, ok = getLine(data, c.Line-line)
if !ok || !bytes.HasPrefix(data, c.Old) { if !ok || !bytes.HasPrefix(data, c.Old) {
return nil, ErrPatchFailure return nil, ErrPatchFailure
} }
buf.Write(prefix); buf.Write(prefix)
data = data[len(c.Old):]; data = data[len(c.Old):]
buf.Write(c.New); buf.Write(c.New)
line = c.Line + bytes.Count(c.Old, newline); line = c.Line + bytes.Count(c.Old, newline)
} }
buf.Write(data); buf.Write(data)
return buf.Bytes(), nil; return buf.Bytes(), nil
} }

View File

@ -7,9 +7,9 @@
package path package path
import ( import (
"io/ioutil"; "io/ioutil"
"os"; "os"
"strings"; "strings"
) )
// Clean returns the shortest path name equivalent to path // Clean returns the shortest path name equivalent to path
@ -34,16 +34,16 @@ func Clean(path string) string {
return "." return "."
} }
rooted := path[0] == '/'; rooted := path[0] == '/'
n := len(path); n := len(path)
// Invariants: // Invariants:
// reading from path; r is index of next byte to process. // reading from path; r is index of next byte to process.
// writing to buf; w is index of next byte to write. // writing to buf; w is index of next byte to write.
// dotdot is index in buf where .. must stop, either because // dotdot is index in buf where .. must stop, either because
// it is the leading slash or it is a leading ../../.. prefix. // it is the leading slash or it is a leading ../../.. prefix.
buf := strings.Bytes(path); buf := strings.Bytes(path)
r, w, dotdot := 0, 0, 0; r, w, dotdot := 0, 0, 0
if rooted { if rooted {
r, w, dotdot = 1, 1, 1 r, w, dotdot = 1, 1, 1
} }
@ -58,48 +58,48 @@ func Clean(path string) string {
r++ r++
case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'): case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
// .. element: remove to last / // .. element: remove to last /
r += 2; r += 2
switch { switch {
case w > dotdot: case w > dotdot:
// can backtrack // can backtrack
w--; w--
for w > dotdot && buf[w] != '/' { for w > dotdot && buf[w] != '/' {
w-- w--
} }
case !rooted: case !rooted:
// cannot backtrack, but not rooted, so append .. element. // cannot backtrack, but not rooted, so append .. element.
if w > 0 { if w > 0 {
buf[w] = '/'; buf[w] = '/'
w++; w++
} }
buf[w] = '.'; buf[w] = '.'
w++; w++
buf[w] = '.'; buf[w] = '.'
w++; w++
dotdot = w; dotdot = w
} }
default: default:
// real path element. // real path element.
// add slash if needed // add slash if needed
if rooted && w != 1 || !rooted && w != 0 { if rooted && w != 1 || !rooted && w != 0 {
buf[w] = '/'; buf[w] = '/'
w++; w++
} }
// copy element // copy element
for ; r < n && path[r] != '/'; r++ { for ; r < n && path[r] != '/'; r++ {
buf[w] = path[r]; buf[w] = path[r]
w++; w++
} }
} }
} }
// Turn empty string into "." // Turn empty string into "."
if w == 0 { if w == 0 {
buf[w] = '.'; buf[w] = '.'
w++; w++
} }
return string(buf[0:w]); return string(buf[0:w])
} }
// Split splits path immediately following the final slash, // Split splits path immediately following the final slash,
@ -112,7 +112,7 @@ func Split(path string) (dir, file string) {
return path[0 : i+1], path[i+1:] return path[0 : i+1], path[i+1:]
} }
} }
return "", path; return "", path
} }
// Join joins dir and file into a single path, adding a separating // Join joins dir and file into a single path, adding a separating
@ -121,7 +121,7 @@ func Join(dir, file string) string {
if dir == "" { if dir == "" {
return file return file
} }
return Clean(dir + "/" + file); return Clean(dir + "/" + file)
} }
// Ext returns the file name extension used by path. // Ext returns the file name extension used by path.
@ -134,28 +134,28 @@ func Ext(path string) string {
return path[i:] return path[i:]
} }
} }
return ""; return ""
} }
// Visitor methods are invoked for corresponding file tree entries // Visitor methods are invoked for corresponding file tree entries
// visited by Walk. The parameter path is the full path of d relative // visited by Walk. The parameter path is the full path of d relative
// to root. // to root.
type Visitor interface { type Visitor interface {
VisitDir(path string, d *os.Dir) bool; VisitDir(path string, d *os.Dir) bool
VisitFile(path string, d *os.Dir); VisitFile(path string, d *os.Dir)
} }
func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) { func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
if !d.IsDirectory() { if !d.IsDirectory() {
v.VisitFile(path, d); v.VisitFile(path, d)
return; return
} }
if !v.VisitDir(path, d) { if !v.VisitDir(path, d) {
return // skip directory entries return // skip directory entries
} }
list, err := ioutil.ReadDir(path); list, err := ioutil.ReadDir(path)
if err != nil { if err != nil {
if errors != nil { if errors != nil {
errors <- err errors <- err
@ -175,12 +175,12 @@ func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
// If errors != nil, Walk sends each directory read error // If errors != nil, Walk sends each directory read error
// to the channel. Otherwise Walk discards the error. // to the channel. Otherwise Walk discards the error.
func Walk(root string, v Visitor, errors chan<- os.Error) { func Walk(root string, v Visitor, errors chan<- os.Error) {
d, err := os.Lstat(root); d, err := os.Lstat(root)
if err != nil { if err != nil {
if errors != nil { if errors != nil {
errors <- err errors <- err
} }
return; // can't progress return // can't progress
} }
walk(root, d, v, errors); walk(root, d, v, errors)
} }

View File

@ -5,12 +5,12 @@
package path package path
import ( import (
"os"; "os"
"testing"; "testing"
) )
type CleanTest struct { type CleanTest struct {
path, clean string; path, clean string
} }
var cleantests = []CleanTest{ var cleantests = []CleanTest{
@ -72,7 +72,7 @@ func TestClean(t *testing.T) {
} }
type SplitTest struct { type SplitTest struct {
path, dir, file string; path, dir, file string
} }
var splittests = []SplitTest{ var splittests = []SplitTest{
@ -92,7 +92,7 @@ func TestSplit(t *testing.T) {
} }
type JoinTest struct { type JoinTest struct {
dir, file, path string; dir, file, path string
} }
var jointests = []JoinTest{ var jointests = []JoinTest{
@ -114,7 +114,7 @@ func TestJoin(t *testing.T) {
} }
type ExtTest struct { type ExtTest struct {
path, ext string; path, ext string
} }
var exttests = []ExtTest{ var exttests = []ExtTest{
@ -134,9 +134,9 @@ func TestExt(t *testing.T) {
} }
type Node struct { type Node struct {
name string; name string
entries []*Node; // nil if the entry is a file entries []*Node // nil if the entry is a file
mark int; mark int
} }
var tree = &Node{ var tree = &Node{
@ -166,7 +166,7 @@ var tree = &Node{
} }
func walkTree(n *Node, path string, f func(path string, n *Node)) { func walkTree(n *Node, path string, f func(path string, n *Node)) {
f(path, n); f(path, n)
for _, e := range n.entries { for _, e := range n.entries {
walkTree(e, Join(path, e.name), f) walkTree(e, Join(path, e.name), f)
} }
@ -175,25 +175,25 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) {
func makeTree(t *testing.T) { func makeTree(t *testing.T) {
walkTree(tree, tree.name, func(path string, n *Node) { walkTree(tree, tree.name, func(path string, n *Node) {
if n.entries == nil { if n.entries == nil {
fd, err := os.Open(path, os.O_CREAT, 0660); fd, err := os.Open(path, os.O_CREAT, 0660)
if err != nil { if err != nil {
t.Errorf("makeTree: %v", err) t.Errorf("makeTree: %v", err)
} }
fd.Close(); fd.Close()
} else { } else {
os.Mkdir(path, 0770) os.Mkdir(path, 0770)
} }
}) })
} }
func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) } func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
func checkMarks(t *testing.T) { func checkMarks(t *testing.T) {
walkTree(tree, tree.name, func(path string, n *Node) { walkTree(tree, tree.name, func(path string, n *Node) {
if n.mark != 1 { if n.mark != 1 {
t.Errorf("node %s mark = %d; expected 1", path, n.mark) t.Errorf("node %s mark = %d; expected 1", path, n.mark)
} }
n.mark = 0; n.mark = 0
}) })
} }
@ -209,8 +209,8 @@ func mark(name string) {
type TestVisitor struct{} type TestVisitor struct{}
func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool { func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool {
mark(d.Name); mark(d.Name)
return true; return true
} }
func (v *TestVisitor) VisitFile(path string, d *os.Dir) { func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
@ -218,52 +218,52 @@ func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
} }
func TestWalk(t *testing.T) { func TestWalk(t *testing.T) {
makeTree(t); makeTree(t)
// 1) ignore error handling, expect none // 1) ignore error handling, expect none
v := &TestVisitor{}; v := &TestVisitor{}
Walk(tree.name, v, nil); Walk(tree.name, v, nil)
checkMarks(t); checkMarks(t)
// 2) handle errors, expect none // 2) handle errors, expect none
errors := make(chan os.Error, 64); errors := make(chan os.Error, 64)
Walk(tree.name, v, errors); Walk(tree.name, v, errors)
if err, ok := <-errors; ok { if err, ok := <-errors; ok {
t.Errorf("no error expected, found: s", err) t.Errorf("no error expected, found: s", err)
} }
checkMarks(t); checkMarks(t)
if os.Getuid() != 0 { if os.Getuid() != 0 {
// introduce 2 errors: chmod top-level directories to 0 // introduce 2 errors: chmod top-level directories to 0
os.Chmod(Join(tree.name, tree.entries[1].name), 0); os.Chmod(Join(tree.name, tree.entries[1].name), 0)
os.Chmod(Join(tree.name, tree.entries[3].name), 0); os.Chmod(Join(tree.name, tree.entries[3].name), 0)
// mark respective subtrees manually // mark respective subtrees manually
markTree(tree.entries[1]); markTree(tree.entries[1])
markTree(tree.entries[3]); markTree(tree.entries[3])
// correct double-marking of directory itself // correct double-marking of directory itself
tree.entries[1].mark--; tree.entries[1].mark--
tree.entries[3].mark--; tree.entries[3].mark--
// 3) handle errors, expect two // 3) handle errors, expect two
errors = make(chan os.Error, 64); errors = make(chan os.Error, 64)
os.Chmod(Join(tree.name, tree.entries[1].name), 0); os.Chmod(Join(tree.name, tree.entries[1].name), 0)
Walk(tree.name, v, errors); Walk(tree.name, v, errors)
for i := 1; i <= 2; i++ { for i := 1; i <= 2; i++ {
if _, ok := <-errors; !ok { if _, ok := <-errors; !ok {
t.Errorf("%d. error expected, none found", i); t.Errorf("%d. error expected, none found", i)
break; break
} }
} }
if err, ok := <-errors; ok { if err, ok := <-errors; ok {
t.Errorf("only two errors expected, found 3rd: %v", err) t.Errorf("only two errors expected, found 3rd: %v", err)
} }
// the inaccessible subtrees were marked manually // the inaccessible subtrees were marked manually
checkMarks(t); checkMarks(t)
} }
// cleanup // cleanup
os.Chmod(Join(tree.name, tree.entries[1].name), 0770); os.Chmod(Join(tree.name, tree.entries[1].name), 0770)
os.Chmod(Join(tree.name, tree.entries[3].name), 0770); os.Chmod(Join(tree.name, tree.entries[3].name), 0770)
if err := os.RemoveAll(tree.name); err != nil { if err := os.RemoveAll(tree.name); err != nil {
t.Errorf("removeTree: %v", err) t.Errorf("removeTree: %v", err)
} }

View File

@ -5,7 +5,7 @@
package rand package rand
import ( import (
"math"; "math"
) )
/* /*
@ -17,7 +17,7 @@ import (
*/ */
const ( const (
re = 7.69711747013104972; re = 7.69711747013104972
) )
// ExpFloat64 returns an exponentially distributed float64 in the range // ExpFloat64 returns an exponentially distributed float64 in the range
@ -30,9 +30,9 @@ const (
// //
func (r *Rand) ExpFloat64() float64 { func (r *Rand) ExpFloat64() float64 {
for { for {
j := r.Uint32(); j := r.Uint32()
i := j & 0xFF; i := j & 0xFF
x := float64(j) * float64(we[i]); x := float64(j) * float64(we[i])
if j < ke[i] { if j < ke[i] {
return x return x
} }
@ -43,7 +43,7 @@ func (r *Rand) ExpFloat64() float64 {
return x return x
} }
} }
panic("unreachable"); panic("unreachable")
} }
var ke = [256]uint32{ var ke = [256]uint32{

View File

@ -5,7 +5,7 @@
package rand package rand
import ( import (
"math"; "math"
) )
/* /*
@ -17,14 +17,14 @@ import (
*/ */
const ( const (
rn = 3.442619855899; rn = 3.442619855899
) )
func absInt32(i int32) uint32 { func absInt32(i int32) uint32 {
if i < 0 { if i < 0 {
return uint32(-i) return uint32(-i)
} }
return uint32(i); return uint32(i)
} }
// NormFloat64 returns a normally distributed float64 in the range // NormFloat64 returns a normally distributed float64 in the range
@ -37,9 +37,9 @@ func absInt32(i int32) uint32 {
// //
func (r *Rand) NormFloat64() float64 { func (r *Rand) NormFloat64() float64 {
for { for {
j := int32(r.Uint32()); // Possibly negative j := int32(r.Uint32()) // Possibly negative
i := j & 0x7F; i := j & 0x7F
x := float64(j) * float64(wn[i]); x := float64(j) * float64(wn[i])
if absInt32(j) < kn[i] { if absInt32(j) < kn[i] {
// This case should be hit better than 99% of the time. // This case should be hit better than 99% of the time.
return x return x
@ -48,8 +48,8 @@ func (r *Rand) NormFloat64() float64 {
if i == 0 { if i == 0 {
// This extra work is only required for the base strip. // This extra work is only required for the base strip.
for { for {
x = -math.Log(r.Float64()) * (1.0 / rn); x = -math.Log(r.Float64()) * (1.0 / rn)
y := -math.Log(r.Float64()); y := -math.Log(r.Float64())
if y+y >= x*x { if y+y >= x*x {
break break
} }
@ -57,13 +57,13 @@ func (r *Rand) NormFloat64() float64 {
if j > 0 { if j > 0 {
return rn + x return rn + x
} }
return -rn - x; return -rn - x
} }
if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) { if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
return x return x
} }
} }
panic("unreachable"); panic("unreachable")
} }
var kn = [128]uint32{ var kn = [128]uint32{

View File

@ -10,42 +10,42 @@ import "sync"
// A Source represents a source of uniformly-distributed // A Source represents a source of uniformly-distributed
// pseudo-random int64 values in the range [0, 1<<63). // pseudo-random int64 values in the range [0, 1<<63).
type Source interface { type Source interface {
Int63() int64; Int63() int64
Seed(seed int64); Seed(seed int64)
} }
// NewSource returns a new pseudo-random Source seeded with the given value. // NewSource returns a new pseudo-random Source seeded with the given value.
func NewSource(seed int64) Source { func NewSource(seed int64) Source {
var rng rngSource; var rng rngSource
rng.Seed(seed); rng.Seed(seed)
return &rng; return &rng
} }
// A Rand is a source of random numbers. // A Rand is a source of random numbers.
type Rand struct { type Rand struct {
src Source; src Source
} }
// New returns a new Rand that uses random values from src // New returns a new Rand that uses random values from src
// to generate other random values. // to generate other random values.
func New(src Source) *Rand { return &Rand{src} } func New(src Source) *Rand { return &Rand{src} }
// Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed uses the provided seed value to initialize the generator to a deterministic state.
func (r *Rand) Seed(seed int64) { r.src.Seed(seed) } func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (r *Rand) Int63() int64 { return r.src.Int63() } func (r *Rand) Int63() int64 { return r.src.Int63() }
// Uint32 returns a pseudo-random 32-bit value as a uint32. // Uint32 returns a pseudo-random 32-bit value as a uint32.
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) } func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. // Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) } func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
// Int returns a non-negative pseudo-random int. // Int returns a non-negative pseudo-random int.
func (r *Rand) Int() int { func (r *Rand) Int() int {
u := uint(r.Int63()); u := uint(r.Int63())
return int(u << 1 >> 1); // clear sign bit if int == int32 return int(u << 1 >> 1) // clear sign bit if int == int32
} }
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
@ -53,40 +53,40 @@ func (r *Rand) Int63n(n int64) int64 {
if n <= 0 { if n <= 0 {
return 0 return 0
} }
max := int64((1 << 63) - 1 - (1<<63)%uint64(n)); max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
v := r.Int63(); v := r.Int63()
for v > max { for v > max {
v = r.Int63() v = r.Int63()
} }
return v % n; return v % n
} }
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
func (r *Rand) Int31n(n int32) int32 { return int32(r.Int63n(int64(n))) } func (r *Rand) Int31n(n int32) int32 { return int32(r.Int63n(int64(n))) }
// Intn returns, as an int, a non-negative pseudo-random number in [0,n). // Intn returns, as an int, a non-negative pseudo-random number in [0,n).
func (r *Rand) Intn(n int) int { return int(r.Int63n(int64(n))) } func (r *Rand) Intn(n int) int { return int(r.Int63n(int64(n))) }
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) } func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float32() float32 { return float32(r.Float64()) } func (r *Rand) Float32() float32 { return float32(r.Float64()) }
// Float returns, as a float, a pseudo-random number in [0.0,1.0). // Float returns, as a float, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float() float { return float(r.Float64()) } func (r *Rand) Float() float { return float(r.Float64()) }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int { func (r *Rand) Perm(n int) []int {
m := make([]int, n); m := make([]int, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
m[i] = i m[i] = i
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
j := r.Intn(i + 1); j := r.Intn(i + 1)
m[i], m[j] = m[j], m[i]; m[i], m[j] = m[j], m[i]
} }
return m; return m
} }
/* /*
@ -96,40 +96,40 @@ func (r *Rand) Perm(n int) []int {
var globalRand = New(&lockedSource{src: NewSource(1)}) var globalRand = New(&lockedSource{src: NewSource(1)})
// Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed uses the provided seed value to initialize the generator to a deterministic state.
func Seed(seed int64) { globalRand.Seed(seed) } func Seed(seed int64) { globalRand.Seed(seed) }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func Int63() int64 { return globalRand.Int63() } func Int63() int64 { return globalRand.Int63() }
// Uint32 returns a pseudo-random 32-bit value as a uint32. // Uint32 returns a pseudo-random 32-bit value as a uint32.
func Uint32() uint32 { return globalRand.Uint32() } func Uint32() uint32 { return globalRand.Uint32() }
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. // Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func Int31() int32 { return globalRand.Int31() } func Int31() int32 { return globalRand.Int31() }
// Int returns a non-negative pseudo-random int. // Int returns a non-negative pseudo-random int.
func Int() int { return globalRand.Int() } func Int() int { return globalRand.Int() }
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
func Int63n(n int64) int64 { return globalRand.Int63n(n) } func Int63n(n int64) int64 { return globalRand.Int63n(n) }
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
func Int31n(n int32) int32 { return globalRand.Int31n(n) } func Int31n(n int32) int32 { return globalRand.Int31n(n) }
// Intn returns, as an int, a non-negative pseudo-random number in [0,n). // Intn returns, as an int, a non-negative pseudo-random number in [0,n).
func Intn(n int) int { return globalRand.Intn(n) } func Intn(n int) int { return globalRand.Intn(n) }
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
func Float64() float64 { return globalRand.Float64() } func Float64() float64 { return globalRand.Float64() }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func Float32() float32 { return globalRand.Float32() } func Float32() float32 { return globalRand.Float32() }
// Float returns, as a float, a pseudo-random number in [0.0,1.0). // Float returns, as a float, a pseudo-random number in [0.0,1.0).
func Float() float { return globalRand.Float() } func Float() float { return globalRand.Float() }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func Perm(n int) []int { return globalRand.Perm(n) } func Perm(n int) []int { return globalRand.Perm(n) }
// NormFloat64 returns a normally distributed float64 in the range // NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with // [-math.MaxFloat64, +math.MaxFloat64] with
@ -139,7 +139,7 @@ func Perm(n int) []int { return globalRand.Perm(n) }
// //
// sample = NormFloat64() * desiredStdDev + desiredMean // sample = NormFloat64() * desiredStdDev + desiredMean
// //
func NormFloat64() float64 { return globalRand.NormFloat64() } func NormFloat64() float64 { return globalRand.NormFloat64() }
// ExpFloat64 returns an exponentially distributed float64 in the range // ExpFloat64 returns an exponentially distributed float64 in the range
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter // (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
@ -149,22 +149,22 @@ func NormFloat64() float64 { return globalRand.NormFloat64() }
// //
// sample = ExpFloat64() / desiredRateParameter // sample = ExpFloat64() / desiredRateParameter
// //
func ExpFloat64() float64 { return globalRand.ExpFloat64() } func ExpFloat64() float64 { return globalRand.ExpFloat64() }
type lockedSource struct { type lockedSource struct {
lk sync.Mutex; lk sync.Mutex
src Source; src Source
} }
func (r *lockedSource) Int63() (n int64) { func (r *lockedSource) Int63() (n int64) {
r.lk.Lock(); r.lk.Lock()
n = r.src.Int63(); n = r.src.Int63()
r.lk.Unlock(); r.lk.Unlock()
return; return
} }
func (r *lockedSource) Seed(seed int64) { func (r *lockedSource) Seed(seed int64) {
r.lk.Lock(); r.lk.Lock()
r.src.Seed(seed); r.src.Seed(seed)
r.lk.Unlock(); r.lk.Unlock()
} }

View File

@ -5,36 +5,36 @@
package rand package rand
import ( import (
"math"; "math"
"fmt"; "fmt"
"os"; "os"
"testing"; "testing"
) )
const ( const (
numTestSamples = 10000; numTestSamples = 10000
) )
type statsResults struct { type statsResults struct {
mean float64; mean float64
stddev float64; stddev float64
closeEnough float64; closeEnough float64
maxError float64; maxError float64
} }
func max(a, b float64) float64 { func max(a, b float64) float64 {
if a > b { if a > b {
return a return a
} }
return b; return b
} }
func nearEqual(a, b, closeEnough, maxError float64) bool { func nearEqual(a, b, closeEnough, maxError float64) bool {
absDiff := math.Fabs(a - b); absDiff := math.Fabs(a - b)
if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero. if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
return true return true
} }
return absDiff/max(math.Fabs(a), math.Fabs(b)) < maxError; return absDiff/max(math.Fabs(a), math.Fabs(b)) < maxError
} }
var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961} var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
@ -43,52 +43,52 @@ var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
// two statsResults are similar. // two statsResults are similar.
func (this *statsResults) checkSimilarDistribution(expected *statsResults) os.Error { func (this *statsResults) checkSimilarDistribution(expected *statsResults) os.Error {
if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) { if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError); s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError)
fmt.Println(s); fmt.Println(s)
return os.ErrorString(s); return os.ErrorString(s)
} }
if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) { if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) {
s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError); s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError)
fmt.Println(s); fmt.Println(s)
return os.ErrorString(s); return os.ErrorString(s)
} }
return nil; return nil
} }
func getStatsResults(samples []float64) *statsResults { func getStatsResults(samples []float64) *statsResults {
res := new(statsResults); res := new(statsResults)
var sum float64; var sum float64
for i := range samples { for i := range samples {
sum += samples[i] sum += samples[i]
} }
res.mean = sum / float64(len(samples)); res.mean = sum / float64(len(samples))
var devsum float64; var devsum float64
for i := range samples { for i := range samples {
devsum += math.Pow(samples[i]-res.mean, 2) devsum += math.Pow(samples[i]-res.mean, 2)
} }
res.stddev = math.Sqrt(devsum / float64(len(samples))); res.stddev = math.Sqrt(devsum / float64(len(samples)))
return res; return res
} }
func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) { func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
actual := getStatsResults(samples); actual := getStatsResults(samples)
err := actual.checkSimilarDistribution(expected); err := actual.checkSimilarDistribution(expected)
if err != nil { if err != nil {
t.Errorf(err.String()) t.Errorf(err.String())
} }
} }
func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) { func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
chunk := len(samples) / nslices; chunk := len(samples) / nslices
for i := 0; i < nslices; i++ { for i := 0; i < nslices; i++ {
low := i * chunk; low := i * chunk
var high int; var high int
if i == nslices-1 { if i == nslices-1 {
high = len(samples) - 1 high = len(samples) - 1
} else { } else {
high = (i + 1) * chunk high = (i + 1) * chunk
} }
checkSampleDistribution(t, samples[low:high], expected); checkSampleDistribution(t, samples[low:high], expected)
} }
} }
@ -97,29 +97,29 @@ func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int,
// //
func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 { func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
r := New(NewSource(seed)); r := New(NewSource(seed))
samples := make([]float64, nsamples); samples := make([]float64, nsamples)
for i := range samples { for i := range samples {
samples[i] = r.NormFloat64()*stddev + mean samples[i] = r.NormFloat64()*stddev + mean
} }
return samples; return samples
} }
func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) { func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
//fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed); //fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
samples := generateNormalSamples(nsamples, mean, stddev, seed); samples := generateNormalSamples(nsamples, mean, stddev, seed)
errorScale := max(1.0, stddev); // Error scales with stddev errorScale := max(1.0, stddev) // Error scales with stddev
expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}; expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
// Make sure that the entire set matches the expected distribution. // Make sure that the entire set matches the expected distribution.
checkSampleDistribution(t, samples, expected); checkSampleDistribution(t, samples, expected)
// Make sure that each half of the set matches the expected distribution. // Make sure that each half of the set matches the expected distribution.
checkSampleSliceDistributions(t, samples, 2, expected); checkSampleSliceDistributions(t, samples, 2, expected)
// Make sure that each 7th of the set matches the expected distribution. // Make sure that each 7th of the set matches the expected distribution.
checkSampleSliceDistributions(t, samples, 7, expected); checkSampleSliceDistributions(t, samples, 7, expected)
} }
// Actual tests // Actual tests
@ -145,32 +145,32 @@ func TestNonStandardNormalValues(t *testing.T) {
// //
func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 { func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
r := New(NewSource(seed)); r := New(NewSource(seed))
samples := make([]float64, nsamples); samples := make([]float64, nsamples)
for i := range samples { for i := range samples {
samples[i] = r.ExpFloat64() / rate samples[i] = r.ExpFloat64() / rate
} }
return samples; return samples
} }
func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) { func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
//fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed); //fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
mean := 1 / rate; mean := 1 / rate
stddev := mean; stddev := mean
samples := generateExponentialSamples(nsamples, rate, seed); samples := generateExponentialSamples(nsamples, rate, seed)
errorScale := max(1.0, 1/rate); // Error scales with the inverse of the rate errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate
expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}; expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}
// Make sure that the entire set matches the expected distribution. // Make sure that the entire set matches the expected distribution.
checkSampleDistribution(t, samples, expected); checkSampleDistribution(t, samples, expected)
// Make sure that each half of the set matches the expected distribution. // Make sure that each half of the set matches the expected distribution.
checkSampleSliceDistributions(t, samples, 2, expected); checkSampleSliceDistributions(t, samples, 2, expected)
// Make sure that each 7th of the set matches the expected distribution. // Make sure that each 7th of the set matches the expected distribution.
checkSampleSliceDistributions(t, samples, 7, expected); checkSampleSliceDistributions(t, samples, 7, expected)
} }
// Actual tests // Actual tests
@ -194,61 +194,61 @@ func TestNonStandardExponentialValues(t *testing.T) {
// //
func initNorm() (testKn []uint32, testWn, testFn []float32) { func initNorm() (testKn []uint32, testWn, testFn []float32) {
const m1 = 1 << 31; const m1 = 1 << 31
var ( var (
dn float64 = rn; dn float64 = rn
tn = dn; tn = dn
vn float64 = 9.91256303526217e-3; vn float64 = 9.91256303526217e-3
) )
testKn = make([]uint32, 128); testKn = make([]uint32, 128)
testWn = make([]float32, 128); testWn = make([]float32, 128)
testFn = make([]float32, 128); testFn = make([]float32, 128)
q := vn / math.Exp(-0.5*dn*dn); q := vn / math.Exp(-0.5*dn*dn)
testKn[0] = uint32((dn / q) * m1); testKn[0] = uint32((dn / q) * m1)
testKn[1] = 0; testKn[1] = 0
testWn[0] = float32(q / m1); testWn[0] = float32(q / m1)
testWn[127] = float32(dn / m1); testWn[127] = float32(dn / m1)
testFn[0] = 1.0; testFn[0] = 1.0
testFn[127] = float32(math.Exp(-0.5 * dn * dn)); testFn[127] = float32(math.Exp(-0.5 * dn * dn))
for i := 126; i >= 1; i-- { for i := 126; i >= 1; i-- {
dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn))); dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)))
testKn[i+1] = uint32((dn / tn) * m1); testKn[i+1] = uint32((dn / tn) * m1)
tn = dn; tn = dn
testFn[i] = float32(math.Exp(-0.5 * dn * dn)); testFn[i] = float32(math.Exp(-0.5 * dn * dn))
testWn[i] = float32(dn / m1); testWn[i] = float32(dn / m1)
} }
return; return
} }
func initExp() (testKe []uint32, testWe, testFe []float32) { func initExp() (testKe []uint32, testWe, testFe []float32) {
const m2 = 1 << 32; const m2 = 1 << 32
var ( var (
de float64 = re; de float64 = re
te = de; te = de
ve float64 = 3.9496598225815571993e-3; ve float64 = 3.9496598225815571993e-3
) )
testKe = make([]uint32, 256); testKe = make([]uint32, 256)
testWe = make([]float32, 256); testWe = make([]float32, 256)
testFe = make([]float32, 256); testFe = make([]float32, 256)
q := ve / math.Exp(-de); q := ve / math.Exp(-de)
testKe[0] = uint32((de / q) * m2); testKe[0] = uint32((de / q) * m2)
testKe[1] = 0; testKe[1] = 0
testWe[0] = float32(q / m2); testWe[0] = float32(q / m2)
testWe[255] = float32(de / m2); testWe[255] = float32(de / m2)
testFe[0] = 1.0; testFe[0] = 1.0
testFe[255] = float32(math.Exp(-de)); testFe[255] = float32(math.Exp(-de))
for i := 254; i >= 1; i-- { for i := 254; i >= 1; i-- {
de = -math.Log(ve/de + math.Exp(-de)); de = -math.Log(ve/de + math.Exp(-de))
testKe[i+1] = uint32((de / te) * m2); testKe[i+1] = uint32((de / te) * m2)
te = de; te = de
testFe[i] = float32(math.Exp(-de)); testFe[i] = float32(math.Exp(-de))
testWe[i] = float32(de / m2); testWe[i] = float32(de / m2)
} }
return; return
} }
// compareUint32Slices returns the first index where the two slices // compareUint32Slices returns the first index where the two slices
@ -259,14 +259,14 @@ func compareUint32Slices(s1, s2 []uint32) int {
if len(s1) > len(s2) { if len(s1) > len(s2) {
return len(s2) + 1 return len(s2) + 1
} }
return len(s1) + 1; return len(s1) + 1
} }
for i := range s1 { for i := range s1 {
if s1[i] != s2[i] { if s1[i] != s2[i] {
return i return i
} }
} }
return -1; return -1
} }
// compareFloat32Slices returns the first index where the two slices // compareFloat32Slices returns the first index where the two slices
@ -277,18 +277,18 @@ func compareFloat32Slices(s1, s2 []float32) int {
if len(s1) > len(s2) { if len(s1) > len(s2) {
return len(s2) + 1 return len(s2) + 1
} }
return len(s1) + 1; return len(s1) + 1
} }
for i := range s1 { for i := range s1 {
if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) { if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
return i return i
} }
} }
return -1; return -1
} }
func TestNormTables(t *testing.T) { func TestNormTables(t *testing.T) {
testKn, testWn, testFn := initNorm(); testKn, testWn, testFn := initNorm()
if i := compareUint32Slices(kn[0:], testKn); i >= 0 { if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
t.Errorf("kn disagrees at index %v; %v != %v\n", i, kn[i], testKn[i]) t.Errorf("kn disagrees at index %v; %v != %v\n", i, kn[i], testKn[i])
} }
@ -301,7 +301,7 @@ func TestNormTables(t *testing.T) {
} }
func TestExpTables(t *testing.T) { func TestExpTables(t *testing.T) {
testKe, testWe, testFe := initExp(); testKe, testWe, testFe := initExp()
if i := compareUint32Slices(ke[0:], testKe); i >= 0 { if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
t.Errorf("ke disagrees at index %v; %v != %v\n", i, ke[i], testKe[i]) t.Errorf("ke disagrees at index %v; %v != %v\n", i, ke[i], testKe[i])
} }
@ -322,7 +322,7 @@ func BenchmarkInt63Threadsafe(b *testing.B) {
} }
func BenchmarkInt63Unthreadsafe(b *testing.B) { func BenchmarkInt63Unthreadsafe(b *testing.B) {
r := New(NewSource(1)); r := New(NewSource(1))
for n := b.N; n > 0; n-- { for n := b.N; n > 0; n-- {
r.Int63() r.Int63()
} }

View File

@ -12,14 +12,14 @@ package rand
*/ */
const ( const (
_LEN = 607; _LEN = 607
_TAP = 273; _TAP = 273
_MAX = 1 << 63; _MAX = 1 << 63
_MASK = _MAX - 1; _MASK = _MAX - 1
_A = 48271; _A = 48271
_M = (1 << 31) - 1; _M = (1 << 31) - 1
_Q = 44488; _Q = 44488
_R = 3399; _R = 3399
) )
var ( var (
@ -179,32 +179,32 @@ var (
4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425, 4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425,
7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134, 7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134,
8382142935188824023, 9103922860780351547, 4152330101494654406, 8382142935188824023, 9103922860780351547, 4152330101494654406,
}; }
) )
type rngSource struct { type rngSource struct {
tap int; // index into vec tap int // index into vec
feed int; // index into vec feed int // index into vec
vec [_LEN]int64; // current feedback register vec [_LEN]int64 // current feedback register
} }
// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1) // seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
func seedrand(x int32) int32 { func seedrand(x int32) int32 {
hi := x / _Q; hi := x / _Q
lo := x % _Q; lo := x % _Q
x = _A*lo - _R*hi; x = _A*lo - _R*hi
if x < 0 { if x < 0 {
x += _M x += _M
} }
return x; return x
} }
// Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed uses the provided seed value to initialize the generator to a deterministic state.
func (rng *rngSource) Seed(seed int64) { func (rng *rngSource) Seed(seed int64) {
rng.tap = 0; rng.tap = 0
rng.feed = _LEN - _TAP; rng.feed = _LEN - _TAP
seed = seed % _M; seed = seed % _M
if seed < 0 { if seed < 0 {
seed += _M seed += _M
} }
@ -212,35 +212,35 @@ func (rng *rngSource) Seed(seed int64) {
seed = 89482311 seed = 89482311
} }
x := int32(seed); x := int32(seed)
for i := -20; i < _LEN; i++ { for i := -20; i < _LEN; i++ {
x = seedrand(x); x = seedrand(x)
if i >= 0 { if i >= 0 {
var u int64; var u int64
u = int64(x) << 40; u = int64(x) << 40
x = seedrand(x); x = seedrand(x)
u ^= int64(x) << 20; u ^= int64(x) << 20
x = seedrand(x); x = seedrand(x)
u ^= int64(x); u ^= int64(x)
u ^= rng_cooked[i]; u ^= rng_cooked[i]
rng.vec[i] = u & _MASK; rng.vec[i] = u & _MASK
} }
} }
} }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (rng *rngSource) Int63() int64 { func (rng *rngSource) Int63() int64 {
rng.tap--; rng.tap--
if rng.tap < 0 { if rng.tap < 0 {
rng.tap += _LEN rng.tap += _LEN
} }
rng.feed--; rng.feed--
if rng.feed < 0 { if rng.feed < 0 {
rng.feed += _LEN rng.feed += _LEN
} }
x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK; x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK
rng.vec[rng.feed] = x; rng.vec[rng.feed] = x
return x; return x
} }

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,10 @@ package reflect
// checks in progress are true when it reencounters them. // checks in progress are true when it reencounters them.
// Visited are stored in a map indexed by 17 * a1 + a2; // Visited are stored in a map indexed by 17 * a1 + a2;
type visit struct { type visit struct {
a1 uintptr; a1 uintptr
a2 uintptr; a2 uintptr
typ Type; typ Type
next *visit; next *visit
} }
// Tests for deep equality using reflected types. The map argument tracks // Tests for deep equality using reflected types. The map argument tracks
@ -31,8 +31,8 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
// if depth > 10 { panic("deepValueEqual") } // for debugging // if depth > 10 { panic("deepValueEqual") } // for debugging
addr1 := v1.Addr(); addr1 := v1.Addr()
addr2 := v2.Addr(); addr2 := v2.Addr()
if addr1 > addr2 { if addr1 > addr2 {
// Canonicalize order to reduce number of entries in visited. // Canonicalize order to reduce number of entries in visited.
addr1, addr2 = addr2, addr1 addr1, addr2 = addr2, addr1
@ -44,9 +44,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
} }
// ... or already seen // ... or already seen
h := 17*addr1 + addr2; h := 17*addr1 + addr2
seen, _ := visited[h]; seen, _ := visited[h]
typ := v1.Type(); typ := v1.Type()
for p := seen; p != nil; p = p.next { for p := seen; p != nil; p = p.next {
if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ { if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
return true return true
@ -54,12 +54,12 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
} }
// Remember for later. // Remember for later.
visited[h] = &visit{addr1, addr2, typ, seen}; visited[h] = &visit{addr1, addr2, typ, seen}
switch v := v1.(type) { switch v := v1.(type) {
case *ArrayValue: case *ArrayValue:
arr1 := v; arr1 := v
arr2 := v2.(*ArrayValue); arr2 := v2.(*ArrayValue)
if arr1.Len() != arr2.Len() { if arr1.Len() != arr2.Len() {
return false return false
} }
@ -68,10 +68,10 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
return false return false
} }
} }
return true; return true
case *SliceValue: case *SliceValue:
arr1 := v; arr1 := v
arr2 := v2.(*SliceValue); arr2 := v2.(*SliceValue)
if arr1.Len() != arr2.Len() { if arr1.Len() != arr2.Len() {
return false return false
} }
@ -80,28 +80,28 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
return false return false
} }
} }
return true; return true
case *InterfaceValue: case *InterfaceValue:
i1 := v.Interface(); i1 := v.Interface()
i2 := v2.Interface(); i2 := v2.Interface()
if i1 == nil || i2 == nil { if i1 == nil || i2 == nil {
return i1 == i2 return i1 == i2
} }
return deepValueEqual(NewValue(i1), NewValue(i2), visited, depth+1); return deepValueEqual(NewValue(i1), NewValue(i2), visited, depth+1)
case *PtrValue: case *PtrValue:
return deepValueEqual(v.Elem(), v2.(*PtrValue).Elem(), visited, depth+1) return deepValueEqual(v.Elem(), v2.(*PtrValue).Elem(), visited, depth+1)
case *StructValue: case *StructValue:
struct1 := v; struct1 := v
struct2 := v2.(*StructValue); struct2 := v2.(*StructValue)
for i, n := 0, v.NumField(); i < n; i++ { for i, n := 0, v.NumField(); i < n; i++ {
if !deepValueEqual(struct1.Field(i), struct2.Field(i), visited, depth+1) { if !deepValueEqual(struct1.Field(i), struct2.Field(i), visited, depth+1) {
return false return false
} }
} }
return true; return true
case *MapValue: case *MapValue:
map1 := v; map1 := v
map2 := v2.(*MapValue); map2 := v2.(*MapValue)
if map1.Len() != map2.Len() { if map1.Len() != map2.Len() {
return false return false
} }
@ -110,13 +110,13 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
return false return false
} }
} }
return true; return true
default: default:
// Normal equality suffices // Normal equality suffices
return v1.Interface() == v2.Interface() return v1.Interface() == v2.Interface()
} }
panic("Not reached"); panic("Not reached")
} }
// DeepEqual tests for deep equality. It uses normal == equality where possible // DeepEqual tests for deep equality. It uses normal == equality where possible
@ -126,10 +126,10 @@ func DeepEqual(a1, a2 interface{}) bool {
if a1 == nil || a2 == nil { if a1 == nil || a2 == nil {
return a1 == a2 return a1 == a2
} }
v1 := NewValue(a1); v1 := NewValue(a1)
v2 := NewValue(a2); v2 := NewValue(a2)
if v1.Type() != v2.Type() { if v1.Type() != v2.Type() {
return false return false
} }
return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0); return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0)
} }

View File

@ -9,18 +9,18 @@
package reflect_test package reflect_test
import ( import (
. "reflect"; . "reflect"
"strconv"; "strconv"
) )
// valueToString returns a textual representation of the reflection value val. // valueToString returns a textual representation of the reflection value val.
// For debugging only. // For debugging only.
func valueToString(val Value) string { func valueToString(val Value) string {
var str string; var str string
if val == nil { if val == nil {
return "<nil>" return "<nil>"
} }
typ := val.Type(); typ := val.Type()
switch val := val.(type) { switch val := val.(type) {
case *IntValue: case *IntValue:
return strconv.Uitoa64(uint64(val.Get())) return strconv.Uitoa64(uint64(val.Get()))
@ -61,57 +61,57 @@ func valueToString(val Value) string {
return "false" return "false"
} }
case *PtrValue: case *PtrValue:
v := val; v := val
str = typ.String() + "("; str = typ.String() + "("
if v.IsNil() { if v.IsNil() {
str += "0" str += "0"
} else { } else {
str += "&" + valueToString(v.Elem()) str += "&" + valueToString(v.Elem())
} }
str += ")"; str += ")"
return str; return str
case ArrayOrSliceValue: case ArrayOrSliceValue:
v := val; v := val
str += typ.String(); str += typ.String()
str += "{"; str += "{"
for i := 0; i < v.Len(); i++ { for i := 0; i < v.Len(); i++ {
if i > 0 { if i > 0 {
str += ", " str += ", "
} }
str += valueToString(v.Elem(i)); str += valueToString(v.Elem(i))
} }
str += "}"; str += "}"
return str; return str
case *MapValue: case *MapValue:
t := typ.(*MapType); t := typ.(*MapType)
str = t.String(); str = t.String()
str += "{"; str += "{"
str += "<can't iterate on maps>"; str += "<can't iterate on maps>"
str += "}"; str += "}"
return str; return str
case *ChanValue: case *ChanValue:
str = typ.String(); str = typ.String()
return str; return str
case *StructValue: case *StructValue:
t := typ.(*StructType); t := typ.(*StructType)
v := val; v := val
str += t.String(); str += t.String()
str += "{"; str += "{"
for i, n := 0, v.NumField(); i < n; i++ { for i, n := 0, v.NumField(); i < n; i++ {
if i > 0 { if i > 0 {
str += ", " str += ", "
} }
str += valueToString(v.Field(i)); str += valueToString(v.Field(i))
} }
str += "}"; str += "}"
return str; return str
case *InterfaceValue: case *InterfaceValue:
return typ.String() + "(" + valueToString(val.Elem()) + ")" return typ.String() + "(" + valueToString(val.Elem()) + ")"
case *FuncValue: case *FuncValue:
v := val; v := val
return typ.String() + "(" + strconv.Itoa64(int64(v.Get())) + ")"; return typ.String() + "(" + strconv.Itoa64(int64(v.Get())) + ")"
default: default:
panicln("valueToString: can't print type ", typ.String()) panicln("valueToString: can't print type ", typ.String())
} }
return "valueToString: can't happen"; return "valueToString: can't happen"
} }

View File

@ -16,9 +16,9 @@
package reflect package reflect
import ( import (
"runtime"; "runtime"
"strconv"; "strconv"
"unsafe"; "unsafe"
) )
/* /*
@ -35,198 +35,198 @@ import (
*/ */
type commonType struct { type commonType struct {
size uintptr; size uintptr
hash uint32; hash uint32
alg uint8; alg uint8
align uint8; align uint8
fieldAlign uint8; fieldAlign uint8
string *string; string *string
*uncommonType; *uncommonType
} }
type method struct { type method struct {
hash uint32; hash uint32
name *string; name *string
pkgPath *string; pkgPath *string
typ *runtime.Type; typ *runtime.Type
ifn unsafe.Pointer; ifn unsafe.Pointer
tfn unsafe.Pointer; tfn unsafe.Pointer
} }
type uncommonType struct { type uncommonType struct {
name *string; name *string
pkgPath *string; pkgPath *string
methods []method; methods []method
} }
// BoolType represents a boolean type. // BoolType represents a boolean type.
type BoolType struct { type BoolType struct {
commonType; commonType
} }
// Float32Type represents a float32 type. // Float32Type represents a float32 type.
type Float32Type struct { type Float32Type struct {
commonType; commonType
} }
// Float64Type represents a float64 type. // Float64Type represents a float64 type.
type Float64Type struct { type Float64Type struct {
commonType; commonType
} }
// FloatType represents a float type. // FloatType represents a float type.
type FloatType struct { type FloatType struct {
commonType; commonType
} }
// Int16Type represents an int16 type. // Int16Type represents an int16 type.
type Int16Type struct { type Int16Type struct {
commonType; commonType
} }
// Int32Type represents an int32 type. // Int32Type represents an int32 type.
type Int32Type struct { type Int32Type struct {
commonType; commonType
} }
// Int64Type represents an int64 type. // Int64Type represents an int64 type.
type Int64Type struct { type Int64Type struct {
commonType; commonType
} }
// Int8Type represents an int8 type. // Int8Type represents an int8 type.
type Int8Type struct { type Int8Type struct {
commonType; commonType
} }
// IntType represents an int type. // IntType represents an int type.
type IntType struct { type IntType struct {
commonType; commonType
} }
// Uint16Type represents a uint16 type. // Uint16Type represents a uint16 type.
type Uint16Type struct { type Uint16Type struct {
commonType; commonType
} }
// Uint32Type represents a uint32 type. // Uint32Type represents a uint32 type.
type Uint32Type struct { type Uint32Type struct {
commonType; commonType
} }
// Uint64Type represents a uint64 type. // Uint64Type represents a uint64 type.
type Uint64Type struct { type Uint64Type struct {
commonType; commonType
} }
// Uint8Type represents a uint8 type. // Uint8Type represents a uint8 type.
type Uint8Type struct { type Uint8Type struct {
commonType; commonType
} }
// UintType represents a uint type. // UintType represents a uint type.
type UintType struct { type UintType struct {
commonType; commonType
} }
// StringType represents a string type. // StringType represents a string type.
type StringType struct { type StringType struct {
commonType; commonType
} }
// UintptrType represents a uintptr type. // UintptrType represents a uintptr type.
type UintptrType struct { type UintptrType struct {
commonType; commonType
} }
// DotDotDotType represents the ... that can // DotDotDotType represents the ... that can
// be used as the type of the final function parameter. // be used as the type of the final function parameter.
type DotDotDotType struct { type DotDotDotType struct {
commonType; commonType
} }
// UnsafePointerType represents an unsafe.Pointer type. // UnsafePointerType represents an unsafe.Pointer type.
type UnsafePointerType struct { type UnsafePointerType struct {
commonType; commonType
} }
// ArrayType represents a fixed array type. // ArrayType represents a fixed array type.
type ArrayType struct { type ArrayType struct {
commonType; commonType
elem *runtime.Type; elem *runtime.Type
len uintptr; len uintptr
} }
// ChanDir represents a channel type's direction. // ChanDir represents a channel type's direction.
type ChanDir int type ChanDir int
const ( const (
RecvDir ChanDir = 1 << iota; RecvDir ChanDir = 1 << iota
SendDir; SendDir
BothDir = RecvDir | SendDir; BothDir = RecvDir | SendDir
) )
// ChanType represents a channel type. // ChanType represents a channel type.
type ChanType struct { type ChanType struct {
commonType; commonType
elem *runtime.Type; elem *runtime.Type
dir uintptr; dir uintptr
} }
// FuncType represents a function type. // FuncType represents a function type.
type FuncType struct { type FuncType struct {
commonType; commonType
in []*runtime.Type; in []*runtime.Type
out []*runtime.Type; out []*runtime.Type
} }
// Method on interface type // Method on interface type
type imethod struct { type imethod struct {
hash uint32; hash uint32
perm uint32; perm uint32
name *string; name *string
pkgPath *string; pkgPath *string
typ *runtime.Type; typ *runtime.Type
} }
// InterfaceType represents an interface type. // InterfaceType represents an interface type.
type InterfaceType struct { type InterfaceType struct {
commonType; commonType
methods []imethod; methods []imethod
} }
// MapType represents a map type. // MapType represents a map type.
type MapType struct { type MapType struct {
commonType; commonType
key *runtime.Type; key *runtime.Type
elem *runtime.Type; elem *runtime.Type
} }
// PtrType represents a pointer type. // PtrType represents a pointer type.
type PtrType struct { type PtrType struct {
commonType; commonType
elem *runtime.Type; elem *runtime.Type
} }
// SliceType represents a slice type. // SliceType represents a slice type.
type SliceType struct { type SliceType struct {
commonType; commonType
elem *runtime.Type; elem *runtime.Type
} }
// Struct field // Struct field
type structField struct { type structField struct {
name *string; name *string
pkgPath *string; pkgPath *string
typ *runtime.Type; typ *runtime.Type
tag *string; tag *string
offset uintptr; offset uintptr
} }
// StructType represents a struct type. // StructType represents a struct type.
type StructType struct { type StructType struct {
commonType; commonType
fields []structField; fields []structField
} }
@ -237,10 +237,10 @@ type StructType struct {
// Method represents a single method. // Method represents a single method.
type Method struct { type Method struct {
PkgPath string; // empty for uppercase Name PkgPath string // empty for uppercase Name
Name string; Name string
Type *FuncType; Type *FuncType
Func *FuncValue; Func *FuncValue
} }
// Type is the runtime representation of a Go type. // Type is the runtime representation of a Go type.
@ -253,37 +253,37 @@ type Type interface {
// PkgPath returns the type's package path. // PkgPath returns the type's package path.
// The package path is a full package import path like "container/vector". // The package path is a full package import path like "container/vector".
// PkgPath returns an empty string for unnamed types. // PkgPath returns an empty string for unnamed types.
PkgPath() string; PkgPath() string
// Name returns the type's name within its package. // Name returns the type's name within its package.
// Name returns an empty string for unnamed types. // Name returns an empty string for unnamed types.
Name() string; Name() string
// String returns a string representation of the type. // String returns a string representation of the type.
// The string representation may use shortened package names // The string representation may use shortened package names
// (e.g., vector instead of "container/vector") and is not // (e.g., vector instead of "container/vector") and is not
// guaranteed to be unique among types. To test for equality, // guaranteed to be unique among types. To test for equality,
// compare the Types directly. // compare the Types directly.
String() string; String() string
// Size returns the number of bytes needed to store // Size returns the number of bytes needed to store
// a value of the given type; it is analogous to unsafe.Sizeof. // a value of the given type; it is analogous to unsafe.Sizeof.
Size() uintptr; Size() uintptr
// Align returns the alignment of a value of this type // Align returns the alignment of a value of this type
// when allocated in memory. // when allocated in memory.
Align() int; Align() int
// FieldAlign returns the alignment of a value of this type // FieldAlign returns the alignment of a value of this type
// when used as a field in a struct. // when used as a field in a struct.
FieldAlign() int; FieldAlign() int
// For non-interface types, Method returns the i'th method with receiver T. // For non-interface types, Method returns the i'th method with receiver T.
// For interface types, Method returns the i'th method in the interface. // For interface types, Method returns the i'th method in the interface.
// NumMethod returns the number of such methods. // NumMethod returns the number of such methods.
Method(int) Method; Method(int) Method
NumMethod() int; NumMethod() int
uncommon() *uncommonType; uncommon() *uncommonType
} }
func (t *uncommonType) uncommon() *uncommonType { func (t *uncommonType) uncommon() *uncommonType {
@ -294,70 +294,70 @@ func (t *uncommonType) PkgPath() string {
if t == nil || t.pkgPath == nil { if t == nil || t.pkgPath == nil {
return "" return ""
} }
return *t.pkgPath; return *t.pkgPath
} }
func (t *uncommonType) Name() string { func (t *uncommonType) Name() string {
if t == nil || t.name == nil { if t == nil || t.name == nil {
return "" return ""
} }
return *t.name; return *t.name
} }
func (t *commonType) String() string { return *t.string } func (t *commonType) String() string { return *t.string }
func (t *commonType) Size() uintptr { return t.size } func (t *commonType) Size() uintptr { return t.size }
func (t *commonType) Align() int { return int(t.align) } func (t *commonType) Align() int { return int(t.align) }
func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } func (t *commonType) FieldAlign() int { return int(t.fieldAlign) }
func (t *uncommonType) Method(i int) (m Method) { func (t *uncommonType) Method(i int) (m Method) {
if t == nil || i < 0 || i >= len(t.methods) { if t == nil || i < 0 || i >= len(t.methods) {
return return
} }
p := &t.methods[i]; p := &t.methods[i]
if p.name != nil { if p.name != nil {
m.Name = *p.name m.Name = *p.name
} }
if p.pkgPath != nil { if p.pkgPath != nil {
m.PkgPath = *p.pkgPath m.PkgPath = *p.pkgPath
} }
m.Type = toType(*p.typ).(*FuncType); m.Type = toType(*p.typ).(*FuncType)
fn := p.tfn; fn := p.tfn
m.Func = newFuncValue(m.Type, addr(&fn), true); m.Func = newFuncValue(m.Type, addr(&fn), true)
return; return
} }
func (t *uncommonType) NumMethod() int { func (t *uncommonType) NumMethod() int {
if t == nil { if t == nil {
return 0 return 0
} }
return len(t.methods); return len(t.methods)
} }
// TODO(rsc): 6g supplies these, but they are not // TODO(rsc): 6g supplies these, but they are not
// as efficient as they could be: they have commonType // as efficient as they could be: they have commonType
// as the receiver instead of *commonType. // as the receiver instead of *commonType.
func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() } func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() }
func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) } func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) }
func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() } func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() }
func (t *commonType) Name() string { return t.uncommonType.Name() } func (t *commonType) Name() string { return t.uncommonType.Name() }
// Len returns the number of elements in the array. // Len returns the number of elements in the array.
func (t *ArrayType) Len() int { return int(t.len) } func (t *ArrayType) Len() int { return int(t.len) }
// Elem returns the type of the array's elements. // Elem returns the type of the array's elements.
func (t *ArrayType) Elem() Type { return toType(*t.elem) } func (t *ArrayType) Elem() Type { return toType(*t.elem) }
// Dir returns the channel direction. // Dir returns the channel direction.
func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) } func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) }
// Elem returns the channel's element type. // Elem returns the channel's element type.
func (t *ChanType) Elem() Type { return toType(*t.elem) } func (t *ChanType) Elem() Type { return toType(*t.elem) }
func (d ChanDir) String() string { func (d ChanDir) String() string {
switch d { switch d {
@ -368,7 +368,7 @@ func (d ChanDir) String() string {
case BothDir: case BothDir:
return "chan" return "chan"
} }
return "ChanDir" + strconv.Itoa(int(d)); return "ChanDir" + strconv.Itoa(int(d))
} }
// In returns the type of the i'th function input parameter. // In returns the type of the i'th function input parameter.
@ -376,60 +376,60 @@ func (t *FuncType) In(i int) Type {
if i < 0 || i >= len(t.in) { if i < 0 || i >= len(t.in) {
return nil return nil
} }
return toType(*t.in[i]); return toType(*t.in[i])
} }
// NumIn returns the number of input parameters. // NumIn returns the number of input parameters.
func (t *FuncType) NumIn() int { return len(t.in) } func (t *FuncType) NumIn() int { return len(t.in) }
// Out returns the type of the i'th function output parameter. // Out returns the type of the i'th function output parameter.
func (t *FuncType) Out(i int) Type { func (t *FuncType) Out(i int) Type {
if i < 0 || i >= len(t.out) { if i < 0 || i >= len(t.out) {
return nil return nil
} }
return toType(*t.out[i]); return toType(*t.out[i])
} }
// NumOut returns the number of function output parameters. // NumOut returns the number of function output parameters.
func (t *FuncType) NumOut() int { return len(t.out) } func (t *FuncType) NumOut() int { return len(t.out) }
// Method returns the i'th interface method. // Method returns the i'th interface method.
func (t *InterfaceType) Method(i int) (m Method) { func (t *InterfaceType) Method(i int) (m Method) {
if i < 0 || i >= len(t.methods) { if i < 0 || i >= len(t.methods) {
return return
} }
p := &t.methods[i]; p := &t.methods[i]
m.Name = *p.name; m.Name = *p.name
if p.pkgPath != nil { if p.pkgPath != nil {
m.PkgPath = *p.pkgPath m.PkgPath = *p.pkgPath
} }
m.Type = toType(*p.typ).(*FuncType); m.Type = toType(*p.typ).(*FuncType)
return; return
} }
// NumMethod returns the number of interface methods. // NumMethod returns the number of interface methods.
func (t *InterfaceType) NumMethod() int { return len(t.methods) } func (t *InterfaceType) NumMethod() int { return len(t.methods) }
// Key returns the map key type. // Key returns the map key type.
func (t *MapType) Key() Type { return toType(*t.key) } func (t *MapType) Key() Type { return toType(*t.key) }
// Elem returns the map element type. // Elem returns the map element type.
func (t *MapType) Elem() Type { return toType(*t.elem) } func (t *MapType) Elem() Type { return toType(*t.elem) }
// Elem returns the pointer element type. // Elem returns the pointer element type.
func (t *PtrType) Elem() Type { return toType(*t.elem) } func (t *PtrType) Elem() Type { return toType(*t.elem) }
// Elem returns the type of the slice's elements. // Elem returns the type of the slice's elements.
func (t *SliceType) Elem() Type { return toType(*t.elem) } func (t *SliceType) Elem() Type { return toType(*t.elem) }
type StructField struct { type StructField struct {
PkgPath string; // empty for uppercase Name PkgPath string // empty for uppercase Name
Name string; Name string
Type Type; Type Type
Tag string; Tag string
Offset uintptr; Offset uintptr
Index []int; Index []int
Anonymous bool; Anonymous bool
} }
// Field returns the i'th struct field. // Field returns the i'th struct field.
@ -437,17 +437,17 @@ func (t *StructType) Field(i int) (f StructField) {
if i < 0 || i >= len(t.fields) { if i < 0 || i >= len(t.fields) {
return return
} }
p := t.fields[i]; p := t.fields[i]
f.Type = toType(*p.typ); f.Type = toType(*p.typ)
if p.name != nil { if p.name != nil {
f.Name = *p.name f.Name = *p.name
} else { } else {
t := f.Type; t := f.Type
if pt, ok := t.(*PtrType); ok { if pt, ok := t.(*PtrType); ok {
t = pt.Elem() t = pt.Elem()
} }
f.Name = t.Name(); f.Name = t.Name()
f.Anonymous = true; f.Anonymous = true
} }
if p.pkgPath != nil { if p.pkgPath != nil {
f.PkgPath = *p.pkgPath f.PkgPath = *p.pkgPath
@ -455,9 +455,9 @@ func (t *StructType) Field(i int) (f StructField) {
if p.tag != nil { if p.tag != nil {
f.Tag = *p.tag f.Tag = *p.tag
} }
f.Offset = p.offset; f.Offset = p.offset
f.Index = []int{i}; f.Index = []int{i}
return; return
} }
// TODO(gri): Should there be an error/bool indicator if the index // TODO(gri): Should there be an error/bool indicator if the index
@ -467,45 +467,45 @@ func (t *StructType) Field(i int) (f StructField) {
func (t *StructType) FieldByIndex(index []int) (f StructField) { func (t *StructType) FieldByIndex(index []int) (f StructField) {
for i, x := range index { for i, x := range index {
if i > 0 { if i > 0 {
ft := f.Type; ft := f.Type
if pt, ok := ft.(*PtrType); ok { if pt, ok := ft.(*PtrType); ok {
ft = pt.Elem() ft = pt.Elem()
} }
if st, ok := ft.(*StructType); ok { if st, ok := ft.(*StructType); ok {
t = st t = st
} else { } else {
var f0 StructField; var f0 StructField
f = f0; f = f0
return; return
} }
} }
f = t.Field(x); f = t.Field(x)
} }
return; return
} }
const inf = 1 << 30 // infinity - no struct has that many nesting levels const inf = 1 << 30 // infinity - no struct has that many nesting levels
func (t *StructType) fieldByName(name string, mark map[*StructType]bool, depth int) (ff StructField, fd int) { func (t *StructType) fieldByName(name string, mark map[*StructType]bool, depth int) (ff StructField, fd int) {
fd = inf; // field depth fd = inf // field depth
if _, marked := mark[t]; marked { if _, marked := mark[t]; marked {
// Struct already seen. // Struct already seen.
return return
} }
mark[t] = true; mark[t] = true
var fi int; // field index var fi int // field index
n := 0; // number of matching fields at depth fd n := 0 // number of matching fields at depth fd
L: for i, _ := range t.fields { L: for i, _ := range t.fields {
f := t.Field(i); f := t.Field(i)
d := inf; d := inf
switch { switch {
case f.Name == name: case f.Name == name:
// Matching top-level field. // Matching top-level field.
d = depth d = depth
case f.Anonymous: case f.Anonymous:
ft := f.Type; ft := f.Type
if pt, ok := ft.(*PtrType); ok { if pt, ok := ft.(*PtrType); ok {
ft = pt.Elem() ft = pt.Elem()
} }
@ -524,12 +524,12 @@ L: for i, _ := range t.fields {
switch { switch {
case d < fd: case d < fd:
// Found field at shallower depth. // Found field at shallower depth.
ff, fi, fd = f, i, d; ff, fi, fd = f, i, d
n = 1; n = 1
case d == fd: case d == fd:
// More than one matching field at the same depth (or d, fd == inf). // More than one matching field at the same depth (or d, fd == inf).
// Same as no field found at this depth. // Same as no field found at this depth.
n++; n++
if d == depth { if d == depth {
// Impossible to find a field at lower depth. // Impossible to find a field at lower depth.
break L break L
@ -542,28 +542,28 @@ L: for i, _ := range t.fields {
if len(ff.Index) <= depth { if len(ff.Index) <= depth {
ff.Index = make([]int, depth+1) ff.Index = make([]int, depth+1)
} }
ff.Index[depth] = fi; ff.Index[depth] = fi
} else { } else {
// None or more than one matching field found. // None or more than one matching field found.
fd = inf fd = inf
} }
mark[t] = false, false; mark[t] = false, false
return; return
} }
// FieldByName returns the struct field with the given name // FieldByName returns the struct field with the given name
// and a boolean to indicate if the field was found. // and a boolean to indicate if the field was found.
func (t *StructType) FieldByName(name string) (f StructField, present bool) { func (t *StructType) FieldByName(name string) (f StructField, present bool) {
if ff, fd := t.fieldByName(name, make(map[*StructType]bool), 0); fd < inf { if ff, fd := t.fieldByName(name, make(map[*StructType]bool), 0); fd < inf {
ff.Index = ff.Index[0 : fd+1]; ff.Index = ff.Index[0 : fd+1]
f, present = ff, true; f, present = ff, true
} }
return; return
} }
// NumField returns the number of struct fields. // NumField returns the number of struct fields.
func (t *StructType) NumField() int { return len(t.fields) } func (t *StructType) NumField() int { return len(t.fields) }
// Convert runtime type to reflect type. // Convert runtime type to reflect type.
// Same memory layouts, different method sets. // Same memory layouts, different method sets.
@ -624,15 +624,15 @@ func toType(i interface{}) Type {
case *runtime.StructType: case *runtime.StructType:
return (*StructType)(unsafe.Pointer(v)) return (*StructType)(unsafe.Pointer(v))
} }
panicln("toType", i); panicln("toType", i)
} }
// ArrayOrSliceType is the common interface implemented // ArrayOrSliceType is the common interface implemented
// by both ArrayType and SliceType. // by both ArrayType and SliceType.
type ArrayOrSliceType interface { type ArrayOrSliceType interface {
Type; Type
Elem() Type; Elem() Type
} }
// Typeof returns the reflection Type of the value in the interface{}. // Typeof returns the reflection Type of the value in the interface{}.
func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) } func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) }

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,9 @@
package regexp package regexp
import ( import (
"os"; "os"
"strings"; "strings"
"testing"; "testing"
) )
var good_re = []string{ var good_re = []string{
@ -32,8 +32,8 @@ var good_re = []string{
// TODO: nice to do this with a map // TODO: nice to do this with a map
type stringError struct { type stringError struct {
re string; re string
err os.Error; err os.Error
} }
var bad_re = []stringError{ var bad_re = []stringError{
@ -54,9 +54,9 @@ var bad_re = []stringError{
type vec []int type vec []int
type tester struct { type tester struct {
re string; re string
text string; text string
match vec; match vec
} }
var matches = []tester{ var matches = []tester{
@ -100,27 +100,27 @@ var matches = []tester{
} }
func compileTest(t *testing.T, expr string, error os.Error) *Regexp { func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
re, err := Compile(expr); re, err := Compile(expr)
if err != error { if err != error {
t.Error("compiling `", expr, "`; unexpected error: ", err.String()) t.Error("compiling `", expr, "`; unexpected error: ", err.String())
} }
return re; return re
} }
func printVec(t *testing.T, m []int) { func printVec(t *testing.T, m []int) {
l := len(m); l := len(m)
if l == 0 { if l == 0 {
t.Log("\t<no match>") t.Log("\t<no match>")
} else { } else {
if m[len(m)-1] == -1 { if m[len(m)-1] == -1 {
m = m[0 : len(m)-2] m = m[0 : len(m)-2]
} }
t.Log("\t", m); t.Log("\t", m)
} }
} }
func equal(m1, m2 []int) bool { func equal(m1, m2 []int) bool {
l := len(m1); l := len(m1)
if l != len(m2) { if l != len(m2) {
return false return false
} }
@ -129,11 +129,11 @@ func equal(m1, m2 []int) bool {
return false return false
} }
} }
return true; return true
} }
func equalStrings(m1, m2 []string) bool { func equalStrings(m1, m2 []string) bool {
l := len(m1); l := len(m1)
if l != len(m2) { if l != len(m2) {
return false return false
} }
@ -142,28 +142,28 @@ func equalStrings(m1, m2 []string) bool {
return false return false
} }
} }
return true; return true
} }
func executeTest(t *testing.T, expr string, str string, match []int) { func executeTest(t *testing.T, expr string, str string, match []int) {
re := compileTest(t, expr, nil); re := compileTest(t, expr, nil)
if re == nil { if re == nil {
return return
} }
m := re.ExecuteString(str); m := re.ExecuteString(str)
if !equal(m, match) { if !equal(m, match) {
t.Errorf("ExecuteString failure on %#q matching %q:", expr, str); t.Errorf("ExecuteString failure on %#q matching %q:", expr, str)
printVec(t, m); printVec(t, m)
t.Log("should be:"); t.Log("should be:")
printVec(t, match); printVec(t, match)
} }
// now try bytes // now try bytes
m = re.Execute(strings.Bytes(str)); m = re.Execute(strings.Bytes(str))
if !equal(m, match) { if !equal(m, match) {
t.Errorf("Execute failure on %#q matching %q:", expr, str); t.Errorf("Execute failure on %#q matching %q:", expr, str)
printVec(t, m); printVec(t, m)
t.Log("should be:"); t.Log("should be:")
printVec(t, match); printVec(t, match)
} }
} }
@ -181,22 +181,22 @@ func TestBadCompile(t *testing.T) {
func TestExecute(t *testing.T) { func TestExecute(t *testing.T) {
for i := 0; i < len(matches); i++ { for i := 0; i < len(matches); i++ {
test := &matches[i]; test := &matches[i]
executeTest(t, test.re, test.text, test.match); executeTest(t, test.re, test.text, test.match)
} }
} }
func matchTest(t *testing.T, expr string, str string, match []int) { func matchTest(t *testing.T, expr string, str string, match []int) {
re := compileTest(t, expr, nil); re := compileTest(t, expr, nil)
if re == nil { if re == nil {
return return
} }
m := re.MatchString(str); m := re.MatchString(str)
if m != (len(match) > 0) { if m != (len(match) > 0) {
t.Errorf("MatchString failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0) t.Errorf("MatchString failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0)
} }
// now try bytes // now try bytes
m = re.Match(strings.Bytes(str)); m = re.Match(strings.Bytes(str))
if m != (len(match) > 0) { if m != (len(match) > 0) {
t.Errorf("Match failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0) t.Errorf("Match failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0)
} }
@ -204,20 +204,20 @@ func matchTest(t *testing.T, expr string, str string, match []int) {
func TestMatch(t *testing.T) { func TestMatch(t *testing.T) {
for i := 0; i < len(matches); i++ { for i := 0; i < len(matches); i++ {
test := &matches[i]; test := &matches[i]
matchTest(t, test.re, test.text, test.match); matchTest(t, test.re, test.text, test.match)
} }
} }
func TestMatchStrings(t *testing.T) { func TestMatchStrings(t *testing.T) {
for i := 0; i < len(matches); i++ { for i := 0; i < len(matches); i++ {
test := &matches[i]; test := &matches[i]
matchTest(t, test.re, test.text, test.match); matchTest(t, test.re, test.text, test.match)
} }
} }
func matchFunctionTest(t *testing.T, expr string, str string, match []int) { func matchFunctionTest(t *testing.T, expr string, str string, match []int) {
m, err := MatchString(expr, str); m, err := MatchString(expr, str)
if err == nil { if err == nil {
return return
} }
@ -228,13 +228,13 @@ func matchFunctionTest(t *testing.T, expr string, str string, match []int) {
func TestMatchFunction(t *testing.T) { func TestMatchFunction(t *testing.T) {
for i := 0; i < len(matches); i++ { for i := 0; i < len(matches); i++ {
test := &matches[i]; test := &matches[i]
matchFunctionTest(t, test.re, test.text, test.match); matchFunctionTest(t, test.re, test.text, test.match)
} }
} }
type ReplaceTest struct { type ReplaceTest struct {
pattern, replacement, input, output string; pattern, replacement, input, output string
} }
var replaceTests = []ReplaceTest{ var replaceTests = []ReplaceTest{
@ -301,18 +301,18 @@ var replaceTests = []ReplaceTest{
func TestReplaceAll(t *testing.T) { func TestReplaceAll(t *testing.T) {
for _, tc := range replaceTests { for _, tc := range replaceTests {
re, err := Compile(tc.pattern); re, err := Compile(tc.pattern)
if err != nil { if err != nil {
t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err); t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
continue; continue
} }
actual := re.ReplaceAllString(tc.input, tc.replacement); actual := re.ReplaceAllString(tc.input, tc.replacement)
if actual != tc.output { if actual != tc.output {
t.Errorf("%q.Replace(%q,%q) = %q; want %q", t.Errorf("%q.Replace(%q,%q) = %q; want %q",
tc.pattern, tc.input, tc.replacement, actual, tc.output) tc.pattern, tc.input, tc.replacement, actual, tc.output)
} }
// now try bytes // now try bytes
actual = string(re.ReplaceAll(strings.Bytes(tc.input), strings.Bytes(tc.replacement))); actual = string(re.ReplaceAll(strings.Bytes(tc.input), strings.Bytes(tc.replacement)))
if actual != tc.output { if actual != tc.output {
t.Errorf("%q.Replace(%q,%q) = %q; want %q", t.Errorf("%q.Replace(%q,%q) = %q; want %q",
tc.pattern, tc.input, tc.replacement, actual, tc.output) tc.pattern, tc.input, tc.replacement, actual, tc.output)
@ -321,7 +321,7 @@ func TestReplaceAll(t *testing.T) {
} }
type QuoteMetaTest struct { type QuoteMetaTest struct {
pattern, output string; pattern, output string
} }
var quoteMetaTests = []QuoteMetaTest{ var quoteMetaTests = []QuoteMetaTest{
@ -333,25 +333,25 @@ var quoteMetaTests = []QuoteMetaTest{
func TestQuoteMeta(t *testing.T) { func TestQuoteMeta(t *testing.T) {
for _, tc := range quoteMetaTests { for _, tc := range quoteMetaTests {
// Verify that QuoteMeta returns the expected string. // Verify that QuoteMeta returns the expected string.
quoted := QuoteMeta(tc.pattern); quoted := QuoteMeta(tc.pattern)
if quoted != tc.output { if quoted != tc.output {
t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`", t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
tc.pattern, quoted, tc.output); tc.pattern, quoted, tc.output)
continue; continue
} }
// Verify that the quoted string is in fact treated as expected // Verify that the quoted string is in fact treated as expected
// by Compile -- i.e. that it matches the original, unquoted string. // by Compile -- i.e. that it matches the original, unquoted string.
if tc.pattern != "" { if tc.pattern != "" {
re, err := Compile(quoted); re, err := Compile(quoted)
if err != nil { if err != nil {
t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err); t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
continue; continue
} }
src := "abc" + tc.pattern + "def"; src := "abc" + tc.pattern + "def"
repl := "xyz"; repl := "xyz"
replaced := re.ReplaceAllString(src, repl); replaced := re.ReplaceAllString(src, repl)
expected := "abcxyzdef"; expected := "abcxyzdef"
if replaced != expected { if replaced != expected {
t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`", t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
tc.pattern, src, repl, replaced, expected) tc.pattern, src, repl, replaced, expected)
@ -361,11 +361,11 @@ func TestQuoteMeta(t *testing.T) {
} }
type matchCase struct { type matchCase struct {
matchfunc string; matchfunc string
input string; input string
n int; n int
regexp string; regexp string
expected []string; expected []string
} }
var matchCases = []matchCase{ var matchCases = []matchCase{
@ -392,90 +392,90 @@ func printStringSlice(t *testing.T, s []string) {
} }
func TestAllMatches(t *testing.T) { func TestAllMatches(t *testing.T) {
ch := make(chan matchCase); ch := make(chan matchCase)
go func() { go func() {
for _, c := range matchCases { for _, c := range matchCases {
ch <- c; ch <- c
stringCase := matchCase{ stringCase := matchCase{
"string" + c.matchfunc, "string" + c.matchfunc,
c.input, c.input,
c.n, c.n,
c.regexp, c.regexp,
c.expected, c.expected,
}; }
ch <- stringCase; ch <- stringCase
} }
close(ch); close(ch)
}(); }()
for c := range ch { for c := range ch {
var result []string; var result []string
re, _ := Compile(c.regexp); re, _ := Compile(c.regexp)
switch c.matchfunc { switch c.matchfunc {
case "matchit": case "matchit":
result = make([]string, len(c.input)+1); result = make([]string, len(c.input)+1)
i := 0; i := 0
b := strings.Bytes(c.input); b := strings.Bytes(c.input)
for match := range re.AllMatchesIter(b, c.n) { for match := range re.AllMatchesIter(b, c.n) {
result[i] = string(match); result[i] = string(match)
i++; i++
} }
result = result[0:i]; result = result[0:i]
case "stringmatchit": case "stringmatchit":
result = make([]string, len(c.input)+1); result = make([]string, len(c.input)+1)
i := 0; i := 0
for match := range re.AllMatchesStringIter(c.input, c.n) { for match := range re.AllMatchesStringIter(c.input, c.n) {
result[i] = match; result[i] = match
i++; i++
} }
result = result[0:i]; result = result[0:i]
case "match": case "match":
result = make([]string, len(c.input)+1); result = make([]string, len(c.input)+1)
b := strings.Bytes(c.input); b := strings.Bytes(c.input)
i := 0; i := 0
for _, match := range re.AllMatches(b, c.n) { for _, match := range re.AllMatches(b, c.n) {
result[i] = string(match); result[i] = string(match)
i++; i++
} }
result = result[0:i]; result = result[0:i]
case "stringmatch": case "stringmatch":
result = re.AllMatchesString(c.input, c.n) result = re.AllMatchesString(c.input, c.n)
} }
if !equalStrings(result, c.expected) { if !equalStrings(result, c.expected) {
t.Errorf("testing '%s'.%s('%s', %d), expected: ", t.Errorf("testing '%s'.%s('%s', %d), expected: ",
c.regexp, c.matchfunc, c.input, c.n); c.regexp, c.matchfunc, c.input, c.n)
printStringSlice(t, c.expected); printStringSlice(t, c.expected)
t.Log("got: "); t.Log("got: ")
printStringSlice(t, result); printStringSlice(t, result)
t.Log("\n"); t.Log("\n")
} }
} }
} }
func BenchmarkLiteral(b *testing.B) { func BenchmarkLiteral(b *testing.B) {
x := strings.Repeat("x", 50); x := strings.Repeat("x", 50)
b.StopTimer(); b.StopTimer()
re, _ := Compile(x); re, _ := Compile(x)
b.StartTimer(); b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if !re.MatchString(x) { if !re.MatchString(x) {
println("no match!"); println("no match!")
break; break
} }
} }
} }
func BenchmarkNotLiteral(b *testing.B) { func BenchmarkNotLiteral(b *testing.B) {
x := strings.Repeat("x", 49); x := strings.Repeat("x", 49)
b.StopTimer(); b.StopTimer()
re, _ := Compile("^" + x); re, _ := Compile("^" + x)
b.StartTimer(); b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if !re.MatchString(x) { if !re.MatchString(x) {
println("no match!"); println("no match!")
break; break
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -5,84 +5,84 @@
package rpc package rpc
import ( import (
"bufio"; "bufio"
"gob"; "gob"
"http"; "http"
"io"; "io"
"log"; "log"
"net"; "net"
"os"; "os"
"sync"; "sync"
) )
// Call represents an active RPC. // Call represents an active RPC.
type Call struct { type Call struct {
ServiceMethod string; // The name of the service and method to call. ServiceMethod string // The name of the service and method to call.
Args interface{}; // The argument to the function (*struct). Args interface{} // The argument to the function (*struct).
Reply interface{}; // The reply from the function (*struct). Reply interface{} // The reply from the function (*struct).
Error os.Error; // After completion, the error status. Error os.Error // After completion, the error status.
Done chan *Call; // Strobes when call is complete; value is the error status. Done chan *Call // Strobes when call is complete; value is the error status.
seq uint64; seq uint64
} }
// Client represents an RPC Client. // Client represents an RPC Client.
// There may be multiple outstanding Calls associated // There may be multiple outstanding Calls associated
// with a single Client. // with a single Client.
type Client struct { type Client struct {
mutex sync.Mutex; // protects pending, seq mutex sync.Mutex // protects pending, seq
shutdown os.Error; // non-nil if the client is shut down shutdown os.Error // non-nil if the client is shut down
sending sync.Mutex; sending sync.Mutex
seq uint64; seq uint64
conn io.ReadWriteCloser; conn io.ReadWriteCloser
enc *gob.Encoder; enc *gob.Encoder
dec *gob.Decoder; dec *gob.Decoder
pending map[uint64]*Call; pending map[uint64]*Call
} }
func (client *Client) send(c *Call) { func (client *Client) send(c *Call) {
// Register this call. // Register this call.
client.mutex.Lock(); client.mutex.Lock()
if client.shutdown != nil { if client.shutdown != nil {
c.Error = client.shutdown; c.Error = client.shutdown
client.mutex.Unlock(); client.mutex.Unlock()
_ = c.Done <- c; // do not block _ = c.Done <- c // do not block
return; return
} }
c.seq = client.seq; c.seq = client.seq
client.seq++; client.seq++
client.pending[c.seq] = c; client.pending[c.seq] = c
client.mutex.Unlock(); client.mutex.Unlock()
// Encode and send the request. // Encode and send the request.
request := new(Request); request := new(Request)
client.sending.Lock(); client.sending.Lock()
request.Seq = c.seq; request.Seq = c.seq
request.ServiceMethod = c.ServiceMethod; request.ServiceMethod = c.ServiceMethod
client.enc.Encode(request); client.enc.Encode(request)
err := client.enc.Encode(c.Args); err := client.enc.Encode(c.Args)
if err != nil { if err != nil {
panicln("rpc: client encode error:", err.String()) panicln("rpc: client encode error:", err.String())
} }
client.sending.Unlock(); client.sending.Unlock()
} }
func (client *Client) input() { func (client *Client) input() {
var err os.Error; var err os.Error
for err == nil { for err == nil {
response := new(Response); response := new(Response)
err = client.dec.Decode(response); err = client.dec.Decode(response)
if err != nil { if err != nil {
if err == os.EOF { if err == os.EOF {
err = io.ErrUnexpectedEOF err = io.ErrUnexpectedEOF
} }
break; break
} }
seq := response.Seq; seq := response.Seq
client.mutex.Lock(); client.mutex.Lock()
c := client.pending[seq]; c := client.pending[seq]
client.pending[seq] = c, false; client.pending[seq] = c, false
client.mutex.Unlock(); client.mutex.Unlock()
err = client.dec.Decode(c.Reply); err = client.dec.Decode(c.Reply)
// Empty strings should turn into nil os.Errors // Empty strings should turn into nil os.Errors
if response.Error != "" { if response.Error != "" {
c.Error = os.ErrorString(response.Error) c.Error = os.ErrorString(response.Error)
@ -91,59 +91,59 @@ func (client *Client) input() {
} }
// We don't want to block here. It is the caller's responsibility to make // We don't want to block here. It is the caller's responsibility to make
// sure the channel has enough buffer space. See comment in Go(). // sure the channel has enough buffer space. See comment in Go().
_ = c.Done <- c; // do not block _ = c.Done <- c // do not block
} }
// Terminate pending calls. // Terminate pending calls.
client.mutex.Lock(); client.mutex.Lock()
client.shutdown = err; client.shutdown = err
for _, call := range client.pending { for _, call := range client.pending {
call.Error = err; call.Error = err
_ = call.Done <- call; // do not block _ = call.Done <- call // do not block
} }
client.mutex.Unlock(); client.mutex.Unlock()
log.Stderr("rpc: client protocol error:", err); log.Stderr("rpc: client protocol error:", err)
} }
// NewClient returns a new Client to handle requests to the // NewClient returns a new Client to handle requests to the
// set of services at the other end of the connection. // set of services at the other end of the connection.
func NewClient(conn io.ReadWriteCloser) *Client { func NewClient(conn io.ReadWriteCloser) *Client {
client := new(Client); client := new(Client)
client.conn = conn; client.conn = conn
client.enc = gob.NewEncoder(conn); client.enc = gob.NewEncoder(conn)
client.dec = gob.NewDecoder(conn); client.dec = gob.NewDecoder(conn)
client.pending = make(map[uint64]*Call); client.pending = make(map[uint64]*Call)
go client.input(); go client.input()
return client; return client
} }
// DialHTTP connects to an HTTP RPC server at the specified network address. // DialHTTP connects to an HTTP RPC server at the specified network address.
func DialHTTP(network, address string) (*Client, os.Error) { func DialHTTP(network, address string) (*Client, os.Error) {
conn, err := net.Dial(network, "", address); conn, err := net.Dial(network, "", address)
if err != nil { if err != nil {
return nil, err return nil, err
} }
io.WriteString(conn, "CONNECT "+rpcPath+" HTTP/1.0\n\n"); io.WriteString(conn, "CONNECT "+rpcPath+" HTTP/1.0\n\n")
// Require successful HTTP response // Require successful HTTP response
// before switching to RPC protocol. // before switching to RPC protocol.
resp, err := http.ReadResponse(bufio.NewReader(conn)); resp, err := http.ReadResponse(bufio.NewReader(conn))
if err == nil && resp.Status == connected { if err == nil && resp.Status == connected {
return NewClient(conn), nil return NewClient(conn), nil
} }
if err == nil { if err == nil {
err = os.ErrorString("unexpected HTTP response: " + resp.Status) err = os.ErrorString("unexpected HTTP response: " + resp.Status)
} }
conn.Close(); conn.Close()
return nil, &net.OpError{"dial-http", network + " " + address, nil, err}; return nil, &net.OpError{"dial-http", network + " " + address, nil, err}
} }
// Dial connects to an RPC server at the specified network address. // Dial connects to an RPC server at the specified network address.
func Dial(network, address string) (*Client, os.Error) { func Dial(network, address string) (*Client, os.Error) {
conn, err := net.Dial(network, "", address); conn, err := net.Dial(network, "", address)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewClient(conn), nil; return NewClient(conn), nil
} }
// Go invokes the function asynchronously. It returns the Call structure representing // Go invokes the function asynchronously. It returns the Call structure representing
@ -151,12 +151,12 @@ func Dial(network, address string) (*Client, os.Error) {
// the same Call object. If done is nil, Go will allocate a new channel. // the same Call object. If done is nil, Go will allocate a new channel.
// If non-nil, done must be buffered or Go will deliberately crash. // If non-nil, done must be buffered or Go will deliberately crash.
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call { func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
c := new(Call); c := new(Call)
c.ServiceMethod = serviceMethod; c.ServiceMethod = serviceMethod
c.Args = args; c.Args = args
c.Reply = reply; c.Reply = reply
if done == nil { if done == nil {
done = make(chan *Call, 10) // buffered. done = make(chan *Call, 10) // buffered.
} else { } else {
// If caller passes done != nil, it must arrange that // If caller passes done != nil, it must arrange that
// done has enough buffer for the number of simultaneous // done has enough buffer for the number of simultaneous
@ -166,14 +166,14 @@ func (client *Client) Go(serviceMethod string, args interface{}, reply interface
log.Crash("rpc: done channel is unbuffered") log.Crash("rpc: done channel is unbuffered")
} }
} }
c.Done = done; c.Done = done
if client.shutdown != nil { if client.shutdown != nil {
c.Error = client.shutdown; c.Error = client.shutdown
_ = c.Done <- c; // do not block _ = c.Done <- c // do not block
return c; return c
} }
client.send(c); client.send(c)
return c; return c
} }
// Call invokes the named function, waits for it to complete, and returns its error status. // Call invokes the named function, waits for it to complete, and returns its error status.
@ -181,6 +181,6 @@ func (client *Client) Call(serviceMethod string, args interface{}, reply interfa
if client.shutdown != nil { if client.shutdown != nil {
return client.shutdown return client.shutdown
} }
call := <-client.Go(serviceMethod, args, reply, nil).Done; call := <-client.Go(serviceMethod, args, reply, nil).Done
return call.Error; return call.Error
} }

View File

@ -10,10 +10,10 @@ package rpc
*/ */
import ( import (
"fmt"; "fmt"
"http"; "http"
"sort"; "sort"
"template"; "template"
) )
const debugText = `<html> const debugText = `<html>
@ -39,47 +39,47 @@ const debugText = `<html>
var debug = template.MustParse(debugText, nil) var debug = template.MustParse(debugText, nil)
type debugMethod struct { type debugMethod struct {
m *methodType; m *methodType
name string; name string
} }
type methodArray []debugMethod type methodArray []debugMethod
type debugService struct { type debugService struct {
s *service; s *service
name string; name string
meth methodArray; meth methodArray
} }
type serviceArray []debugService type serviceArray []debugService
func (s serviceArray) Len() int { return len(s) } func (s serviceArray) Len() int { return len(s) }
func (s serviceArray) Less(i, j int) bool { return s[i].name < s[j].name } func (s serviceArray) Less(i, j int) bool { return s[i].name < s[j].name }
func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (m methodArray) Len() int { return len(m) } func (m methodArray) Len() int { return len(m) }
func (m methodArray) Less(i, j int) bool { return m[i].name < m[j].name } func (m methodArray) Less(i, j int) bool { return m[i].name < m[j].name }
func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] } func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
// Runs at /debug/rpc // Runs at /debug/rpc
func debugHTTP(c *http.Conn, req *http.Request) { func debugHTTP(c *http.Conn, req *http.Request) {
// Build a sorted version of the data. // Build a sorted version of the data.
var services = make(serviceArray, len(server.serviceMap)); var services = make(serviceArray, len(server.serviceMap))
i := 0; i := 0
server.Lock(); server.Lock()
for sname, service := range server.serviceMap { for sname, service := range server.serviceMap {
services[i] = debugService{service, sname, make(methodArray, len(service.method))}; services[i] = debugService{service, sname, make(methodArray, len(service.method))}
j := 0; j := 0
for mname, method := range service.method { for mname, method := range service.method {
services[i].meth[j] = debugMethod{method, mname}; services[i].meth[j] = debugMethod{method, mname}
j++; j++
} }
sort.Sort(services[i].meth); sort.Sort(services[i].meth)
i++; i++
} }
server.Unlock(); server.Unlock()
sort.Sort(services); sort.Sort(services)
err := debug.Execute(services, c); err := debug.Execute(services, c)
if err != nil { if err != nil {
fmt.Fprintln(c, "rpc: error executing template:", err.String()) fmt.Fprintln(c, "rpc: error executing template:", err.String())
} }

View File

@ -108,17 +108,17 @@
package rpc package rpc
import ( import (
"gob"; "gob"
"http"; "http"
"log"; "log"
"io"; "io"
"net"; "net"
"os"; "os"
"reflect"; "reflect"
"strings"; "strings"
"sync"; "sync"
"unicode"; "unicode"
"utf8"; "utf8"
) )
// Precompute the reflect type for os.Error. Can't use os.Error directly // Precompute the reflect type for os.Error. Can't use os.Error directly
@ -127,40 +127,40 @@ var unusedError *os.Error
var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem() var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem()
type methodType struct { type methodType struct {
sync.Mutex; // protects counters sync.Mutex // protects counters
method reflect.Method; method reflect.Method
argType *reflect.PtrType; argType *reflect.PtrType
replyType *reflect.PtrType; replyType *reflect.PtrType
numCalls uint; numCalls uint
} }
type service struct { type service struct {
name string; // name of service name string // name of service
rcvr reflect.Value; // receiver of methods for the service rcvr reflect.Value // receiver of methods for the service
typ reflect.Type; // type of the receiver typ reflect.Type // type of the receiver
method map[string]*methodType; // registered methods method map[string]*methodType // registered methods
} }
// Request is a header written before every RPC call. It is used internally // Request is a header written before every RPC call. It is used internally
// but documented here as an aid to debugging, such as when analyzing // but documented here as an aid to debugging, such as when analyzing
// network traffic. // network traffic.
type Request struct { type Request struct {
ServiceMethod string; // format: "Service.Method" ServiceMethod string // format: "Service.Method"
Seq uint64; // sequence number chosen by client Seq uint64 // sequence number chosen by client
} }
// Response is a header written before every RPC return. It is used internally // Response is a header written before every RPC return. It is used internally
// but documented here as an aid to debugging, such as when analyzing // but documented here as an aid to debugging, such as when analyzing
// network traffic. // network traffic.
type Response struct { type Response struct {
ServiceMethod string; // echoes that of the Request ServiceMethod string // echoes that of the Request
Seq uint64; // echoes that of the request Seq uint64 // echoes that of the request
Error string; // error, if any. Error string // error, if any.
} }
type serverType struct { type serverType struct {
sync.Mutex; // protects the serviceMap sync.Mutex // protects the serviceMap
serviceMap map[string]*service; serviceMap map[string]*service
} }
// This variable is a global whose "public" methods are really private methods // This variable is a global whose "public" methods are really private methods
@ -170,198 +170,198 @@ var server = &serverType{serviceMap: make(map[string]*service)}
// Is this a publicly visible - upper case - name? // Is this a publicly visible - upper case - name?
func isPublic(name string) bool { func isPublic(name string) bool {
rune, _ := utf8.DecodeRuneInString(name); rune, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(rune); return unicode.IsUpper(rune)
} }
func (server *serverType) register(rcvr interface{}) os.Error { func (server *serverType) register(rcvr interface{}) os.Error {
server.Lock(); server.Lock()
defer server.Unlock(); defer server.Unlock()
if server.serviceMap == nil { if server.serviceMap == nil {
server.serviceMap = make(map[string]*service) server.serviceMap = make(map[string]*service)
} }
s := new(service); s := new(service)
s.typ = reflect.Typeof(rcvr); s.typ = reflect.Typeof(rcvr)
s.rcvr = reflect.NewValue(rcvr); s.rcvr = reflect.NewValue(rcvr)
sname := reflect.Indirect(s.rcvr).Type().Name(); sname := reflect.Indirect(s.rcvr).Type().Name()
if sname == "" { if sname == "" {
log.Exit("rpc: no service name for type", s.typ.String()) log.Exit("rpc: no service name for type", s.typ.String())
} }
if !isPublic(sname) { if !isPublic(sname) {
s := "rpc Register: type " + sname + " is not public"; s := "rpc Register: type " + sname + " is not public"
log.Stderr(s); log.Stderr(s)
return os.ErrorString(s); return os.ErrorString(s)
} }
if _, present := server.serviceMap[sname]; present { if _, present := server.serviceMap[sname]; present {
return os.ErrorString("rpc: service already defined: " + sname) return os.ErrorString("rpc: service already defined: " + sname)
} }
s.name = sname; s.name = sname
s.method = make(map[string]*methodType); s.method = make(map[string]*methodType)
// Install the methods // Install the methods
for m := 0; m < s.typ.NumMethod(); m++ { for m := 0; m < s.typ.NumMethod(); m++ {
method := s.typ.Method(m); method := s.typ.Method(m)
mtype := method.Type; mtype := method.Type
mname := method.Name; mname := method.Name
if !isPublic(mname) { if !isPublic(mname) {
continue continue
} }
// Method needs three ins: receiver, *args, *reply. // Method needs three ins: receiver, *args, *reply.
// The args and reply must be structs until gobs are more general. // The args and reply must be structs until gobs are more general.
if mtype.NumIn() != 3 { if mtype.NumIn() != 3 {
log.Stderr("method", mname, "has wrong number of ins:", mtype.NumIn()); log.Stderr("method", mname, "has wrong number of ins:", mtype.NumIn())
continue; continue
} }
argType, ok := mtype.In(1).(*reflect.PtrType); argType, ok := mtype.In(1).(*reflect.PtrType)
if !ok { if !ok {
log.Stderr(mname, "arg type not a pointer:", mtype.In(1)); log.Stderr(mname, "arg type not a pointer:", mtype.In(1))
continue; continue
} }
if _, ok := argType.Elem().(*reflect.StructType); !ok { if _, ok := argType.Elem().(*reflect.StructType); !ok {
log.Stderr(mname, "arg type not a pointer to a struct:", argType); log.Stderr(mname, "arg type not a pointer to a struct:", argType)
continue; continue
} }
replyType, ok := mtype.In(2).(*reflect.PtrType); replyType, ok := mtype.In(2).(*reflect.PtrType)
if !ok { if !ok {
log.Stderr(mname, "reply type not a pointer:", mtype.In(2)); log.Stderr(mname, "reply type not a pointer:", mtype.In(2))
continue; continue
} }
if _, ok := replyType.Elem().(*reflect.StructType); !ok { if _, ok := replyType.Elem().(*reflect.StructType); !ok {
log.Stderr(mname, "reply type not a pointer to a struct:", replyType); log.Stderr(mname, "reply type not a pointer to a struct:", replyType)
continue; continue
} }
if !isPublic(argType.Elem().Name()) { if !isPublic(argType.Elem().Name()) {
log.Stderr(mname, "argument type not public:", argType); log.Stderr(mname, "argument type not public:", argType)
continue; continue
} }
if !isPublic(replyType.Elem().Name()) { if !isPublic(replyType.Elem().Name()) {
log.Stderr(mname, "reply type not public:", replyType); log.Stderr(mname, "reply type not public:", replyType)
continue; continue
} }
// Method needs one out: os.Error. // Method needs one out: os.Error.
if mtype.NumOut() != 1 { if mtype.NumOut() != 1 {
log.Stderr("method", mname, "has wrong number of outs:", mtype.NumOut()); log.Stderr("method", mname, "has wrong number of outs:", mtype.NumOut())
continue; continue
} }
if returnType := mtype.Out(0); returnType != typeOfOsError { if returnType := mtype.Out(0); returnType != typeOfOsError {
log.Stderr("method", mname, "returns", returnType.String(), "not os.Error"); log.Stderr("method", mname, "returns", returnType.String(), "not os.Error")
continue; continue
} }
s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType}; s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType}
} }
if len(s.method) == 0 { if len(s.method) == 0 {
s := "rpc Register: type " + sname + " has no public methods of suitable type"; s := "rpc Register: type " + sname + " has no public methods of suitable type"
log.Stderr(s); log.Stderr(s)
return os.ErrorString(s); return os.ErrorString(s)
} }
server.serviceMap[s.name] = s; server.serviceMap[s.name] = s
return nil; return nil
} }
// A value sent as a placeholder for the response when the server receives an invalid request. // A value sent as a placeholder for the response when the server receives an invalid request.
type InvalidRequest struct { type InvalidRequest struct {
marker int; marker int
} }
var invalidRequest = InvalidRequest{1} var invalidRequest = InvalidRequest{1}
func _new(t *reflect.PtrType) *reflect.PtrValue { func _new(t *reflect.PtrType) *reflect.PtrValue {
v := reflect.MakeZero(t).(*reflect.PtrValue); v := reflect.MakeZero(t).(*reflect.PtrValue)
v.PointTo(reflect.MakeZero(t.Elem())); v.PointTo(reflect.MakeZero(t.Elem()))
return v; return v
} }
func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, enc *gob.Encoder, errmsg string) { func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, enc *gob.Encoder, errmsg string) {
resp := new(Response); resp := new(Response)
// Encode the response header // Encode the response header
resp.ServiceMethod = req.ServiceMethod; resp.ServiceMethod = req.ServiceMethod
if errmsg != "" { if errmsg != "" {
resp.Error = errmsg resp.Error = errmsg
} }
resp.Seq = req.Seq; resp.Seq = req.Seq
sending.Lock(); sending.Lock()
enc.Encode(resp); enc.Encode(resp)
// Encode the reply value. // Encode the reply value.
enc.Encode(reply); enc.Encode(reply)
sending.Unlock(); sending.Unlock()
} }
func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, enc *gob.Encoder) { func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, enc *gob.Encoder) {
mtype.Lock(); mtype.Lock()
mtype.numCalls++; mtype.numCalls++
mtype.Unlock(); mtype.Unlock()
function := mtype.method.Func; function := mtype.method.Func
// Invoke the method, providing a new value for the reply. // Invoke the method, providing a new value for the reply.
returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv}); returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
// The return value for the method is an os.Error. // The return value for the method is an os.Error.
errInter := returnValues[0].Interface(); errInter := returnValues[0].Interface()
errmsg := ""; errmsg := ""
if errInter != nil { if errInter != nil {
errmsg = errInter.(os.Error).String() errmsg = errInter.(os.Error).String()
} }
sendResponse(sending, req, replyv.Interface(), enc, errmsg); sendResponse(sending, req, replyv.Interface(), enc, errmsg)
} }
func (server *serverType) input(conn io.ReadWriteCloser) { func (server *serverType) input(conn io.ReadWriteCloser) {
dec := gob.NewDecoder(conn); dec := gob.NewDecoder(conn)
enc := gob.NewEncoder(conn); enc := gob.NewEncoder(conn)
sending := new(sync.Mutex); sending := new(sync.Mutex)
for { for {
// Grab the request header. // Grab the request header.
req := new(Request); req := new(Request)
err := dec.Decode(req); err := dec.Decode(req)
if err != nil { if err != nil {
if err == os.EOF || err == io.ErrUnexpectedEOF { if err == os.EOF || err == io.ErrUnexpectedEOF {
log.Stderr("rpc: ", err); log.Stderr("rpc: ", err)
break; break
} }
s := "rpc: server cannot decode request: " + err.String(); s := "rpc: server cannot decode request: " + err.String()
sendResponse(sending, req, invalidRequest, enc, s); sendResponse(sending, req, invalidRequest, enc, s)
continue; continue
} }
serviceMethod := strings.Split(req.ServiceMethod, ".", 0); serviceMethod := strings.Split(req.ServiceMethod, ".", 0)
if len(serviceMethod) != 2 { if len(serviceMethod) != 2 {
s := "rpc: service/method request ill:formed: " + req.ServiceMethod; s := "rpc: service/method request ill:formed: " + req.ServiceMethod
sendResponse(sending, req, invalidRequest, enc, s); sendResponse(sending, req, invalidRequest, enc, s)
continue; continue
} }
// Look up the request. // Look up the request.
server.Lock(); server.Lock()
service, ok := server.serviceMap[serviceMethod[0]]; service, ok := server.serviceMap[serviceMethod[0]]
server.Unlock(); server.Unlock()
if !ok { if !ok {
s := "rpc: can't find service " + req.ServiceMethod; s := "rpc: can't find service " + req.ServiceMethod
sendResponse(sending, req, invalidRequest, enc, s); sendResponse(sending, req, invalidRequest, enc, s)
continue; continue
} }
mtype, ok := service.method[serviceMethod[1]]; mtype, ok := service.method[serviceMethod[1]]
if !ok { if !ok {
s := "rpc: can't find method " + req.ServiceMethod; s := "rpc: can't find method " + req.ServiceMethod
sendResponse(sending, req, invalidRequest, enc, s); sendResponse(sending, req, invalidRequest, enc, s)
continue; continue
} }
// Decode the argument value. // Decode the argument value.
argv := _new(mtype.argType); argv := _new(mtype.argType)
replyv := _new(mtype.replyType); replyv := _new(mtype.replyType)
err = dec.Decode(argv.Interface()); err = dec.Decode(argv.Interface())
if err != nil { if err != nil {
log.Stderr("rpc: tearing down", serviceMethod[0], "connection:", err); log.Stderr("rpc: tearing down", serviceMethod[0], "connection:", err)
sendResponse(sending, req, replyv.Interface(), enc, err.String()); sendResponse(sending, req, replyv.Interface(), enc, err.String())
continue; continue
} }
go service.call(sending, mtype, req, argv, replyv, enc); go service.call(sending, mtype, req, argv, replyv, enc)
} }
conn.Close(); conn.Close()
} }
func (server *serverType) accept(lis net.Listener) { func (server *serverType) accept(lis net.Listener) {
for { for {
conn, err := lis.Accept(); conn, err := lis.Accept()
if err != nil { if err != nil {
log.Exit("rpc.Serve: accept:", err.String()) // TODO(r): exit? log.Exit("rpc.Serve: accept:", err.String()) // TODO(r): exit?
} }
go server.input(conn); go server.input(conn)
} }
} }
@ -372,17 +372,17 @@ func (server *serverType) accept(lis net.Listener) {
// - one return value of type os.Error // - one return value of type os.Error
// It returns an error if the receiver is not public or has no // It returns an error if the receiver is not public or has no
// suitable methods. // suitable methods.
func Register(rcvr interface{}) os.Error { return server.register(rcvr) } func Register(rcvr interface{}) os.Error { return server.register(rcvr) }
// ServeConn runs the server on a single connection. When the connection // ServeConn runs the server on a single connection. When the connection
// completes, service terminates. ServeConn blocks; the caller typically // completes, service terminates. ServeConn blocks; the caller typically
// invokes it in a go statement. // invokes it in a go statement.
func ServeConn(conn io.ReadWriteCloser) { go server.input(conn) } func ServeConn(conn io.ReadWriteCloser) { go server.input(conn) }
// Accept accepts connections on the listener and serves requests // Accept accepts connections on the listener and serves requests
// for each incoming connection. Accept blocks; the caller typically // for each incoming connection. Accept blocks; the caller typically
// invokes it in a go statement. // invokes it in a go statement.
func Accept(lis net.Listener) { server.accept(lis) } func Accept(lis net.Listener) { server.accept(lis) }
// Can connect to RPC service using HTTP CONNECT to rpcPath. // Can connect to RPC service using HTTP CONNECT to rpcPath.
var rpcPath string = "/_goRPC_" var rpcPath string = "/_goRPC_"
@ -391,23 +391,23 @@ var connected = "200 Connected to Go RPC"
func serveHTTP(c *http.Conn, req *http.Request) { func serveHTTP(c *http.Conn, req *http.Request) {
if req.Method != "CONNECT" { if req.Method != "CONNECT" {
c.SetHeader("Content-Type", "text/plain; charset=utf-8"); c.SetHeader("Content-Type", "text/plain; charset=utf-8")
c.WriteHeader(http.StatusMethodNotAllowed); c.WriteHeader(http.StatusMethodNotAllowed)
io.WriteString(c, "405 must CONNECT to "+rpcPath+"\n"); io.WriteString(c, "405 must CONNECT to "+rpcPath+"\n")
return; return
} }
conn, _, err := c.Hijack(); conn, _, err := c.Hijack()
if err != nil { if err != nil {
log.Stderr("rpc hijacking ", c.RemoteAddr, ": ", err.String()); log.Stderr("rpc hijacking ", c.RemoteAddr, ": ", err.String())
return; return
} }
io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n"); io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
server.input(conn); server.input(conn)
} }
// HandleHTTP registers an HTTP handler for RPC messages. // HandleHTTP registers an HTTP handler for RPC messages.
// It is still necessary to invoke http.Serve(), typically in a go statement. // It is still necessary to invoke http.Serve(), typically in a go statement.
func HandleHTTP() { func HandleHTTP() {
http.Handle(rpcPath, http.HandlerFunc(serveHTTP)); http.Handle(rpcPath, http.HandlerFunc(serveHTTP))
http.Handle(debugPath, http.HandlerFunc(debugHTTP)); http.Handle(debugPath, http.HandlerFunc(debugHTTP))
} }

View File

@ -5,13 +5,13 @@
package rpc package rpc
import ( import (
"http"; "http"
"log"; "log"
"net"; "net"
"once"; "once"
"os"; "os"
"strings"; "strings"
"testing"; "testing"
) )
var serverAddr string var serverAddr string
@ -21,31 +21,31 @@ const second = 1e9
type Args struct { type Args struct {
A, B int; A, B int
} }
type Reply struct { type Reply struct {
C int; C int
} }
type Arith int type Arith int
func (t *Arith) Add(args *Args, reply *Reply) os.Error { func (t *Arith) Add(args *Args, reply *Reply) os.Error {
reply.C = args.A + args.B; reply.C = args.A + args.B
return nil; return nil
} }
func (t *Arith) Mul(args *Args, reply *Reply) os.Error { func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
reply.C = args.A * args.B; reply.C = args.A * args.B
return nil; return nil
} }
func (t *Arith) Div(args *Args, reply *Reply) os.Error { func (t *Arith) Div(args *Args, reply *Reply) os.Error {
if args.B == 0 { if args.B == 0 {
return os.ErrorString("divide by zero") return os.ErrorString("divide by zero")
} }
reply.C = args.A / args.B; reply.C = args.A / args.B
return nil; return nil
} }
func (t *Arith) Error(args *Args, reply *Reply) os.Error { func (t *Arith) Error(args *Args, reply *Reply) os.Error {
@ -53,39 +53,39 @@ func (t *Arith) Error(args *Args, reply *Reply) os.Error {
} }
func startServer() { func startServer() {
Register(new(Arith)); Register(new(Arith))
l, e := net.Listen("tcp", ":0"); // any available address l, e := net.Listen("tcp", ":0") // any available address
if e != nil { if e != nil {
log.Exitf("net.Listen tcp :0: %v", e) log.Exitf("net.Listen tcp :0: %v", e)
} }
serverAddr = l.Addr().String(); serverAddr = l.Addr().String()
log.Stderr("Test RPC server listening on ", serverAddr); log.Stderr("Test RPC server listening on ", serverAddr)
go Accept(l); go Accept(l)
HandleHTTP(); HandleHTTP()
l, e = net.Listen("tcp", ":0"); // any available address l, e = net.Listen("tcp", ":0") // any available address
if e != nil { if e != nil {
log.Stderrf("net.Listen tcp :0: %v", e); log.Stderrf("net.Listen tcp :0: %v", e)
os.Exit(1); os.Exit(1)
} }
httpServerAddr = l.Addr().String(); httpServerAddr = l.Addr().String()
log.Stderr("Test HTTP RPC server listening on ", httpServerAddr); log.Stderr("Test HTTP RPC server listening on ", httpServerAddr)
go http.Serve(l, nil); go http.Serve(l, nil)
} }
func TestRPC(t *testing.T) { func TestRPC(t *testing.T) {
once.Do(startServer); once.Do(startServer)
client, err := Dial("tcp", serverAddr); client, err := Dial("tcp", serverAddr)
if err != nil { if err != nil {
t.Fatal("dialing", err) t.Fatal("dialing", err)
} }
// Synchronous calls // Synchronous calls
args := &Args{7, 8}; args := &Args{7, 8}
reply := new(Reply); reply := new(Reply)
err = client.Call("Arith.Add", args, reply); err = client.Call("Arith.Add", args, reply)
if err != nil { if err != nil {
t.Errorf("Add: expected no error but got string %q", err.String()) t.Errorf("Add: expected no error but got string %q", err.String())
} }
@ -93,9 +93,9 @@ func TestRPC(t *testing.T) {
t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B) t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
} }
args = &Args{7, 8}; args = &Args{7, 8}
reply = new(Reply); reply = new(Reply)
err = client.Call("Arith.Mul", args, reply); err = client.Call("Arith.Mul", args, reply)
if err != nil { if err != nil {
t.Errorf("Mul: expected no error but got string %q", err.String()) t.Errorf("Mul: expected no error but got string %q", err.String())
} }
@ -104,13 +104,13 @@ func TestRPC(t *testing.T) {
} }
// Out of order. // Out of order.
args = &Args{7, 8}; args = &Args{7, 8}
mulReply := new(Reply); mulReply := new(Reply)
mulCall := client.Go("Arith.Mul", args, mulReply, nil); mulCall := client.Go("Arith.Mul", args, mulReply, nil)
addReply := new(Reply); addReply := new(Reply)
addCall := client.Go("Arith.Add", args, addReply, nil); addCall := client.Go("Arith.Add", args, addReply, nil)
addCall = <-addCall.Done; addCall = <-addCall.Done
if addCall.Error != nil { if addCall.Error != nil {
t.Errorf("Add: expected no error but got string %q", addCall.Error.String()) t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
} }
@ -118,7 +118,7 @@ func TestRPC(t *testing.T) {
t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B) t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
} }
mulCall = <-mulCall.Done; mulCall = <-mulCall.Done
if mulCall.Error != nil { if mulCall.Error != nil {
t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String()) t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
} }
@ -127,9 +127,9 @@ func TestRPC(t *testing.T) {
} }
// Error test // Error test
args = &Args{7, 0}; args = &Args{7, 0}
reply = new(Reply); reply = new(Reply)
err = client.Call("Arith.Div", args, reply); err = client.Call("Arith.Div", args, reply)
// expect an error: zero divide // expect an error: zero divide
if err == nil { if err == nil {
t.Error("Div: expected error") t.Error("Div: expected error")
@ -139,17 +139,17 @@ func TestRPC(t *testing.T) {
} }
func TestHTTPRPC(t *testing.T) { func TestHTTPRPC(t *testing.T) {
once.Do(startServer); once.Do(startServer)
client, err := DialHTTP("tcp", httpServerAddr); client, err := DialHTTP("tcp", httpServerAddr)
if err != nil { if err != nil {
t.Fatal("dialing", err) t.Fatal("dialing", err)
} }
// Synchronous calls // Synchronous calls
args := &Args{7, 8}; args := &Args{7, 8}
reply := new(Reply); reply := new(Reply)
err = client.Call("Arith.Add", args, reply); err = client.Call("Arith.Add", args, reply)
if err != nil { if err != nil {
t.Errorf("Add: expected no error but got string %q", err.String()) t.Errorf("Add: expected no error but got string %q", err.String())
} }
@ -159,18 +159,18 @@ func TestHTTPRPC(t *testing.T) {
} }
func TestCheckUnknownService(t *testing.T) { func TestCheckUnknownService(t *testing.T) {
once.Do(startServer); once.Do(startServer)
conn, err := net.Dial("tcp", "", serverAddr); conn, err := net.Dial("tcp", "", serverAddr)
if err != nil { if err != nil {
t.Fatal("dialing:", err) t.Fatal("dialing:", err)
} }
client := NewClient(conn); client := NewClient(conn)
args := &Args{7, 8}; args := &Args{7, 8}
reply := new(Reply); reply := new(Reply)
err = client.Call("Unknown.Add", args, reply); err = client.Call("Unknown.Add", args, reply)
if err == nil { if err == nil {
t.Error("expected error calling unknown service") t.Error("expected error calling unknown service")
} else if strings.Index(err.String(), "service") < 0 { } else if strings.Index(err.String(), "service") < 0 {
@ -179,18 +179,18 @@ func TestCheckUnknownService(t *testing.T) {
} }
func TestCheckUnknownMethod(t *testing.T) { func TestCheckUnknownMethod(t *testing.T) {
once.Do(startServer); once.Do(startServer)
conn, err := net.Dial("tcp", "", serverAddr); conn, err := net.Dial("tcp", "", serverAddr)
if err != nil { if err != nil {
t.Fatal("dialing:", err) t.Fatal("dialing:", err)
} }
client := NewClient(conn); client := NewClient(conn)
args := &Args{7, 8}; args := &Args{7, 8}
reply := new(Reply); reply := new(Reply)
err = client.Call("Arith.Unknown", args, reply); err = client.Call("Arith.Unknown", args, reply)
if err == nil { if err == nil {
t.Error("expected error calling unknown service") t.Error("expected error calling unknown service")
} else if strings.Index(err.String(), "method") < 0 { } else if strings.Index(err.String(), "method") < 0 {
@ -199,17 +199,17 @@ func TestCheckUnknownMethod(t *testing.T) {
} }
func TestCheckBadType(t *testing.T) { func TestCheckBadType(t *testing.T) {
once.Do(startServer); once.Do(startServer)
conn, err := net.Dial("tcp", "", serverAddr); conn, err := net.Dial("tcp", "", serverAddr)
if err != nil { if err != nil {
t.Fatal("dialing:", err) t.Fatal("dialing:", err)
} }
client := NewClient(conn); client := NewClient(conn)
reply := new(Reply); reply := new(Reply)
err = client.Call("Arith.Add", reply, reply); // args, reply would be the correct thing to use err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
if err == nil { if err == nil {
t.Error("expected error calling Arith.Add with wrong arg type") t.Error("expected error calling Arith.Add with wrong arg type")
} else if strings.Index(err.String(), "type") < 0 { } else if strings.Index(err.String(), "type") < 0 {
@ -246,7 +246,7 @@ func (t *Bad) ReplyNotPublic(args *Args, reply *local) os.Error {
// Check that registration handles lots of bad methods and a type with no suitable methods. // Check that registration handles lots of bad methods and a type with no suitable methods.
func TestRegistrationError(t *testing.T) { func TestRegistrationError(t *testing.T) {
err := Register(new(Bad)); err := Register(new(Bad))
if err == nil { if err == nil {
t.Errorf("expected error registering bad type") t.Errorf("expected error registering bad type")
} }

View File

@ -26,56 +26,56 @@ type Type interface{}
// All types begin with a few common fields needed for // All types begin with a few common fields needed for
// the interface runtime. // the interface runtime.
type commonType struct { type commonType struct {
size uintptr; // size in bytes size uintptr // size in bytes
hash uint32; // hash of type; avoids computation in hash tables hash uint32 // hash of type; avoids computation in hash tables
alg uint8; // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM) alg uint8 // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM)
align uint8; // alignment of variable with this type align uint8 // alignment of variable with this type
fieldAlign uint8; // alignment of struct field with this type fieldAlign uint8 // alignment of struct field with this type
kind uint8; // enumeration for C kind uint8 // enumeration for C
string *string; // string form; unnecessary but undeniably useful string *string // string form; unnecessary but undeniably useful
*uncommonType; // (relatively) uncommon fields *uncommonType // (relatively) uncommon fields
} }
// Values for commonType.kind. // Values for commonType.kind.
const ( const (
kindBool = 1 + iota; kindBool = 1 + iota
kindInt; kindInt
kindInt8; kindInt8
kindInt16; kindInt16
kindInt32; kindInt32
kindInt64; kindInt64
kindUint; kindUint
kindUint8; kindUint8
kindUint16; kindUint16
kindUint32; kindUint32
kindUint64; kindUint64
kindUintptr; kindUintptr
kindFloat; kindFloat
kindFloat32; kindFloat32
kindFloat64; kindFloat64
kindArray; kindArray
kindChan; kindChan
kindDotDotDot; kindDotDotDot
kindFunc; kindFunc
kindInterface; kindInterface
kindMap; kindMap
kindPtr; kindPtr
kindSlice; kindSlice
kindString; kindString
kindStruct; kindStruct
kindUnsafePointer; kindUnsafePointer
kindNoPointers = 1 << 7; // OR'ed into kind kindNoPointers = 1 << 7 // OR'ed into kind
) )
// Method on non-interface type // Method on non-interface type
type method struct { type method struct {
hash uint32; // hash of name + pkg + typ hash uint32 // hash of name + pkg + typ
name *string; // name of method name *string // name of method
pkgPath *string; // nil for exported Names; otherwise import path pkgPath *string // nil for exported Names; otherwise import path
typ *Type; // .(*FuncType) underneath typ *Type // .(*FuncType) underneath
ifn unsafe.Pointer; // fn used in interface call (one-word receiver) ifn unsafe.Pointer // fn used in interface call (one-word receiver)
tfn unsafe.Pointer; // fn used for normal method call tfn unsafe.Pointer // fn used for normal method call
} }
// uncommonType is present only for types with names or methods // uncommonType is present only for types with names or methods
@ -83,9 +83,9 @@ type method struct {
// Using a pointer to this struct reduces the overall size required // Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods. // to describe an unnamed type with no methods.
type uncommonType struct { type uncommonType struct {
name *string; // name of type name *string // name of type
pkgPath *string; // import path; nil for built-in types like int, string pkgPath *string // import path; nil for built-in types like int, string
methods []method; // methods associated with type methods []method // methods associated with type
} }
// BoolType represents a boolean type. // BoolType represents a boolean type.
@ -145,91 +145,91 @@ type UnsafePointerType commonType
// ArrayType represents a fixed array type. // ArrayType represents a fixed array type.
type ArrayType struct { type ArrayType struct {
commonType; commonType
elem *Type; // array element type elem *Type // array element type
len uintptr; len uintptr
} }
// SliceType represents a slice type. // SliceType represents a slice type.
type SliceType struct { type SliceType struct {
commonType; commonType
elem *Type; // slice element type elem *Type // slice element type
} }
// ChanDir represents a channel type's direction. // ChanDir represents a channel type's direction.
type ChanDir int type ChanDir int
const ( const (
RecvDir ChanDir = 1 << iota; // <-chan RecvDir ChanDir = 1 << iota // <-chan
SendDir; // chan<- SendDir // chan<-
BothDir = RecvDir | SendDir; // chan BothDir = RecvDir | SendDir // chan
) )
// ChanType represents a channel type. // ChanType represents a channel type.
type ChanType struct { type ChanType struct {
commonType; commonType
elem *Type; // channel element type elem *Type // channel element type
dir uintptr; // channel direction (ChanDir) dir uintptr // channel direction (ChanDir)
} }
// FuncType represents a function type. // FuncType represents a function type.
type FuncType struct { type FuncType struct {
commonType; commonType
in []*Type; // input parameter types in []*Type // input parameter types
out []*Type; // output parameter types out []*Type // output parameter types
} }
// Method on interface type // Method on interface type
type imethod struct { type imethod struct {
hash uint32; // hash of name + pkg + typ; same hash as method hash uint32 // hash of name + pkg + typ; same hash as method
perm uint32; // index of function pointer in interface map perm uint32 // index of function pointer in interface map
name *string; // name of method name *string // name of method
pkgPath *string; // nil for exported Names; otherwise import path pkgPath *string // nil for exported Names; otherwise import path
typ *Type; // .(*FuncType) underneath typ *Type // .(*FuncType) underneath
} }
// InterfaceType represents an interface type. // InterfaceType represents an interface type.
type InterfaceType struct { type InterfaceType struct {
commonType; commonType
methods []imethod; // sorted by hash methods []imethod // sorted by hash
} }
// MapType represents a map type. // MapType represents a map type.
type MapType struct { type MapType struct {
commonType; commonType
key *Type; // map key type key *Type // map key type
elem *Type; // map element (value) type elem *Type // map element (value) type
} }
// PtrType represents a pointer type. // PtrType represents a pointer type.
type PtrType struct { type PtrType struct {
commonType; commonType
elem *Type; // pointer element (pointed at) type elem *Type // pointer element (pointed at) type
} }
// Struct field // Struct field
type structField struct { type structField struct {
name *string; // nil for embedded fields name *string // nil for embedded fields
pkgPath *string; // nil for exported Names; otherwise import path pkgPath *string // nil for exported Names; otherwise import path
typ *Type; // type of field typ *Type // type of field
tag *string; // nil if no tag tag *string // nil if no tag
offset uintptr; // byte offset of field within struct offset uintptr // byte offset of field within struct
} }
// StructType represents a struct type. // StructType represents a struct type.
type StructType struct { type StructType struct {
commonType; commonType
fields []structField; // sorted by offset fields []structField // sorted by offset
} }
/* /*
* Must match iface.c:/Itab and compilers. * Must match iface.c:/Itab and compilers.
*/ */
type Itable struct { type Itable struct {
Itype *Type; // (*tab.inter).(*InterfaceType) is the interface type Itype *Type // (*tab.inter).(*InterfaceType) is the interface type
Type *Type; Type *Type
link *Itable; link *Itable
bad int32; bad int32
unused int32; unused int32
Fn [100000]uintptr; // bigger than we'll ever see Fn [100000]uintptr // bigger than we'll ever see
} }

View File

@ -11,19 +11,19 @@ package sort
// elements of the collection be enumerated by an integer index. // elements of the collection be enumerated by an integer index.
type Interface interface { type Interface interface {
// Len is the number of elements in the collection. // Len is the number of elements in the collection.
Len() int; Len() int
// Less returns whether the element with index i is should sort // Less returns whether the element with index i is should sort
// before the element with index j. // before the element with index j.
Less(i, j int) bool; Less(i, j int) bool
// Swap swaps the elements with indexes i and j. // Swap swaps the elements with indexes i and j.
Swap(i, j int); Swap(i, j int)
} }
func min(a, b int) int { func min(a, b int) int {
if a < b { if a < b {
return a return a
} }
return b; return b
} }
// Insertion sort // Insertion sort
@ -40,9 +40,9 @@ func insertionSort(data Interface, a, b int) {
// Move the median of the three values data[a], data[b], data[c] into data[a]. // Move the median of the three values data[a], data[b], data[c] into data[a].
func medianOfThree(data Interface, a, b, c int) { func medianOfThree(data Interface, a, b, c int) {
m0 := b; m0 := b
m1 := a; m1 := a
m2 := c; m2 := c
// bubble sort on 3 elements // bubble sort on 3 elements
if data.Less(m1, m0) { if data.Less(m1, m0) {
data.Swap(m1, m0) data.Swap(m1, m0)
@ -63,15 +63,15 @@ func swapRange(data Interface, a, b, n int) {
} }
func doPivot(data Interface, lo, hi int) (midlo, midhi int) { func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
m := (lo + hi) / 2; m := (lo + hi) / 2
if hi-lo > 40 { if hi-lo > 40 {
// Tukey's ``Ninther,'' median of three medians of three. // Tukey's ``Ninther,'' median of three medians of three.
s := (hi - lo) / 8; s := (hi - lo) / 8
medianOfThree(data, lo, lo+s, lo+2*s); medianOfThree(data, lo, lo+s, lo+2*s)
medianOfThree(data, m, m-s, m+s); medianOfThree(data, m, m-s, m+s)
medianOfThree(data, hi-1, hi-1-s, hi-1-2*s); medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
} }
medianOfThree(data, lo, m, hi-1); medianOfThree(data, lo, m, hi-1)
// Invariants are: // Invariants are:
// data[lo] = pivot (set up by ChoosePivot) // data[lo] = pivot (set up by ChoosePivot)
@ -83,65 +83,65 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
// //
// Once b meets c, can swap the "= pivot" sections // Once b meets c, can swap the "= pivot" sections
// into the middle of the array. // into the middle of the array.
pivot := lo; pivot := lo
a, b, c, d := lo+1, lo+1, hi, hi; a, b, c, d := lo+1, lo+1, hi, hi
for b < c { for b < c {
if data.Less(b, pivot) { // data[b] < pivot if data.Less(b, pivot) { // data[b] < pivot
b++; b++
continue; continue
} }
if !data.Less(pivot, b) { // data[b] = pivot if !data.Less(pivot, b) { // data[b] = pivot
data.Swap(a, b); data.Swap(a, b)
a++; a++
b++; b++
continue; continue
} }
if data.Less(pivot, c-1) { // data[c-1] > pivot if data.Less(pivot, c-1) { // data[c-1] > pivot
c--; c--
continue; continue
} }
if !data.Less(c-1, pivot) { // data[c-1] = pivot if !data.Less(c-1, pivot) { // data[c-1] = pivot
data.Swap(c-1, d-1); data.Swap(c-1, d-1)
c--; c--
d--; d--
continue; continue
} }
// data[b] > pivot; data[c-1] < pivot // data[b] > pivot; data[c-1] < pivot
data.Swap(b, c-1); data.Swap(b, c-1)
b++; b++
c--; c--
} }
n := min(b-a, a-lo); n := min(b-a, a-lo)
swapRange(data, lo, b-n, n); swapRange(data, lo, b-n, n)
n = min(hi-d, d-c); n = min(hi-d, d-c)
swapRange(data, c, hi-n, n); swapRange(data, c, hi-n, n)
return lo + b - a, hi - (d - c); return lo + b - a, hi - (d - c)
} }
func quickSort(data Interface, a, b int) { func quickSort(data Interface, a, b int) {
if b-a > 7 { if b-a > 7 {
mlo, mhi := doPivot(data, a, b); mlo, mhi := doPivot(data, a, b)
quickSort(data, a, mlo); quickSort(data, a, mlo)
quickSort(data, mhi, b); quickSort(data, mhi, b)
} else if b-a > 1 { } else if b-a > 1 {
insertionSort(data, a, b) insertionSort(data, a, b)
} }
} }
func Sort(data Interface) { quickSort(data, 0, data.Len()) } func Sort(data Interface) { quickSort(data, 0, data.Len()) }
func IsSorted(data Interface) bool { func IsSorted(data Interface) bool {
n := data.Len(); n := data.Len()
for i := n - 1; i > 0; i-- { for i := n - 1; i > 0; i-- {
if data.Less(i, i-1) { if data.Less(i, i-1) {
return false return false
} }
} }
return true; return true
} }
@ -150,49 +150,49 @@ func IsSorted(data Interface) bool {
// IntArray attaches the methods of Interface to []int, sorting in increasing order. // IntArray attaches the methods of Interface to []int, sorting in increasing order.
type IntArray []int type IntArray []int
func (p IntArray) Len() int { return len(p) } func (p IntArray) Len() int { return len(p) }
func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } func (p IntArray) Less(i, j int) bool { return p[i] < p[j] }
func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Sort is a convenience method. // Sort is a convenience method.
func (p IntArray) Sort() { Sort(p) } func (p IntArray) Sort() { Sort(p) }
// FloatArray attaches the methods of Interface to []float, sorting in increasing order. // FloatArray attaches the methods of Interface to []float, sorting in increasing order.
type FloatArray []float type FloatArray []float
func (p FloatArray) Len() int { return len(p) } func (p FloatArray) Len() int { return len(p) }
func (p FloatArray) Less(i, j int) bool { return p[i] < p[j] } func (p FloatArray) Less(i, j int) bool { return p[i] < p[j] }
func (p FloatArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p FloatArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Sort is a convenience method. // Sort is a convenience method.
func (p FloatArray) Sort() { Sort(p) } func (p FloatArray) Sort() { Sort(p) }
// StringArray attaches the methods of Interface to []string, sorting in increasing order. // StringArray attaches the methods of Interface to []string, sorting in increasing order.
type StringArray []string type StringArray []string
func (p StringArray) Len() int { return len(p) } func (p StringArray) Len() int { return len(p) }
func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } func (p StringArray) Less(i, j int) bool { return p[i] < p[j] }
func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Sort is a convenience method. // Sort is a convenience method.
func (p StringArray) Sort() { Sort(p) } func (p StringArray) Sort() { Sort(p) }
// Convenience wrappers for common cases // Convenience wrappers for common cases
// SortInts sorts an array of ints in increasing order. // SortInts sorts an array of ints in increasing order.
func SortInts(a []int) { Sort(IntArray(a)) } func SortInts(a []int) { Sort(IntArray(a)) }
// SortFloats sorts an array of floats in increasing order. // SortFloats sorts an array of floats in increasing order.
func SortFloats(a []float) { Sort(FloatArray(a)) } func SortFloats(a []float) { Sort(FloatArray(a)) }
// SortStrings sorts an array of strings in increasing order. // SortStrings sorts an array of strings in increasing order.
func SortStrings(a []string) { Sort(StringArray(a)) } func SortStrings(a []string) { Sort(StringArray(a)) }
// IntsAreSorted tests whether an array of ints is sorted in increasing order. // IntsAreSorted tests whether an array of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) }
// FloatsAreSorted tests whether an array of floats is sorted in increasing order. // FloatsAreSorted tests whether an array of floats is sorted in increasing order.
func FloatsAreSorted(a []float) bool { return IsSorted(FloatArray(a)) } func FloatsAreSorted(a []float) bool { return IsSorted(FloatArray(a)) }
// StringsAreSorted tests whether an array of strings is sorted in increasing order. // StringsAreSorted tests whether an array of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) }

View File

@ -5,10 +5,10 @@
package sort package sort
import ( import (
"fmt"; "fmt"
"rand"; "rand"
"strconv"; "strconv"
"testing"; "testing"
) )
@ -17,173 +17,173 @@ var floats = [...]float{74.3, 59.0, 238.2, -784.0, 2.3, 9845.768, -959.7485, 905
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"} var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
func TestSortIntArray(t *testing.T) { func TestSortIntArray(t *testing.T) {
data := ints; data := ints
a := IntArray(&data); a := IntArray(&data)
Sort(a); Sort(a)
if !IsSorted(a) { if !IsSorted(a) {
t.Errorf("sorted %v", ints); t.Errorf("sorted %v", ints)
t.Errorf(" got %v", data); t.Errorf(" got %v", data)
} }
} }
func TestSortFloatArray(t *testing.T) { func TestSortFloatArray(t *testing.T) {
data := floats; data := floats
a := FloatArray(&data); a := FloatArray(&data)
Sort(a); Sort(a)
if !IsSorted(a) { if !IsSorted(a) {
t.Errorf("sorted %v", floats); t.Errorf("sorted %v", floats)
t.Errorf(" got %v", data); t.Errorf(" got %v", data)
} }
} }
func TestSortStringArray(t *testing.T) { func TestSortStringArray(t *testing.T) {
data := strings; data := strings
a := StringArray(&data); a := StringArray(&data)
Sort(a); Sort(a)
if !IsSorted(a) { if !IsSorted(a) {
t.Errorf("sorted %v", strings); t.Errorf("sorted %v", strings)
t.Errorf(" got %v", data); t.Errorf(" got %v", data)
} }
} }
func TestSortInts(t *testing.T) { func TestSortInts(t *testing.T) {
data := ints; data := ints
SortInts(&data); SortInts(&data)
if !IntsAreSorted(&data) { if !IntsAreSorted(&data) {
t.Errorf("sorted %v", ints); t.Errorf("sorted %v", ints)
t.Errorf(" got %v", data); t.Errorf(" got %v", data)
} }
} }
func TestSortFloats(t *testing.T) { func TestSortFloats(t *testing.T) {
data := floats; data := floats
SortFloats(&data); SortFloats(&data)
if !FloatsAreSorted(&data) { if !FloatsAreSorted(&data) {
t.Errorf("sorted %v", floats); t.Errorf("sorted %v", floats)
t.Errorf(" got %v", data); t.Errorf(" got %v", data)
} }
} }
func TestSortStrings(t *testing.T) { func TestSortStrings(t *testing.T) {
data := strings; data := strings
SortStrings(&data); SortStrings(&data)
if !StringsAreSorted(&data) { if !StringsAreSorted(&data) {
t.Errorf("sorted %v", strings); t.Errorf("sorted %v", strings)
t.Errorf(" got %v", data); t.Errorf(" got %v", data)
} }
} }
func TestSortLarge_Random(t *testing.T) { func TestSortLarge_Random(t *testing.T) {
data := make([]int, 1000000); data := make([]int, 1000000)
for i := 0; i < len(data); i++ { for i := 0; i < len(data); i++ {
data[i] = rand.Intn(100) data[i] = rand.Intn(100)
} }
if IntsAreSorted(data) { if IntsAreSorted(data) {
t.Fatalf("terrible rand.rand") t.Fatalf("terrible rand.rand")
} }
SortInts(data); SortInts(data)
if !IntsAreSorted(data) { if !IntsAreSorted(data) {
t.Errorf("sort didn't sort - 1M ints") t.Errorf("sort didn't sort - 1M ints")
} }
} }
func BenchmarkSortString1K(b *testing.B) { func BenchmarkSortString1K(b *testing.B) {
b.StopTimer(); b.StopTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
data := make([]string, 1<<10); data := make([]string, 1<<10)
for i := 0; i < len(data); i++ { for i := 0; i < len(data); i++ {
data[i] = strconv.Itoa(i ^ 0x2cc) data[i] = strconv.Itoa(i ^ 0x2cc)
} }
b.StartTimer(); b.StartTimer()
SortStrings(data); SortStrings(data)
b.StopTimer(); b.StopTimer()
} }
} }
func BenchmarkSortInt1K(b *testing.B) { func BenchmarkSortInt1K(b *testing.B) {
b.StopTimer(); b.StopTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
data := make([]int, 1<<10); data := make([]int, 1<<10)
for i := 0; i < len(data); i++ { for i := 0; i < len(data); i++ {
data[i] = i ^ 0x2cc data[i] = i ^ 0x2cc
} }
b.StartTimer(); b.StartTimer()
SortInts(data); SortInts(data)
b.StopTimer(); b.StopTimer()
} }
} }
func BenchmarkSortInt64K(b *testing.B) { func BenchmarkSortInt64K(b *testing.B) {
b.StopTimer(); b.StopTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
data := make([]int, 1<<16); data := make([]int, 1<<16)
for i := 0; i < len(data); i++ { for i := 0; i < len(data); i++ {
data[i] = i ^ 0xcccc data[i] = i ^ 0xcccc
} }
b.StartTimer(); b.StartTimer()
SortInts(data); SortInts(data)
b.StopTimer(); b.StopTimer()
} }
} }
const ( const (
_Sawtooth = iota; _Sawtooth = iota
_Rand; _Rand
_Stagger; _Stagger
_Plateau; _Plateau
_Shuffle; _Shuffle
_NDist; _NDist
) )
const ( const (
_Copy = iota; _Copy = iota
_Reverse; _Reverse
_ReverseFirstHalf; _ReverseFirstHalf
_ReverseSecondHalf; _ReverseSecondHalf
_Sorted; _Sorted
_Dither; _Dither
_NMode; _NMode
) )
type testingData struct { type testingData struct {
desc string; desc string
t *testing.T; t *testing.T
data []int; data []int
maxswap int; // number of swaps allowed maxswap int // number of swaps allowed
nswap int; nswap int
} }
func (d *testingData) Len() int { return len(d.data) } func (d *testingData) Len() int { return len(d.data) }
func (d *testingData) Less(i, j int) bool { return d.data[i] < d.data[j] } func (d *testingData) Less(i, j int) bool { return d.data[i] < d.data[j] }
func (d *testingData) Swap(i, j int) { func (d *testingData) Swap(i, j int) {
if d.nswap >= d.maxswap { if d.nswap >= d.maxswap {
d.t.Errorf("%s: used %d swaps sorting array of %d", d.desc, d.nswap, len(d.data)); d.t.Errorf("%s: used %d swaps sorting array of %d", d.desc, d.nswap, len(d.data))
d.t.FailNow(); d.t.FailNow()
} }
d.nswap++; d.nswap++
d.data[i], d.data[j] = d.data[j], d.data[i]; d.data[i], d.data[j] = d.data[j], d.data[i]
} }
func lg(n int) int { func lg(n int) int {
i := 0; i := 0
for 1<<uint(i) < n { for 1<<uint(i) < n {
i++ i++
} }
return i; return i
} }
func TestBentleyMcIlroy(t *testing.T) { func TestBentleyMcIlroy(t *testing.T) {
sizes := []int{100, 1023, 1024, 1025}; sizes := []int{100, 1023, 1024, 1025}
dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"}; dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"}
modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"}; modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"}
var tmp1, tmp2 [1025]int; var tmp1, tmp2 [1025]int
for ni := 0; ni < len(sizes); ni++ { for ni := 0; ni < len(sizes); ni++ {
n := sizes[ni]; n := sizes[ni]
for m := 1; m < 2*n; m *= 2 { for m := 1; m < 2*n; m *= 2 {
for dist := 0; dist < _NDist; dist++ { for dist := 0; dist < _NDist; dist++ {
j := 0; j := 0
k := 1; k := 1
data := tmp1[0:n]; data := tmp1[0:n]
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
switch dist { switch dist {
case _Sawtooth: case _Sawtooth:
@ -196,16 +196,16 @@ func TestBentleyMcIlroy(t *testing.T) {
data[i] = min(i, m) data[i] = min(i, m)
case _Shuffle: case _Shuffle:
if rand.Intn(m) != 0 { if rand.Intn(m) != 0 {
j += 2; j += 2
data[i] = j; data[i] = j
} else { } else {
k += 2; k += 2
data[i] = k; data[i] = k
} }
} }
} }
mdata := tmp2[0:n]; mdata := tmp2[0:n]
for mode := 0; mode < _NMode; mode++ { for mode := 0; mode < _NMode; mode++ {
switch mode { switch mode {
case _Copy: case _Copy:
@ -236,16 +236,16 @@ func TestBentleyMcIlroy(t *testing.T) {
} }
// SortInts is known to be correct // SortInts is known to be correct
// because mode Sort runs after mode _Copy. // because mode Sort runs after mode _Copy.
SortInts(mdata); SortInts(mdata)
case _Dither: case _Dither:
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
mdata[i] = data[i] + i%5 mdata[i] = data[i] + i%5
} }
} }
desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]); desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
d := &testingData{desc, t, mdata[0:n], n * lg(n) * 12 / 10, 0}; d := &testingData{desc, t, mdata[0:n], n * lg(n) * 12 / 10, 0}
Sort(d); Sort(d)
// If we were testing C qsort, we'd have to make a copy // If we were testing C qsort, we'd have to make a copy
// of the array and sort it ourselves and then compare // of the array and sort it ourselves and then compare
@ -256,9 +256,9 @@ func TestBentleyMcIlroy(t *testing.T) {
// mutating method Sort can call is TestingData.swap, // mutating method Sort can call is TestingData.swap,
// it suffices here just to check that the final array is sorted. // it suffices here just to check that the final array is sorted.
if !IntsAreSorted(mdata) { if !IntsAreSorted(mdata) {
t.Errorf("%s: ints not sorted", desc); t.Errorf("%s: ints not sorted", desc)
t.Errorf("\t%v", mdata); t.Errorf("\t%v", mdata)
t.FailNow(); t.FailNow()
} }
} }
} }

View File

@ -13,15 +13,15 @@
package strconv package strconv
import ( import (
"math"; "math"
"os"; "os"
) )
var optimize = true // can change for testing var optimize = true // can change for testing
// TODO(rsc): Better truncation handling. // TODO(rsc): Better truncation handling.
func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) { func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
i := 0; i := 0
// optional sign // optional sign
if i >= len(s) { if i >= len(s) {
@ -31,35 +31,35 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
case s[i] == '+': case s[i] == '+':
i++ i++
case s[i] == '-': case s[i] == '-':
neg = true; neg = true
i++; i++
} }
// digits // digits
b := new(decimal); b := new(decimal)
sawdot := false; sawdot := false
sawdigits := false; sawdigits := false
for ; i < len(s); i++ { for ; i < len(s); i++ {
switch { switch {
case s[i] == '.': case s[i] == '.':
if sawdot { if sawdot {
return return
} }
sawdot = true; sawdot = true
b.dp = b.nd; b.dp = b.nd
continue; continue
case '0' <= s[i] && s[i] <= '9': case '0' <= s[i] && s[i] <= '9':
sawdigits = true; sawdigits = true
if s[i] == '0' && b.nd == 0 { // ignore leading zeros if s[i] == '0' && b.nd == 0 { // ignore leading zeros
b.dp--; b.dp--
continue; continue
} }
b.d[b.nd] = s[i]; b.d[b.nd] = s[i]
b.nd++; b.nd++
continue; continue
} }
break; break
} }
if !sawdigits { if !sawdigits {
return return
@ -74,50 +74,50 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
// a lot (say, 100000). it doesn't matter if it's // a lot (say, 100000). it doesn't matter if it's
// not the exact number. // not the exact number.
if i < len(s) && s[i] == 'e' { if i < len(s) && s[i] == 'e' {
i++; i++
if i >= len(s) { if i >= len(s) {
return return
} }
esign := 1; esign := 1
if s[i] == '+' { if s[i] == '+' {
i++ i++
} else if s[i] == '-' { } else if s[i] == '-' {
i++; i++
esign = -1; esign = -1
} }
if i >= len(s) || s[i] < '0' || s[i] > '9' { if i >= len(s) || s[i] < '0' || s[i] > '9' {
return return
} }
e := 0; e := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if e < 10000 { if e < 10000 {
e = e*10 + int(s[i]) - '0' e = e*10 + int(s[i]) - '0'
} }
} }
b.dp += e * esign; b.dp += e * esign
} }
if i != len(s) { if i != len(s) {
return return
} }
d = b; d = b
ok = true; ok = true
return; return
} }
// decimal power of ten to binary power of two. // decimal power of ten to binary power of two.
var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26} var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uint64, overflow bool) { func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uint64, overflow bool) {
var exp int; var exp int
var mant uint64; var mant uint64
// Zero is always a special case. // Zero is always a special case.
if d.nd == 0 { if d.nd == 0 {
mant = 0; mant = 0
exp = flt.bias; exp = flt.bias
goto out; goto out
} }
// Obvious overflow/underflow. // Obvious overflow/underflow.
@ -128,44 +128,44 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
} }
if d.dp < -330 { if d.dp < -330 {
// zero // zero
mant = 0; mant = 0
exp = flt.bias; exp = flt.bias
goto out; goto out
} }
// Scale by powers of two until in range [0.5, 1.0) // Scale by powers of two until in range [0.5, 1.0)
exp = 0; exp = 0
for d.dp > 0 { for d.dp > 0 {
var n int; var n int
if d.dp >= len(powtab) { if d.dp >= len(powtab) {
n = 27 n = 27
} else { } else {
n = powtab[d.dp] n = powtab[d.dp]
} }
d.Shift(-n); d.Shift(-n)
exp += n; exp += n
} }
for d.dp < 0 || d.dp == 0 && d.d[0] < '5' { for d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
var n int; var n int
if -d.dp >= len(powtab) { if -d.dp >= len(powtab) {
n = 27 n = 27
} else { } else {
n = powtab[-d.dp] n = powtab[-d.dp]
} }
d.Shift(n); d.Shift(n)
exp -= n; exp -= n
} }
// Our range is [0.5,1) but floating point range is [1,2). // Our range is [0.5,1) but floating point range is [1,2).
exp--; exp--
// Minimum representable exponent is flt.bias+1. // Minimum representable exponent is flt.bias+1.
// If the exponent is smaller, move it up and // If the exponent is smaller, move it up and
// adjust d accordingly. // adjust d accordingly.
if exp < flt.bias+1 { if exp < flt.bias+1 {
n := flt.bias + 1 - exp; n := flt.bias + 1 - exp
d.Shift(-n); d.Shift(-n)
exp += n; exp += n
} }
if exp-flt.bias >= 1<<flt.expbits-1 { if exp-flt.bias >= 1<<flt.expbits-1 {
@ -173,12 +173,12 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
} }
// Extract 1+flt.mantbits bits. // Extract 1+flt.mantbits bits.
mant = d.Shift(int(1 + flt.mantbits)).RoundedInteger(); mant = d.Shift(int(1 + flt.mantbits)).RoundedInteger()
// Rounding might have added a bit; shift down. // Rounding might have added a bit; shift down.
if mant == 2<<flt.mantbits { if mant == 2<<flt.mantbits {
mant >>= 1; mant >>= 1
exp++; exp++
if exp-flt.bias >= 1<<flt.expbits-1 { if exp-flt.bias >= 1<<flt.expbits-1 {
goto overflow goto overflow
} }
@ -188,46 +188,46 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
if mant&(1<<flt.mantbits) == 0 { if mant&(1<<flt.mantbits) == 0 {
exp = flt.bias exp = flt.bias
} }
goto out; goto out
overflow: overflow:
// ±Inf // ±Inf
mant = 0; mant = 0
exp = 1<<flt.expbits - 1 + flt.bias; exp = 1<<flt.expbits - 1 + flt.bias
overflow = true; overflow = true
out: out:
// Assemble bits. // Assemble bits.
bits := mant & (uint64(1)<<flt.mantbits - 1); bits := mant & (uint64(1)<<flt.mantbits - 1)
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits; bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
if neg { if neg {
bits |= 1 << flt.mantbits << flt.expbits bits |= 1 << flt.mantbits << flt.expbits
} }
return bits, overflow; return bits, overflow
} }
// Compute exact floating-point integer from d's digits. // Compute exact floating-point integer from d's digits.
// Caller is responsible for avoiding overflow. // Caller is responsible for avoiding overflow.
func decimalAtof64Int(neg bool, d *decimal) float64 { func decimalAtof64Int(neg bool, d *decimal) float64 {
f := float64(0); f := float64(0)
for i := 0; i < d.nd; i++ { for i := 0; i < d.nd; i++ {
f = f*10 + float64(d.d[i]-'0') f = f*10 + float64(d.d[i]-'0')
} }
if neg { if neg {
f *= -1 // BUG work around 6g f = -f. f *= -1 // BUG work around 6g f = -f.
} }
return f; return f
} }
func decimalAtof32Int(neg bool, d *decimal) float32 { func decimalAtof32Int(neg bool, d *decimal) float32 {
f := float32(0); f := float32(0)
for i := 0; i < d.nd; i++ { for i := 0; i < d.nd; i++ {
f = f*10 + float32(d.d[i]-'0') f = f*10 + float32(d.d[i]-'0')
} }
if neg { if neg {
f *= -1 // BUG work around 6g f = -f. f *= -1 // BUG work around 6g f = -f.
} }
return f; return f
} }
// Exact powers of 10. // Exact powers of 10.
@ -252,26 +252,26 @@ func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) {
return return
} }
switch { switch {
case d.dp == d.nd: // int case d.dp == d.nd: // int
f := decimalAtof64Int(neg, d); f := decimalAtof64Int(neg, d)
return f, true; return f, true
case d.dp > d.nd && d.dp <= 15+22: // int * 10^k case d.dp > d.nd && d.dp <= 15+22: // int * 10^k
f := decimalAtof64Int(neg, d); f := decimalAtof64Int(neg, d)
k := d.dp - d.nd; k := d.dp - d.nd
// If exponent is big but number of digits is not, // If exponent is big but number of digits is not,
// can move a few zeros into the integer part. // can move a few zeros into the integer part.
if k > 22 { if k > 22 {
f *= float64pow10[k-22]; f *= float64pow10[k-22]
k = 22; k = 22
} }
return f * float64pow10[k], true; return f * float64pow10[k], true
case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k
f := decimalAtof64Int(neg, d); f := decimalAtof64Int(neg, d)
return f / float64pow10[d.nd-d.dp], true; return f / float64pow10[d.nd-d.dp], true
} }
return; return
} }
// If possible to convert decimal d to 32-bit float f exactly, // If possible to convert decimal d to 32-bit float f exactly,
@ -283,26 +283,26 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
return return
} }
switch { switch {
case d.dp == d.nd: // int case d.dp == d.nd: // int
f := decimalAtof32Int(neg, d); f := decimalAtof32Int(neg, d)
return f, true; return f, true
case d.dp > d.nd && d.dp <= 7+10: // int * 10^k case d.dp > d.nd && d.dp <= 7+10: // int * 10^k
f := decimalAtof32Int(neg, d); f := decimalAtof32Int(neg, d)
k := d.dp - d.nd; k := d.dp - d.nd
// If exponent is big but number of digits is not, // If exponent is big but number of digits is not,
// can move a few zeros into the integer part. // can move a few zeros into the integer part.
if k > 10 { if k > 10 {
f *= float32pow10[k-10]; f *= float32pow10[k-10]
k = 10; k = 10
} }
return f * float32pow10[k], true; return f * float32pow10[k], true
case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k
f := decimalAtof32Int(neg, d); f := decimalAtof32Int(neg, d)
return f / float32pow10[d.nd-d.dp], true; return f / float32pow10[d.nd-d.dp], true
} }
return; return
} }
// Atof32 converts the string s to a 32-bit floating-point number. // Atof32 converts the string s to a 32-bit floating-point number.
@ -320,7 +320,7 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
// away from the largest floating point number of the given size, // away from the largest floating point number of the given size,
// Atof32 returns f = ±Inf, err.Error = os.ERANGE. // Atof32 returns f = ±Inf, err.Error = os.ERANGE.
func Atof32(s string) (f float32, err os.Error) { func Atof32(s string) (f float32, err os.Error) {
neg, d, trunc, ok := stringToDecimal(s); neg, d, trunc, ok := stringToDecimal(s)
if !ok { if !ok {
return 0, &NumError{s, os.EINVAL} return 0, &NumError{s, os.EINVAL}
} }
@ -329,19 +329,19 @@ func Atof32(s string) (f float32, err os.Error) {
return f, nil return f, nil
} }
} }
b, ovf := decimalToFloatBits(neg, d, trunc, &float32info); b, ovf := decimalToFloatBits(neg, d, trunc, &float32info)
f = math.Float32frombits(uint32(b)); f = math.Float32frombits(uint32(b))
if ovf { if ovf {
err = &NumError{s, os.ERANGE} err = &NumError{s, os.ERANGE}
} }
return f, err; return f, err
} }
// Atof64 converts the string s to a 64-bit floating-point number. // Atof64 converts the string s to a 64-bit floating-point number.
// Except for the type of its result, its definition is the same as that // Except for the type of its result, its definition is the same as that
// of Atof32. // of Atof32.
func Atof64(s string) (f float64, err os.Error) { func Atof64(s string) (f float64, err os.Error) {
neg, d, trunc, ok := stringToDecimal(s); neg, d, trunc, ok := stringToDecimal(s)
if !ok { if !ok {
return 0, &NumError{s, os.EINVAL} return 0, &NumError{s, os.EINVAL}
} }
@ -350,20 +350,20 @@ func Atof64(s string) (f float64, err os.Error) {
return f, nil return f, nil
} }
} }
b, ovf := decimalToFloatBits(neg, d, trunc, &float64info); b, ovf := decimalToFloatBits(neg, d, trunc, &float64info)
f = math.Float64frombits(b); f = math.Float64frombits(b)
if ovf { if ovf {
err = &NumError{s, os.ERANGE} err = &NumError{s, os.ERANGE}
} }
return f, err; return f, err
} }
// Atof is like Atof32 or Atof64, depending on the size of float. // Atof is like Atof32 or Atof64, depending on the size of float.
func Atof(s string) (f float, err os.Error) { func Atof(s string) (f float, err os.Error) {
if FloatSize == 32 { if FloatSize == 32 {
f1, err1 := Atof32(s); f1, err1 := Atof32(s)
return float(f1), err1; return float(f1), err1
} }
f1, err1 := Atof64(s); f1, err1 := Atof64(s)
return float(f1), err1; return float(f1), err1
} }

View File

@ -5,16 +5,16 @@
package strconv_test package strconv_test
import ( import (
"os"; "os"
"reflect"; "reflect"
. "strconv"; . "strconv"
"testing"; "testing"
) )
type atofTest struct { type atofTest struct {
in string; in string
out string; out string
err os.Error; err os.Error
} }
var atoftests = []atofTest{ var atoftests = []atofTest{
@ -96,7 +96,7 @@ func init() {
// The atof routines return NumErrors wrapping // The atof routines return NumErrors wrapping
// the error and the string. Convert the table above. // the error and the string. Convert the table above.
for i := range atoftests { for i := range atoftests {
test := &atoftests[i]; test := &atoftests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
@ -104,19 +104,19 @@ func init() {
} }
func testAtof(t *testing.T, opt bool) { func testAtof(t *testing.T, opt bool) {
oldopt := SetOptimize(opt); oldopt := SetOptimize(opt)
for i := 0; i < len(atoftests); i++ { for i := 0; i < len(atoftests); i++ {
test := &atoftests[i]; test := &atoftests[i]
out, err := Atof64(test.in); out, err := Atof64(test.in)
outs := Ftoa64(out, 'g', -1); outs := Ftoa64(out, 'g', -1)
if outs != test.out || !reflect.DeepEqual(err, test.err) { if outs != test.out || !reflect.DeepEqual(err, test.err) {
t.Errorf("Atof64(%v) = %v, %v want %v, %v\n", t.Errorf("Atof64(%v) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
} }
if float64(float32(out)) == out { if float64(float32(out)) == out {
out32, err := Atof32(test.in); out32, err := Atof32(test.in)
outs := Ftoa32(out32, 'g', -1); outs := Ftoa32(out32, 'g', -1)
if outs != test.out || !reflect.DeepEqual(err, test.err) { if outs != test.out || !reflect.DeepEqual(err, test.err) {
t.Errorf("Atof32(%v) = %v, %v want %v, %v # %v\n", t.Errorf("Atof32(%v) = %v, %v want %v, %v # %v\n",
test.in, out32, err, test.out, test.err, out) test.in, out32, err, test.out, test.err, out)
@ -124,20 +124,20 @@ func testAtof(t *testing.T, opt bool) {
} }
if FloatSize == 64 || float64(float32(out)) == out { if FloatSize == 64 || float64(float32(out)) == out {
outf, err := Atof(test.in); outf, err := Atof(test.in)
outs := Ftoa(outf, 'g', -1); outs := Ftoa(outf, 'g', -1)
if outs != test.out || !reflect.DeepEqual(err, test.err) { if outs != test.out || !reflect.DeepEqual(err, test.err) {
t.Errorf("Ftoa(%v) = %v, %v want %v, %v # %v\n", t.Errorf("Ftoa(%v) = %v, %v want %v, %v # %v\n",
test.in, outf, err, test.out, test.err, out) test.in, outf, err, test.out, test.err, out)
} }
} }
} }
SetOptimize(oldopt); SetOptimize(oldopt)
} }
func TestAtof(t *testing.T) { testAtof(t, true) } func TestAtof(t *testing.T) { testAtof(t, true) }
func TestAtofSlow(t *testing.T) { testAtof(t, false) } func TestAtofSlow(t *testing.T) { testAtof(t, false) }
func BenchmarkAtofDecimal(b *testing.B) { func BenchmarkAtofDecimal(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {

View File

@ -7,19 +7,19 @@ package strconv
import "os" import "os"
type NumError struct { type NumError struct {
Num string; Num string
Error os.Error; Error os.Error
} }
func (e *NumError) String() string { return "parsing " + e.Num + ": " + e.Error.String() } func (e *NumError) String() string { return "parsing " + e.Num + ": " + e.Error.String() }
func computeIntsize() uint { func computeIntsize() uint {
siz := uint(8); siz := uint(8)
for 1<<siz != 0 { for 1<<siz != 0 {
siz *= 2 siz *= 2
} }
return siz; return siz
} }
var IntSize = computeIntsize() var IntSize = computeIntsize()
@ -29,7 +29,7 @@ func cutoff64(base int) uint64 {
if base < 2 { if base < 2 {
return 0 return 0
} }
return (1<<64-1)/uint64(base) + 1; return (1<<64-1)/uint64(base) + 1
} }
// Btoui64 interprets a string s in an arbitrary base b (2 to 36) // Btoui64 interprets a string s in an arbitrary base b (2 to 36)
@ -42,11 +42,11 @@ func cutoff64(base int) uint64 {
// digits, err.Error = os.EINVAL; if the value corresponding // digits, err.Error = os.EINVAL; if the value corresponding
// to s cannot be represented by a uint64, err.Error = os.ERANGE. // to s cannot be represented by a uint64, err.Error = os.ERANGE.
func Btoui64(s string, b int) (n uint64, err os.Error) { func Btoui64(s string, b int) (n uint64, err os.Error) {
s0 := s; s0 := s
switch { switch {
case len(s) < 1: case len(s) < 1:
err = os.EINVAL; err = os.EINVAL
goto Error; goto Error
case 2 <= b && b <= 36: case 2 <= b && b <= 36:
// valid base; nothing to do // valid base; nothing to do
@ -55,11 +55,11 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
// Look for octal, hex prefix. // Look for octal, hex prefix.
switch { switch {
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
b = 16; b = 16
s = s[2:]; s = s[2:]
if len(s) < 1 { if len(s) < 1 {
err = os.EINVAL; err = os.EINVAL
goto Error; goto Error
} }
case s[0] == '0': case s[0] == '0':
b = 8 b = 8
@ -68,15 +68,15 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
} }
default: default:
err = os.ErrorString("invalid base " + Itoa(b)); err = os.ErrorString("invalid base " + Itoa(b))
goto Error; goto Error
} }
n = 0; n = 0
cutoff := cutoff64(b); cutoff := cutoff64(b)
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
var v byte; var v byte
switch { switch {
case '0' <= s[i] && s[i] <= '9': case '0' <= s[i] && s[i] <= '9':
v = s[i] - '0' v = s[i] - '0'
@ -85,38 +85,38 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
case 'A' <= s[i] && s[i] <= 'Z': case 'A' <= s[i] && s[i] <= 'Z':
v = s[i] - 'A' + 10 v = s[i] - 'A' + 10
default: default:
n = 0; n = 0
err = os.EINVAL; err = os.EINVAL
goto Error; goto Error
} }
if int(v) >= b { if int(v) >= b {
n = 0; n = 0
err = os.EINVAL; err = os.EINVAL
goto Error; goto Error
} }
if n >= cutoff { if n >= cutoff {
// n*b overflows // n*b overflows
n = 1<<64 - 1; n = 1<<64 - 1
err = os.ERANGE; err = os.ERANGE
goto Error; goto Error
} }
n *= uint64(b); n *= uint64(b)
n1 := n + uint64(v); n1 := n + uint64(v)
if n1 < n { if n1 < n {
// n+v overflows // n+v overflows
n = 1<<64 - 1; n = 1<<64 - 1
err = os.ERANGE; err = os.ERANGE
goto Error; goto Error
} }
n = n1; n = n1
} }
return n, nil; return n, nil
Error: Error:
return n, &NumError{s0, err}; return n, &NumError{s0, err}
} }
// Atoui64 interprets a string s as a decimal number and // Atoui64 interprets a string s as a decimal number and
@ -137,21 +137,21 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
} }
// Pick off leading sign. // Pick off leading sign.
s0 := s; s0 := s
neg := false; neg := false
if s[0] == '+' { if s[0] == '+' {
s = s[1:] s = s[1:]
} else if s[0] == '-' { } else if s[0] == '-' {
neg = true; neg = true
s = s[1:]; s = s[1:]
} }
// Convert unsigned and check range. // Convert unsigned and check range.
var un uint64; var un uint64
un, err = Btoui64(s, base); un, err = Btoui64(s, base)
if err != nil && err.(*NumError).Error != os.ERANGE { if err != nil && err.(*NumError).Error != os.ERANGE {
err.(*NumError).Num = s0; err.(*NumError).Num = s0
return 0, err; return 0, err
} }
if !neg && un >= 1<<63 { if !neg && un >= 1<<63 {
return 1<<63 - 1, &NumError{s0, os.ERANGE} return 1<<63 - 1, &NumError{s0, os.ERANGE}
@ -159,43 +159,43 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
if neg && un > 1<<63 { if neg && un > 1<<63 {
return -1 << 63, &NumError{s0, os.ERANGE} return -1 << 63, &NumError{s0, os.ERANGE}
} }
n := int64(un); n := int64(un)
if neg { if neg {
n = -n n = -n
} }
return n, nil; return n, nil
} }
// Atoi64 is like Atoui64 but allows signed numbers and // Atoi64 is like Atoui64 but allows signed numbers and
// returns its result in an int64. // returns its result in an int64.
func Atoi64(s string) (i int64, err os.Error) { return Btoi64(s, 10) } func Atoi64(s string) (i int64, err os.Error) { return Btoi64(s, 10) }
// Atoui is like Atoui64 but returns its result as a uint. // Atoui is like Atoui64 but returns its result as a uint.
func Atoui(s string) (i uint, err os.Error) { func Atoui(s string) (i uint, err os.Error) {
i1, e1 := Atoui64(s); i1, e1 := Atoui64(s)
if e1 != nil && e1.(*NumError).Error != os.ERANGE { if e1 != nil && e1.(*NumError).Error != os.ERANGE {
return 0, e1 return 0, e1
} }
i = uint(i1); i = uint(i1)
if uint64(i) != i1 { if uint64(i) != i1 {
return ^uint(0), &NumError{s, os.ERANGE} return ^uint(0), &NumError{s, os.ERANGE}
} }
return i, nil; return i, nil
} }
// Atoi is like Atoi64 but returns its result as an int. // Atoi is like Atoi64 but returns its result as an int.
func Atoi(s string) (i int, err os.Error) { func Atoi(s string) (i int, err os.Error) {
i1, e1 := Atoi64(s); i1, e1 := Atoi64(s)
if e1 != nil && e1.(*NumError).Error != os.ERANGE { if e1 != nil && e1.(*NumError).Error != os.ERANGE {
return 0, e1 return 0, e1
} }
i = int(i1); i = int(i1)
if int64(i) != i1 { if int64(i) != i1 {
if i1 < 0 { if i1 < 0 {
return -1 << (IntSize - 1), &NumError{s, os.ERANGE} return -1 << (IntSize - 1), &NumError{s, os.ERANGE}
} }
return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE}; return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE}
} }
return i, nil; return i, nil
} }

View File

@ -5,16 +5,16 @@
package strconv_test package strconv_test
import ( import (
"os"; "os"
"reflect"; "reflect"
. "strconv"; . "strconv"
"testing"; "testing"
) )
type atoui64Test struct { type atoui64Test struct {
in string; in string
out uint64; out uint64
err os.Error; err os.Error
} }
var atoui64tests = []atoui64Test{ var atoui64tests = []atoui64Test{
@ -52,9 +52,9 @@ var btoui64tests = []atoui64Test{
} }
type atoi64Test struct { type atoi64Test struct {
in string; in string
out int64; out int64
err os.Error; err os.Error
} }
var atoi64tests = []atoi64Test{ var atoi64tests = []atoi64Test{
@ -102,9 +102,9 @@ var btoi64tests = []atoi64Test{
} }
type atoui32Test struct { type atoui32Test struct {
in string; in string
out uint32; out uint32
err os.Error; err os.Error
} }
var atoui32tests = []atoui32Test{ var atoui32tests = []atoui32Test{
@ -120,9 +120,9 @@ var atoui32tests = []atoui32Test{
} }
type atoi32Test struct { type atoi32Test struct {
in string; in string
out int32; out int32
err os.Error; err os.Error
} }
var atoi32tests = []atoi32Test{ var atoi32tests = []atoi32Test{
@ -151,37 +151,37 @@ func init() {
// The atoi routines return NumErrors wrapping // The atoi routines return NumErrors wrapping
// the error and the string. Convert the tables above. // the error and the string. Convert the tables above.
for i := range atoui64tests { for i := range atoui64tests {
test := &atoui64tests[i]; test := &atoui64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
} }
for i := range btoui64tests { for i := range btoui64tests {
test := &btoui64tests[i]; test := &btoui64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
} }
for i := range atoi64tests { for i := range atoi64tests {
test := &atoi64tests[i]; test := &atoi64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
} }
for i := range btoi64tests { for i := range btoi64tests {
test := &btoi64tests[i]; test := &btoi64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
} }
for i := range atoui32tests { for i := range atoui32tests {
test := &atoui32tests[i]; test := &atoui32tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
} }
for i := range atoi32tests { for i := range atoi32tests {
test := &atoi32tests[i]; test := &atoi32tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{test.in, test.err}
} }
@ -190,8 +190,8 @@ func init() {
func TestAtoui64(t *testing.T) { func TestAtoui64(t *testing.T) {
for i := range atoui64tests { for i := range atoui64tests {
test := &atoui64tests[i]; test := &atoui64tests[i]
out, err := Atoui64(test.in); out, err := Atoui64(test.in)
if test.out != out || !reflect.DeepEqual(test.err, err) { if test.out != out || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoui64(%q) = %v, %v want %v, %v\n", t.Errorf("Atoui64(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -201,8 +201,8 @@ func TestAtoui64(t *testing.T) {
func TestBtoui64(t *testing.T) { func TestBtoui64(t *testing.T) {
for i := range btoui64tests { for i := range btoui64tests {
test := &btoui64tests[i]; test := &btoui64tests[i]
out, err := Btoui64(test.in, 0); out, err := Btoui64(test.in, 0)
if test.out != out || !reflect.DeepEqual(test.err, err) { if test.out != out || !reflect.DeepEqual(test.err, err) {
t.Errorf("Btoui64(%q) = %v, %v want %v, %v\n", t.Errorf("Btoui64(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -212,8 +212,8 @@ func TestBtoui64(t *testing.T) {
func TestAtoi64(t *testing.T) { func TestAtoi64(t *testing.T) {
for i := range atoi64tests { for i := range atoi64tests {
test := &atoi64tests[i]; test := &atoi64tests[i]
out, err := Atoi64(test.in); out, err := Atoi64(test.in)
if test.out != out || !reflect.DeepEqual(test.err, err) { if test.out != out || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoi64(%q) = %v, %v want %v, %v\n", t.Errorf("Atoi64(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -223,8 +223,8 @@ func TestAtoi64(t *testing.T) {
func TestBtoi64(t *testing.T) { func TestBtoi64(t *testing.T) {
for i := range btoi64tests { for i := range btoi64tests {
test := &btoi64tests[i]; test := &btoi64tests[i]
out, err := Btoi64(test.in, 0); out, err := Btoi64(test.in, 0)
if test.out != out || !reflect.DeepEqual(test.err, err) { if test.out != out || !reflect.DeepEqual(test.err, err) {
t.Errorf("Btoi64(%q) = %v, %v want %v, %v\n", t.Errorf("Btoi64(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -236,8 +236,8 @@ func TestAtoui(t *testing.T) {
switch IntSize { switch IntSize {
case 32: case 32:
for i := range atoui32tests { for i := range atoui32tests {
test := &atoui32tests[i]; test := &atoui32tests[i]
out, err := Atoui(test.in); out, err := Atoui(test.in)
if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) { if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoui(%q) = %v, %v want %v, %v\n", t.Errorf("Atoui(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -245,8 +245,8 @@ func TestAtoui(t *testing.T) {
} }
case 64: case 64:
for i := range atoui64tests { for i := range atoui64tests {
test := &atoui64tests[i]; test := &atoui64tests[i]
out, err := Atoui(test.in); out, err := Atoui(test.in)
if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) { if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoui(%q) = %v, %v want %v, %v\n", t.Errorf("Atoui(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -259,8 +259,8 @@ func TestAtoi(t *testing.T) {
switch IntSize { switch IntSize {
case 32: case 32:
for i := range atoi32tests { for i := range atoi32tests {
test := &atoi32tests[i]; test := &atoi32tests[i]
out, err := Atoi(test.in); out, err := Atoi(test.in)
if test.out != int32(out) || !reflect.DeepEqual(test.err, err) { if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoi(%q) = %v, %v want %v, %v\n", t.Errorf("Atoi(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)
@ -268,8 +268,8 @@ func TestAtoi(t *testing.T) {
} }
case 64: case 64:
for i := range atoi64tests { for i := range atoi64tests {
test := &atoi64tests[i]; test := &atoi64tests[i]
out, err := Atoi(test.in); out, err := Atoi(test.in)
if test.out != int64(out) || !reflect.DeepEqual(test.err, err) { if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoi(%q) = %v, %v want %v, %v\n", t.Errorf("Atoi(%q) = %v, %v want %v, %v\n",
test.in, out, err, test.out, test.err) test.in, out, err, test.out, test.err)

View File

@ -14,13 +14,13 @@ package strconv
type decimal struct { type decimal struct {
// TODO(rsc): Can make d[] a bit smaller and add // TODO(rsc): Can make d[] a bit smaller and add
// truncated bool; // truncated bool;
d [2000]byte; // digits d [2000]byte // digits
nd int; // number of digits used nd int // number of digits used
dp int; // decimal point dp int // decimal point
} }
func (a *decimal) String() string { func (a *decimal) String() string {
n := 10 + a.nd; n := 10 + a.nd
if a.dp > 0 { if a.dp > 0 {
n += a.dp n += a.dp
} }
@ -28,48 +28,48 @@ func (a *decimal) String() string {
n += -a.dp n += -a.dp
} }
buf := make([]byte, n); buf := make([]byte, n)
w := 0; w := 0
switch { switch {
case a.nd == 0: case a.nd == 0:
return "0" return "0"
case a.dp <= 0: case a.dp <= 0:
// zeros fill space between decimal point and digits // zeros fill space between decimal point and digits
buf[w] = '0'; buf[w] = '0'
w++; w++
buf[w] = '.'; buf[w] = '.'
w++; w++
w += digitZero(buf[w : w+-a.dp]); w += digitZero(buf[w : w+-a.dp])
w += copy(buf[w:w+a.nd], a.d[0:a.nd]); w += copy(buf[w:w+a.nd], a.d[0:a.nd])
case a.dp < a.nd: case a.dp < a.nd:
// decimal point in middle of digits // decimal point in middle of digits
w += copy(buf[w:w+a.dp], a.d[0:a.dp]); w += copy(buf[w:w+a.dp], a.d[0:a.dp])
buf[w] = '.'; buf[w] = '.'
w++; w++
w += copy(buf[w:w+a.nd-a.dp], a.d[a.dp:a.nd]); w += copy(buf[w:w+a.nd-a.dp], a.d[a.dp:a.nd])
default: default:
// zeros fill space between digits and decimal point // zeros fill space between digits and decimal point
w += copy(buf[w:w+a.nd], a.d[0:a.nd]); w += copy(buf[w:w+a.nd], a.d[0:a.nd])
w += digitZero(buf[w : w+a.dp-a.nd]); w += digitZero(buf[w : w+a.dp-a.nd])
} }
return string(buf[0:w]); return string(buf[0:w])
} }
func copy(dst []byte, src []byte) int { func copy(dst []byte, src []byte) int {
for i := 0; i < len(dst); i++ { for i := 0; i < len(dst); i++ {
dst[i] = src[i] dst[i] = src[i]
} }
return len(dst); return len(dst)
} }
func digitZero(dst []byte) int { func digitZero(dst []byte) int {
for i := 0; i < len(dst); i++ { for i := 0; i < len(dst); i++ {
dst[i] = '0' dst[i] = '0'
} }
return len(dst); return len(dst)
} }
// trim trailing zeros from number. // trim trailing zeros from number.
@ -86,32 +86,32 @@ func trim(a *decimal) {
// Assign v to a. // Assign v to a.
func (a *decimal) Assign(v uint64) { func (a *decimal) Assign(v uint64) {
var buf [50]byte; var buf [50]byte
// Write reversed decimal in buf. // Write reversed decimal in buf.
n := 0; n := 0
for v > 0 { for v > 0 {
v1 := v / 10; v1 := v / 10
v -= 10 * v1; v -= 10 * v1
buf[n] = byte(v + '0'); buf[n] = byte(v + '0')
n++; n++
v = v1; v = v1
} }
// Reverse again to produce forward decimal in a.d. // Reverse again to produce forward decimal in a.d.
a.nd = 0; a.nd = 0
for n--; n >= 0; n-- { for n--; n >= 0; n-- {
a.d[a.nd] = buf[n]; a.d[a.nd] = buf[n]
a.nd++; a.nd++
} }
a.dp = a.nd; a.dp = a.nd
trim(a); trim(a)
} }
func newDecimal(i uint64) *decimal { func newDecimal(i uint64) *decimal {
a := new(decimal); a := new(decimal)
a.Assign(i); a.Assign(i)
return a; return a
} }
// Maximum shift that we can do in one pass without overflow. // Maximum shift that we can do in one pass without overflow.
@ -120,50 +120,50 @@ const maxShift = 27
// Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow. // Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow.
func rightShift(a *decimal, k uint) { func rightShift(a *decimal, k uint) {
r := 0; // read pointer r := 0 // read pointer
w := 0; // write pointer w := 0 // write pointer
// Pick up enough leading digits to cover first shift. // Pick up enough leading digits to cover first shift.
n := 0; n := 0
for ; n>>k == 0; r++ { for ; n>>k == 0; r++ {
if r >= a.nd { if r >= a.nd {
if n == 0 { if n == 0 {
// a == 0; shouldn't get here, but handle anyway. // a == 0; shouldn't get here, but handle anyway.
a.nd = 0; a.nd = 0
return; return
} }
for n>>k == 0 { for n>>k == 0 {
n = n * 10; n = n * 10
r++; r++
} }
break; break
} }
c := int(a.d[r]); c := int(a.d[r])
n = n*10 + c - '0'; n = n*10 + c - '0'
} }
a.dp -= r - 1; a.dp -= r - 1
// Pick up a digit, put down a digit. // Pick up a digit, put down a digit.
for ; r < a.nd; r++ { for ; r < a.nd; r++ {
c := int(a.d[r]); c := int(a.d[r])
dig := n >> k; dig := n >> k
n -= dig << k; n -= dig << k
a.d[w] = byte(dig + '0'); a.d[w] = byte(dig + '0')
w++; w++
n = n*10 + c - '0'; n = n*10 + c - '0'
} }
// Put down extra digits. // Put down extra digits.
for n > 0 { for n > 0 {
dig := n >> k; dig := n >> k
n -= dig << k; n -= dig << k
a.d[w] = byte(dig + '0'); a.d[w] = byte(dig + '0')
w++; w++
n = n * 10; n = n * 10
} }
a.nd = w; a.nd = w
trim(a); trim(a)
} }
// Cheat sheet for left shift: table indexed by shift count giving // Cheat sheet for left shift: table indexed by shift count giving
@ -177,8 +177,8 @@ func rightShift(a *decimal, k uint) {
// Credit for this trick goes to Ken. // Credit for this trick goes to Ken.
type leftCheat struct { type leftCheat struct {
delta int; // number of new digits delta int // number of new digits
cutoff string; // minus one digit if original < a. cutoff string // minus one digit if original < a.
} }
var leftcheats = []leftCheat{ var leftcheats = []leftCheat{
@ -195,33 +195,33 @@ var leftcheats = []leftCheat{
}' }'
*/ */
leftCheat{0, ""}, leftCheat{0, ""},
leftCheat{1, "5"}, // * 2 leftCheat{1, "5"}, // * 2
leftCheat{1, "25"}, // * 4 leftCheat{1, "25"}, // * 4
leftCheat{1, "125"}, // * 8 leftCheat{1, "125"}, // * 8
leftCheat{2, "625"}, // * 16 leftCheat{2, "625"}, // * 16
leftCheat{2, "3125"}, // * 32 leftCheat{2, "3125"}, // * 32
leftCheat{2, "15625"}, // * 64 leftCheat{2, "15625"}, // * 64
leftCheat{3, "78125"}, // * 128 leftCheat{3, "78125"}, // * 128
leftCheat{3, "390625"}, // * 256 leftCheat{3, "390625"}, // * 256
leftCheat{3, "1953125"}, // * 512 leftCheat{3, "1953125"}, // * 512
leftCheat{4, "9765625"}, // * 1024 leftCheat{4, "9765625"}, // * 1024
leftCheat{4, "48828125"}, // * 2048 leftCheat{4, "48828125"}, // * 2048
leftCheat{4, "244140625"}, // * 4096 leftCheat{4, "244140625"}, // * 4096
leftCheat{4, "1220703125"}, // * 8192 leftCheat{4, "1220703125"}, // * 8192
leftCheat{5, "6103515625"}, // * 16384 leftCheat{5, "6103515625"}, // * 16384
leftCheat{5, "30517578125"}, // * 32768 leftCheat{5, "30517578125"}, // * 32768
leftCheat{5, "152587890625"}, // * 65536 leftCheat{5, "152587890625"}, // * 65536
leftCheat{6, "762939453125"}, // * 131072 leftCheat{6, "762939453125"}, // * 131072
leftCheat{6, "3814697265625"}, // * 262144 leftCheat{6, "3814697265625"}, // * 262144
leftCheat{6, "19073486328125"}, // * 524288 leftCheat{6, "19073486328125"}, // * 524288
leftCheat{7, "95367431640625"}, // * 1048576 leftCheat{7, "95367431640625"}, // * 1048576
leftCheat{7, "476837158203125"}, // * 2097152 leftCheat{7, "476837158203125"}, // * 2097152
leftCheat{7, "2384185791015625"}, // * 4194304 leftCheat{7, "2384185791015625"}, // * 4194304
leftCheat{7, "11920928955078125"}, // * 8388608 leftCheat{7, "11920928955078125"}, // * 8388608
leftCheat{8, "59604644775390625"}, // * 16777216 leftCheat{8, "59604644775390625"}, // * 16777216
leftCheat{8, "298023223876953125"}, // * 33554432 leftCheat{8, "298023223876953125"}, // * 33554432
leftCheat{8, "1490116119384765625"}, // * 67108864 leftCheat{8, "1490116119384765625"}, // * 67108864
leftCheat{9, "7450580596923828125"}, // * 134217728 leftCheat{9, "7450580596923828125"}, // * 134217728
} }
// Is the leading prefix of b lexicographically less than s? // Is the leading prefix of b lexicographically less than s?
@ -234,42 +234,42 @@ func prefixIsLessThan(b []byte, s string) bool {
return b[i] < s[i] return b[i] < s[i]
} }
} }
return false; return false
} }
// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow. // Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow.
func leftShift(a *decimal, k uint) { func leftShift(a *decimal, k uint) {
delta := leftcheats[k].delta; delta := leftcheats[k].delta
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
delta-- delta--
} }
r := a.nd; // read index r := a.nd // read index
w := a.nd + delta; // write index w := a.nd + delta // write index
n := 0; n := 0
// Pick up a digit, put down a digit. // Pick up a digit, put down a digit.
for r--; r >= 0; r-- { for r--; r >= 0; r-- {
n += (int(a.d[r]) - '0') << k; n += (int(a.d[r]) - '0') << k
quo := n / 10; quo := n / 10
rem := n - 10*quo; rem := n - 10*quo
w--; w--
a.d[w] = byte(rem + '0'); a.d[w] = byte(rem + '0')
n = quo; n = quo
} }
// Put down extra digits. // Put down extra digits.
for n > 0 { for n > 0 {
quo := n / 10; quo := n / 10
rem := n - 10*quo; rem := n - 10*quo
w--; w--
a.d[w] = byte(rem + '0'); a.d[w] = byte(rem + '0')
n = quo; n = quo
} }
a.nd += delta; a.nd += delta
a.dp += delta; a.dp += delta
trim(a); trim(a)
} }
// Binary shift left (k > 0) or right (k < 0). // Binary shift left (k > 0) or right (k < 0).
@ -280,18 +280,18 @@ func (a *decimal) Shift(k int) *decimal {
// nothing to do: a == 0 // nothing to do: a == 0
case k > 0: case k > 0:
for k > maxShift { for k > maxShift {
leftShift(a, maxShift); leftShift(a, maxShift)
k -= maxShift; k -= maxShift
} }
leftShift(a, uint(k)); leftShift(a, uint(k))
case k < 0: case k < 0:
for k < -maxShift { for k < -maxShift {
rightShift(a, maxShift); rightShift(a, maxShift)
k += maxShift; k += maxShift
} }
rightShift(a, uint(-k)); rightShift(a, uint(-k))
} }
return a; return a
} }
// If we chop a at nd digits, should we round up? // If we chop a at nd digits, should we round up?
@ -299,11 +299,11 @@ func shouldRoundUp(a *decimal, nd int) bool {
if nd <= 0 || nd >= a.nd { if nd <= 0 || nd >= a.nd {
return false return false
} }
if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
return (a.d[nd-1]-'0')%2 != 0 return (a.d[nd-1]-'0')%2 != 0
} }
// not halfway - digit tells all // not halfway - digit tells all
return a.d[nd] >= '5'; return a.d[nd] >= '5'
} }
// Round a to nd digits (or fewer). // Round a to nd digits (or fewer).
@ -315,7 +315,7 @@ func (a *decimal) Round(nd int) *decimal {
if shouldRoundUp(a, nd) { if shouldRoundUp(a, nd) {
return a.RoundUp(nd) return a.RoundUp(nd)
} }
return a.RoundDown(nd); return a.RoundDown(nd)
} }
// Round a down to nd digits (or fewer). // Round a down to nd digits (or fewer).
@ -324,9 +324,9 @@ func (a *decimal) RoundDown(nd int) *decimal {
if nd <= 0 || nd >= a.nd { if nd <= 0 || nd >= a.nd {
return a return a
} }
a.nd = nd; a.nd = nd
trim(a); trim(a)
return a; return a
} }
// Round a up to nd digits (or fewer). // Round a up to nd digits (or fewer).
@ -338,20 +338,20 @@ func (a *decimal) RoundUp(nd int) *decimal {
// round up // round up
for i := nd - 1; i >= 0; i-- { for i := nd - 1; i >= 0; i-- {
c := a.d[i]; c := a.d[i]
if c < '9' { // can stop after this digit if c < '9' { // can stop after this digit
a.d[i]++; a.d[i]++
a.nd = i + 1; a.nd = i + 1
return a; return a
} }
} }
// Number is all 9s. // Number is all 9s.
// Change to single 1 with adjusted decimal point. // Change to single 1 with adjusted decimal point.
a.d[0] = '1'; a.d[0] = '1'
a.nd = 1; a.nd = 1
a.dp++; a.dp++
return a; return a
} }
// Extract integer part, rounded appropriately. // Extract integer part, rounded appropriately.
@ -360,8 +360,8 @@ func (a *decimal) RoundedInteger() uint64 {
if a.dp > 20 { if a.dp > 20 {
return 0xFFFFFFFFFFFFFFFF return 0xFFFFFFFFFFFFFFFF
} }
var i int; var i int
n := uint64(0); n := uint64(0)
for i = 0; i < a.dp && i < a.nd; i++ { for i = 0; i < a.dp && i < a.nd; i++ {
n = n*10 + uint64(a.d[i]-'0') n = n*10 + uint64(a.d[i]-'0')
} }
@ -371,5 +371,5 @@ func (a *decimal) RoundedInteger() uint64 {
if shouldRoundUp(a, a.dp) { if shouldRoundUp(a, a.dp) {
n++ n++
} }
return n; return n
} }

View File

@ -5,14 +5,14 @@
package strconv_test package strconv_test
import ( import (
. "strconv"; . "strconv"
"testing"; "testing"
) )
type shiftTest struct { type shiftTest struct {
i uint64; i uint64
shift int; shift int
out string; out string
} }
var shifttests = []shiftTest{ var shifttests = []shiftTest{
@ -31,8 +31,8 @@ var shifttests = []shiftTest{
func TestDecimalShift(t *testing.T) { func TestDecimalShift(t *testing.T) {
for i := 0; i < len(shifttests); i++ { for i := 0; i < len(shifttests); i++ {
test := &shifttests[i]; test := &shifttests[i]
s := NewDecimal(test.i).Shift(test.shift).String(); s := NewDecimal(test.i).Shift(test.shift).String()
if s != test.out { if s != test.out {
t.Errorf("Decimal %v << %v = %v, want %v\n", t.Errorf("Decimal %v << %v = %v, want %v\n",
test.i, test.shift, s, test.out) test.i, test.shift, s, test.out)
@ -41,10 +41,10 @@ func TestDecimalShift(t *testing.T) {
} }
type roundTest struct { type roundTest struct {
i uint64; i uint64
nd int; nd int
down, round, up string; down, round, up string
int uint64; int uint64
} }
var roundtests = []roundTest{ var roundtests = []roundTest{
@ -67,18 +67,18 @@ var roundtests = []roundTest{
func TestDecimalRound(t *testing.T) { func TestDecimalRound(t *testing.T) {
for i := 0; i < len(roundtests); i++ { for i := 0; i < len(roundtests); i++ {
test := &roundtests[i]; test := &roundtests[i]
s := NewDecimal(test.i).RoundDown(test.nd).String(); s := NewDecimal(test.i).RoundDown(test.nd).String()
if s != test.down { if s != test.down {
t.Errorf("Decimal %v RoundDown %d = %v, want %v\n", t.Errorf("Decimal %v RoundDown %d = %v, want %v\n",
test.i, test.nd, s, test.down) test.i, test.nd, s, test.down)
} }
s = NewDecimal(test.i).Round(test.nd).String(); s = NewDecimal(test.i).Round(test.nd).String()
if s != test.round { if s != test.round {
t.Errorf("Decimal %v Round %d = %v, want %v\n", t.Errorf("Decimal %v Round %d = %v, want %v\n",
test.i, test.nd, s, test.down) test.i, test.nd, s, test.down)
} }
s = NewDecimal(test.i).RoundUp(test.nd).String(); s = NewDecimal(test.i).RoundUp(test.nd).String()
if s != test.up { if s != test.up {
t.Errorf("Decimal %v RoundUp %d = %v, want %v\n", t.Errorf("Decimal %v RoundUp %d = %v, want %v\n",
test.i, test.nd, s, test.up) test.i, test.nd, s, test.up)
@ -87,9 +87,9 @@ func TestDecimalRound(t *testing.T) {
} }
type roundIntTest struct { type roundIntTest struct {
i uint64; i uint64
shift int; shift int
int uint64; int uint64
} }
var roundinttests = []roundIntTest{ var roundinttests = []roundIntTest{
@ -107,8 +107,8 @@ var roundinttests = []roundIntTest{
func TestDecimalRoundedInteger(t *testing.T) { func TestDecimalRoundedInteger(t *testing.T) {
for i := 0; i < len(roundinttests); i++ { for i := 0; i < len(roundinttests); i++ {
test := roundinttests[i]; test := roundinttests[i]
int := NewDecimal(test.i).Shift(test.shift).RoundedInteger(); int := NewDecimal(test.i).Shift(test.shift).RoundedInteger()
if int != test.int { if int != test.int {
t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v\n", t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v\n",
test.i, test.shift, int, test.int) test.i, test.shift, int, test.int)

View File

@ -5,12 +5,12 @@
package strconv_test package strconv_test
import ( import (
"bufio"; "bufio"
"fmt"; "fmt"
"os"; "os"
"strconv"; "strconv"
"strings"; "strings"
"testing"; "testing"
) )
func pow2(i int) float64 { func pow2(i int) float64 {
@ -22,124 +22,124 @@ func pow2(i int) float64 {
case i == 1: case i == 1:
return 2 return 2
} }
return pow2(i/2) * pow2(i-i/2); return pow2(i/2) * pow2(i-i/2)
} }
// Wrapper around strconv.Atof64. Handles dddddp+ddd (binary exponent) // Wrapper around strconv.Atof64. Handles dddddp+ddd (binary exponent)
// itself, passes the rest on to strconv.Atof64. // itself, passes the rest on to strconv.Atof64.
func myatof64(s string) (f float64, ok bool) { func myatof64(s string) (f float64, ok bool) {
a := strings.Split(s, "p", 2); a := strings.Split(s, "p", 2)
if len(a) == 2 { if len(a) == 2 {
n, err := strconv.Atoi64(a[0]); n, err := strconv.Atoi64(a[0])
if err != nil { if err != nil {
return 0, false return 0, false
} }
e, err1 := strconv.Atoi(a[1]); e, err1 := strconv.Atoi(a[1])
if err1 != nil { if err1 != nil {
println("bad e", a[1]); println("bad e", a[1])
return 0, false; return 0, false
} }
v := float64(n); v := float64(n)
// We expect that v*pow2(e) fits in a float64, // We expect that v*pow2(e) fits in a float64,
// but pow2(e) by itself may not. Be careful. // but pow2(e) by itself may not. Be careful.
if e <= -1000 { if e <= -1000 {
v *= pow2(-1000); v *= pow2(-1000)
e += 1000; e += 1000
for e < 0 { for e < 0 {
v /= 2; v /= 2
e++; e++
} }
return v, true; return v, true
} }
if e >= 1000 { if e >= 1000 {
v *= pow2(1000); v *= pow2(1000)
e -= 1000; e -= 1000
for e > 0 { for e > 0 {
v *= 2; v *= 2
e--; e--
} }
return v, true; return v, true
} }
return v * pow2(e), true; return v * pow2(e), true
} }
f1, err := strconv.Atof64(s); f1, err := strconv.Atof64(s)
if err != nil { if err != nil {
return 0, false return 0, false
} }
return f1, true; return f1, true
} }
// Wrapper around strconv.Atof32. Handles dddddp+ddd (binary exponent) // Wrapper around strconv.Atof32. Handles dddddp+ddd (binary exponent)
// itself, passes the rest on to strconv.Atof32. // itself, passes the rest on to strconv.Atof32.
func myatof32(s string) (f float32, ok bool) { func myatof32(s string) (f float32, ok bool) {
a := strings.Split(s, "p", 2); a := strings.Split(s, "p", 2)
if len(a) == 2 { if len(a) == 2 {
n, err := strconv.Atoi(a[0]); n, err := strconv.Atoi(a[0])
if err != nil { if err != nil {
println("bad n", a[0]); println("bad n", a[0])
return 0, false; return 0, false
} }
e, err1 := strconv.Atoi(a[1]); e, err1 := strconv.Atoi(a[1])
if err1 != nil { if err1 != nil {
println("bad p", a[1]); println("bad p", a[1])
return 0, false; return 0, false
} }
return float32(float64(n) * pow2(e)), true; return float32(float64(n) * pow2(e)), true
} }
f1, err1 := strconv.Atof32(s); f1, err1 := strconv.Atof32(s)
if err1 != nil { if err1 != nil {
return 0, false return 0, false
} }
return f1, true; return f1, true
} }
func TestFp(t *testing.T) { func TestFp(t *testing.T) {
f, err := os.Open("testfp.txt", os.O_RDONLY, 0); f, err := os.Open("testfp.txt", os.O_RDONLY, 0)
if err != nil { if err != nil {
panicln("testfp: open testfp.txt:", err.String()) panicln("testfp: open testfp.txt:", err.String())
} }
defer f.Close(); defer f.Close()
b := bufio.NewReader(f); b := bufio.NewReader(f)
lineno := 0; lineno := 0
for { for {
line, err2 := b.ReadString('\n'); line, err2 := b.ReadString('\n')
if err2 == os.EOF { if err2 == os.EOF {
break break
} }
if err2 != nil { if err2 != nil {
panicln("testfp: read testfp.txt:", err2.String()) panicln("testfp: read testfp.txt:", err2.String())
} }
line = line[0 : len(line)-1]; line = line[0 : len(line)-1]
lineno++; lineno++
if len(line) == 0 || line[0] == '#' { if len(line) == 0 || line[0] == '#' {
continue continue
} }
a := strings.Split(line, " ", 0); a := strings.Split(line, " ", 0)
if len(a) != 4 { if len(a) != 4 {
t.Error("testfp.txt:", lineno, ": wrong field count\n"); t.Error("testfp.txt:", lineno, ": wrong field count\n")
continue; continue
} }
var s string; var s string
var v float64; var v float64
switch a[0] { switch a[0] {
case "float64": case "float64":
var ok bool; var ok bool
v, ok = myatof64(a[2]); v, ok = myatof64(a[2])
if !ok { if !ok {
t.Error("testfp.txt:", lineno, ": cannot atof64 ", a[2]); t.Error("testfp.txt:", lineno, ": cannot atof64 ", a[2])
continue; continue
} }
s = fmt.Sprintf(a[1], v); s = fmt.Sprintf(a[1], v)
case "float32": case "float32":
v1, ok := myatof32(a[2]); v1, ok := myatof32(a[2])
if !ok { if !ok {
t.Error("testfp.txt:", lineno, ": cannot atof32 ", a[2]); t.Error("testfp.txt:", lineno, ": cannot atof32 ", a[2])
continue; continue
} }
s = fmt.Sprintf(a[1], v1); s = fmt.Sprintf(a[1], v1)
v = float64(v1); v = float64(v1)
} }
if s != a[3] { if s != a[3] {
t.Error("testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ", t.Error("testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",

View File

@ -14,9 +14,9 @@ import "math"
// TODO: move elsewhere? // TODO: move elsewhere?
type floatInfo struct { type floatInfo struct {
mantbits uint; mantbits uint
expbits uint; expbits uint
bias int; bias int
} }
var float32info = floatInfo{23, 8, -127} var float32info = floatInfo{23, 8, -127}
@ -26,11 +26,11 @@ func floatsize() int {
// Figure out whether float is float32 or float64. // Figure out whether float is float32 or float64.
// 1e-35 is representable in both, but 1e-70 // 1e-35 is representable in both, but 1e-70
// is too small for a float32. // is too small for a float32.
var f float = 1e-35; var f float = 1e-35
if f*f == 0 { if f*f == 0 {
return 32 return 32
} }
return 64; return 64
} }
// Floatsize gives the size of the float type, either 32 or 64. // Floatsize gives the size of the float type, either 32 or 64.
@ -69,13 +69,13 @@ func Ftoa(f float, fmt byte, prec int) string {
if FloatSize == 32 { if FloatSize == 32 {
return Ftoa32(float32(f), fmt, prec) return Ftoa32(float32(f), fmt, prec)
} }
return Ftoa64(float64(f), fmt, prec); return Ftoa64(float64(f), fmt, prec)
} }
func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string { func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
neg := bits>>flt.expbits>>flt.mantbits != 0; neg := bits>>flt.expbits>>flt.mantbits != 0
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1); exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
mant := bits & (uint64(1)<<flt.mantbits - 1); mant := bits & (uint64(1)<<flt.mantbits - 1)
switch exp { switch exp {
case 1<<flt.expbits - 1: case 1<<flt.expbits - 1:
@ -86,7 +86,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
if neg { if neg {
return "-Inf" return "-Inf"
} }
return "+Inf"; return "+Inf"
case 0: case 0:
// denormalized // denormalized
@ -96,7 +96,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
// add implicit top bit // add implicit top bit
mant |= uint64(1) << flt.mantbits mant |= uint64(1) << flt.mantbits
} }
exp += flt.bias; exp += flt.bias
// Pick off easy binary format. // Pick off easy binary format.
if fmt == 'b' { if fmt == 'b' {
@ -107,14 +107,14 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
// The shift is exp - flt.mantbits because mant is a 1-bit integer // The shift is exp - flt.mantbits because mant is a 1-bit integer
// followed by a flt.mantbits fraction, and we are treating it as // followed by a flt.mantbits fraction, and we are treating it as
// a 1+flt.mantbits-bit integer. // a 1+flt.mantbits-bit integer.
d := newDecimal(mant).Shift(exp - int(flt.mantbits)); d := newDecimal(mant).Shift(exp - int(flt.mantbits))
// Round appropriately. // Round appropriately.
// Negative precision means "only as much as needed to be exact." // Negative precision means "only as much as needed to be exact."
shortest := false; shortest := false
if prec < 0 { if prec < 0 {
shortest = true; shortest = true
roundShortest(d, mant, exp, flt); roundShortest(d, mant, exp, flt)
switch fmt { switch fmt {
case 'e', 'E': case 'e', 'E':
prec = d.nd - 1 prec = d.nd - 1
@ -133,7 +133,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
if prec == 0 { if prec == 0 {
prec = 1 prec = 1
} }
d.Round(prec); d.Round(prec)
} }
} }
@ -150,18 +150,18 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
// %e is used if the exponent from the conversion // %e is used if the exponent from the conversion
// is less than -4 or greater than or equal to the precision. // is less than -4 or greater than or equal to the precision.
// if precision was the shortest possible, use precision 6 for this decision. // if precision was the shortest possible, use precision 6 for this decision.
eprec := prec; eprec := prec
if shortest { if shortest {
eprec = 6 eprec = 6
} }
exp := d.dp - 1; exp := d.dp - 1
if exp < -4 || exp >= eprec { if exp < -4 || exp >= eprec {
return fmtE(neg, d, prec-1, fmt+'e'-'g') return fmtE(neg, d, prec-1, fmt+'e'-'g')
} }
return fmtF(neg, d, max(prec-d.dp, 0)); return fmtF(neg, d, max(prec-d.dp, 0))
} }
return "%" + string(fmt); return "%" + string(fmt)
} }
// Round d (= mant * 2^exp) to the shortest number of digits // Round d (= mant * 2^exp) to the shortest number of digits
@ -170,8 +170,8 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// If mantissa is zero, the number is zero; stop now. // If mantissa is zero, the number is zero; stop now.
if mant == 0 { if mant == 0 {
d.nd = 0; d.nd = 0
return; return
} }
// TODO(rsc): Unless exp == minexp, if the number of digits in d // TODO(rsc): Unless exp == minexp, if the number of digits in d
@ -186,7 +186,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// d = mant << (exp - mantbits) // d = mant << (exp - mantbits)
// Next highest floating point number is mant+1 << exp-mantbits. // Next highest floating point number is mant+1 << exp-mantbits.
// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1. // Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.
upper := newDecimal(mant*2 + 1).Shift(exp - int(flt.mantbits) - 1); upper := newDecimal(mant*2 + 1).Shift(exp - int(flt.mantbits) - 1)
// d = mant << (exp - mantbits) // d = mant << (exp - mantbits)
// Next lowest floating point number is mant-1 << exp-mantbits, // Next lowest floating point number is mant-1 << exp-mantbits,
@ -194,33 +194,33 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// in which case the next lowest is mant*2-1 << exp-mantbits-1. // in which case the next lowest is mant*2-1 << exp-mantbits-1.
// Either way, call it mantlo << explo-mantbits. // Either way, call it mantlo << explo-mantbits.
// Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1. // Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1.
minexp := flt.bias + 1; // minimum possible exponent minexp := flt.bias + 1 // minimum possible exponent
var mantlo uint64; var mantlo uint64
var explo int; var explo int
if mant > 1<<flt.mantbits || exp == minexp { if mant > 1<<flt.mantbits || exp == minexp {
mantlo = mant - 1; mantlo = mant - 1
explo = exp; explo = exp
} else { } else {
mantlo = mant*2 - 1; mantlo = mant*2 - 1
explo = exp - 1; explo = exp - 1
} }
lower := newDecimal(mantlo*2 + 1).Shift(explo - int(flt.mantbits) - 1); lower := newDecimal(mantlo*2 + 1).Shift(explo - int(flt.mantbits) - 1)
// The upper and lower bounds are possible outputs only if // The upper and lower bounds are possible outputs only if
// the original mantissa is even, so that IEEE round-to-even // the original mantissa is even, so that IEEE round-to-even
// would round to the original mantissa and not the neighbors. // would round to the original mantissa and not the neighbors.
inclusive := mant%2 == 0; inclusive := mant%2 == 0
// Now we can figure out the minimum number of digits required. // Now we can figure out the minimum number of digits required.
// Walk along until d has distinguished itself from upper and lower. // Walk along until d has distinguished itself from upper and lower.
for i := 0; i < d.nd; i++ { for i := 0; i < d.nd; i++ {
var l, m, u byte; // lower, middle, upper digits var l, m, u byte // lower, middle, upper digits
if i < lower.nd { if i < lower.nd {
l = lower.d[i] l = lower.d[i]
} else { } else {
l = '0' l = '0'
} }
m = d.d[i]; m = d.d[i]
if i < upper.nd { if i < upper.nd {
u = upper.d[i] u = upper.d[i]
} else { } else {
@ -229,37 +229,37 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// Okay to round down (truncate) if lower has a different digit // Okay to round down (truncate) if lower has a different digit
// or if lower is inclusive and is exactly the result of rounding down. // or if lower is inclusive and is exactly the result of rounding down.
okdown := l != m || (inclusive && l == m && i+1 == lower.nd); okdown := l != m || (inclusive && l == m && i+1 == lower.nd)
// Okay to round up if upper has a different digit and // Okay to round up if upper has a different digit and
// either upper is inclusive or upper is bigger than the result of rounding up. // either upper is inclusive or upper is bigger than the result of rounding up.
okup := m != u && (inclusive || i+1 < upper.nd); okup := m != u && (inclusive || i+1 < upper.nd)
// If it's okay to do either, then round to the nearest one. // If it's okay to do either, then round to the nearest one.
// If it's okay to do only one, do it. // If it's okay to do only one, do it.
switch { switch {
case okdown && okup: case okdown && okup:
d.Round(i + 1); d.Round(i + 1)
return; return
case okdown: case okdown:
d.RoundDown(i + 1); d.RoundDown(i + 1)
return; return
case okup: case okup:
d.RoundUp(i + 1); d.RoundUp(i + 1)
return; return
} }
} }
} }
// %e: -d.ddddde±dd // %e: -d.ddddde±dd
func fmtE(neg bool, d *decimal, prec int, fmt byte) string { func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
buf := make([]byte, 3+max(prec, 0)+30); // "-0." + prec digits + exp buf := make([]byte, 3+max(prec, 0)+30) // "-0." + prec digits + exp
w := 0; // write index w := 0 // write index
// sign // sign
if neg { if neg {
buf[w] = '-'; buf[w] = '-'
w++; w++
} }
// first digit // first digit
@ -268,141 +268,141 @@ func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
} else { } else {
buf[w] = d.d[0] buf[w] = d.d[0]
} }
w++; w++
// .moredigits // .moredigits
if prec > 0 { if prec > 0 {
buf[w] = '.'; buf[w] = '.'
w++; w++
for i := 0; i < prec; i++ { for i := 0; i < prec; i++ {
if 1+i < d.nd { if 1+i < d.nd {
buf[w] = d.d[1+i] buf[w] = d.d[1+i]
} else { } else {
buf[w] = '0' buf[w] = '0'
} }
w++; w++
} }
} }
// e± // e±
buf[w] = fmt; buf[w] = fmt
w++; w++
exp := d.dp - 1; exp := d.dp - 1
if d.nd == 0 { // special case: 0 has exponent 0 if d.nd == 0 { // special case: 0 has exponent 0
exp = 0 exp = 0
} }
if exp < 0 { if exp < 0 {
buf[w] = '-'; buf[w] = '-'
exp = -exp; exp = -exp
} else { } else {
buf[w] = '+' buf[w] = '+'
} }
w++; w++
// dddd // dddd
// count digits // count digits
n := 0; n := 0
for e := exp; e > 0; e /= 10 { for e := exp; e > 0; e /= 10 {
n++ n++
} }
// leading zeros // leading zeros
for i := n; i < 2; i++ { for i := n; i < 2; i++ {
buf[w] = '0'; buf[w] = '0'
w++; w++
} }
// digits // digits
w += n; w += n
n = 0; n = 0
for e := exp; e > 0; e /= 10 { for e := exp; e > 0; e /= 10 {
n++; n++
buf[w-n] = byte(e%10 + '0'); buf[w-n] = byte(e%10 + '0')
} }
return string(buf[0:w]); return string(buf[0:w])
} }
// %f: -ddddddd.ddddd // %f: -ddddddd.ddddd
func fmtF(neg bool, d *decimal, prec int) string { func fmtF(neg bool, d *decimal, prec int) string {
buf := make([]byte, 1+max(d.dp, 1)+1+max(prec, 0)); buf := make([]byte, 1+max(d.dp, 1)+1+max(prec, 0))
w := 0; w := 0
// sign // sign
if neg { if neg {
buf[w] = '-'; buf[w] = '-'
w++; w++
} }
// integer, padded with zeros as needed. // integer, padded with zeros as needed.
if d.dp > 0 { if d.dp > 0 {
var i int; var i int
for i = 0; i < d.dp && i < d.nd; i++ { for i = 0; i < d.dp && i < d.nd; i++ {
buf[w] = d.d[i]; buf[w] = d.d[i]
w++; w++
} }
for ; i < d.dp; i++ { for ; i < d.dp; i++ {
buf[w] = '0'; buf[w] = '0'
w++; w++
} }
} else { } else {
buf[w] = '0'; buf[w] = '0'
w++; w++
} }
// fraction // fraction
if prec > 0 { if prec > 0 {
buf[w] = '.'; buf[w] = '.'
w++; w++
for i := 0; i < prec; i++ { for i := 0; i < prec; i++ {
if d.dp+i < 0 || d.dp+i >= d.nd { if d.dp+i < 0 || d.dp+i >= d.nd {
buf[w] = '0' buf[w] = '0'
} else { } else {
buf[w] = d.d[d.dp+i] buf[w] = d.d[d.dp+i]
} }
w++; w++
} }
} }
return string(buf[0:w]); return string(buf[0:w])
} }
// %b: -ddddddddp+ddd // %b: -ddddddddp+ddd
func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string { func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string {
var buf [50]byte; var buf [50]byte
w := len(buf); w := len(buf)
exp -= int(flt.mantbits); exp -= int(flt.mantbits)
esign := byte('+'); esign := byte('+')
if exp < 0 { if exp < 0 {
esign = '-'; esign = '-'
exp = -exp; exp = -exp
} }
n := 0; n := 0
for exp > 0 || n < 1 { for exp > 0 || n < 1 {
n++; n++
w--; w--
buf[w] = byte(exp%10 + '0'); buf[w] = byte(exp%10 + '0')
exp /= 10; exp /= 10
} }
w--; w--
buf[w] = esign; buf[w] = esign
w--; w--
buf[w] = 'p'; buf[w] = 'p'
n = 0; n = 0
for mant > 0 || n < 1 { for mant > 0 || n < 1 {
n++; n++
w--; w--
buf[w] = byte(mant%10 + '0'); buf[w] = byte(mant%10 + '0')
mant /= 10; mant /= 10
} }
if neg { if neg {
w--; w--
buf[w] = '-'; buf[w] = '-'
} }
return string(buf[w:]); return string(buf[w:])
} }
func max(a, b int) int { func max(a, b int) int {
if a > b { if a > b {
return a return a
} }
return b; return b
} }

View File

@ -5,23 +5,23 @@
package strconv_test package strconv_test
import ( import (
"math"; "math"
. "strconv"; . "strconv"
"testing"; "testing"
) )
type ftoaTest struct { type ftoaTest struct {
f float64; f float64
fmt byte; fmt byte
prec int; prec int
s string; s string
} }
func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark
const ( const (
below1e23 = 99999999999999974834176; below1e23 = 99999999999999974834176
above1e23 = 100000000000000008388608; above1e23 = 100000000000000008388608
) )
var ftoatests = []ftoaTest{ var ftoatests = []ftoaTest{
@ -104,13 +104,13 @@ func TestFtoa(t *testing.T) {
panic("floatsize: ", FloatSize) panic("floatsize: ", FloatSize)
} }
for i := 0; i < len(ftoatests); i++ { for i := 0; i < len(ftoatests); i++ {
test := &ftoatests[i]; test := &ftoatests[i]
s := Ftoa64(test.f, test.fmt, test.prec); s := Ftoa64(test.f, test.fmt, test.prec)
if s != test.s { if s != test.s {
t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
} }
if float64(float32(test.f)) == test.f && test.fmt != 'b' { if float64(float32(test.f)) == test.f && test.fmt != 'b' {
s := Ftoa32(float32(test.f), test.fmt, test.prec); s := Ftoa32(float32(test.f), test.fmt, test.prec)
if s != test.s { if s != test.s {
t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
} }

View File

@ -6,10 +6,10 @@
package strconv package strconv
func NewDecimal(i uint64) *decimal { return newDecimal(i) } func NewDecimal(i uint64) *decimal { return newDecimal(i) }
func SetOptimize(b bool) bool { func SetOptimize(b bool) bool {
old := optimize; old := optimize
optimize = b; optimize = b
return old; return old
} }

View File

@ -11,16 +11,16 @@ func Uitob64(u uint64, base uint) string {
} }
// Assemble decimal in reverse order. // Assemble decimal in reverse order.
var buf [32]byte; var buf [32]byte
j := len(buf); j := len(buf)
b := uint64(base); b := uint64(base)
for u > 0 { for u > 0 {
j--; j--
buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]; buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]
u /= b; u /= b
} }
return string(buf[j:]); return string(buf[j:])
} }
// Itob64 returns the string representation of i in the given base. // Itob64 returns the string representation of i in the given base.
@ -32,23 +32,23 @@ func Itob64(i int64, base uint) string {
if i < 0 { if i < 0 {
return "-" + Uitob64(-uint64(i), base) return "-" + Uitob64(-uint64(i), base)
} }
return Uitob64(uint64(i), base); return Uitob64(uint64(i), base)
} }
// Itoa64 returns the decimal string representation of i. // Itoa64 returns the decimal string representation of i.
func Itoa64(i int64) string { return Itob64(i, 10) } func Itoa64(i int64) string { return Itob64(i, 10) }
// Uitoa64 returns the decimal string representation of i. // Uitoa64 returns the decimal string representation of i.
func Uitoa64(i uint64) string { return Uitob64(i, 10) } func Uitoa64(i uint64) string { return Uitob64(i, 10) }
// Uitob returns the string representation of i in the given base. // Uitob returns the string representation of i in the given base.
func Uitob(i uint, base uint) string { return Uitob64(uint64(i), base) } func Uitob(i uint, base uint) string { return Uitob64(uint64(i), base) }
// Itob returns the string representation of i in the given base. // Itob returns the string representation of i in the given base.
func Itob(i int, base uint) string { return Itob64(int64(i), base) } func Itob(i int, base uint) string { return Itob64(int64(i), base) }
// Itoa returns the decimal string representation of i. // Itoa returns the decimal string representation of i.
func Itoa(i int) string { return Itob64(int64(i), 10) } func Itoa(i int) string { return Itob64(int64(i), 10) }
// Uitoa returns the decimal string representation of i. // Uitoa returns the decimal string representation of i.
func Uitoa(i uint) string { return Uitob64(uint64(i), 10) } func Uitoa(i uint) string { return Uitob64(uint64(i), 10) }

View File

@ -5,14 +5,14 @@
package strconv_test package strconv_test
import ( import (
. "strconv"; . "strconv"
"testing"; "testing"
) )
type itob64Test struct { type itob64Test struct {
in int64; in int64
base uint; base uint
out string; out string
} }
var itob64tests = []itob64Test{ var itob64tests = []itob64Test{
@ -59,14 +59,14 @@ var itob64tests = []itob64Test{
func TestItoa(t *testing.T) { func TestItoa(t *testing.T) {
for _, test := range itob64tests { for _, test := range itob64tests {
s := Itob64(test.in, test.base); s := Itob64(test.in, test.base)
if s != test.out { if s != test.out {
t.Errorf("Itob64(%v, %v) = %v want %v\n", t.Errorf("Itob64(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
} }
if test.in >= 0 { if test.in >= 0 {
s := Uitob64(uint64(test.in), test.base); s := Uitob64(uint64(test.in), test.base)
if s != test.out { if s != test.out {
t.Errorf("Uitob64(%v, %v) = %v want %v\n", t.Errorf("Uitob64(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
@ -74,14 +74,14 @@ func TestItoa(t *testing.T) {
} }
if int64(int(test.in)) == test.in { if int64(int(test.in)) == test.in {
s := Itob(int(test.in), test.base); s := Itob(int(test.in), test.base)
if s != test.out { if s != test.out {
t.Errorf("Itob(%v, %v) = %v want %v\n", t.Errorf("Itob(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
} }
if test.in >= 0 { if test.in >= 0 {
s := Uitob(uint(test.in), test.base); s := Uitob(uint(test.in), test.base)
if s != test.out { if s != test.out {
t.Errorf("Uitob(%v, %v) = %v want %v\n", t.Errorf("Uitob(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
@ -90,14 +90,14 @@ func TestItoa(t *testing.T) {
} }
if test.base == 10 { if test.base == 10 {
s := Itoa64(test.in); s := Itoa64(test.in)
if s != test.out { if s != test.out {
t.Errorf("Itoa64(%v) = %v want %v\n", t.Errorf("Itoa64(%v) = %v want %v\n",
test.in, s, test.out) test.in, s, test.out)
} }
if test.in >= 0 { if test.in >= 0 {
s := Uitob64(uint64(test.in), test.base); s := Uitob64(uint64(test.in), test.base)
if s != test.out { if s != test.out {
t.Errorf("Uitob64(%v, %v) = %v want %v\n", t.Errorf("Uitob64(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
@ -105,14 +105,14 @@ func TestItoa(t *testing.T) {
} }
if int64(int(test.in)) == test.in { if int64(int(test.in)) == test.in {
s := Itoa(int(test.in)); s := Itoa(int(test.in))
if s != test.out { if s != test.out {
t.Errorf("Itoa(%v) = %v want %v\n", t.Errorf("Itoa(%v) = %v want %v\n",
test.in, s, test.out) test.in, s, test.out)
} }
if test.in >= 0 { if test.in >= 0 {
s := Uitoa(uint(test.in)); s := Uitoa(uint(test.in))
if s != test.out { if s != test.out {
t.Errorf("Uitoa(%v) = %v want %v\n", t.Errorf("Uitoa(%v) = %v want %v\n",
test.in, s, test.out) test.in, s, test.out)
@ -124,9 +124,9 @@ func TestItoa(t *testing.T) {
} }
type uitob64Test struct { type uitob64Test struct {
in uint64; in uint64
base uint; base uint
out string; out string
} }
var uitob64tests = []uitob64Test{ var uitob64tests = []uitob64Test{
@ -139,14 +139,14 @@ var uitob64tests = []uitob64Test{
func TestUitoa(t *testing.T) { func TestUitoa(t *testing.T) {
for _, test := range uitob64tests { for _, test := range uitob64tests {
s := Uitob64(test.in, test.base); s := Uitob64(test.in, test.base)
if s != test.out { if s != test.out {
t.Errorf("Uitob64(%v, %v) = %v want %v\n", t.Errorf("Uitob64(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
} }
if uint64(uint(test.in)) == test.in { if uint64(uint(test.in)) == test.in {
s := Uitob(uint(test.in), test.base); s := Uitob(uint(test.in), test.base)
if s != test.out { if s != test.out {
t.Errorf("Uitob(%v, %v) = %v want %v\n", t.Errorf("Uitob(%v, %v) = %v want %v\n",
test.in, test.base, s, test.out) test.in, test.base, s, test.out)
@ -154,14 +154,14 @@ func TestUitoa(t *testing.T) {
} }
if test.base == 10 { if test.base == 10 {
s := Uitoa64(test.in); s := Uitoa64(test.in)
if s != test.out { if s != test.out {
t.Errorf("Uitoa64(%v) = %v want %v\n", t.Errorf("Uitoa64(%v) = %v want %v\n",
test.in, s, test.out) test.in, s, test.out)
} }
if uint64(uint(test.in)) == test.in { if uint64(uint(test.in)) == test.in {
s := Uitoa(uint(test.in)); s := Uitoa(uint(test.in))
if s != test.out { if s != test.out {
t.Errorf("Uitoa(%v) = %v want %v\n", t.Errorf("Uitoa(%v) = %v want %v\n",
test.in, s, test.out) test.in, s, test.out)

View File

@ -5,11 +5,11 @@
package strconv package strconv
import ( import (
"bytes"; "bytes"
"os"; "os"
"strings"; "strings"
"unicode"; "unicode"
"utf8"; "utf8"
) )
const lowerhex = "0123456789abcdef" const lowerhex = "0123456789abcdef"
@ -19,8 +19,8 @@ const lowerhex = "0123456789abcdef"
// sequences (\t, \n, \xFF, \u0100) for control characters // sequences (\t, \n, \xFF, \u0100) for control characters
// and non-ASCII characters. // and non-ASCII characters.
func Quote(s string) string { func Quote(s string) string {
var buf bytes.Buffer; var buf bytes.Buffer
buf.WriteByte('"'); buf.WriteByte('"')
for ; len(s) > 0; s = s[1:] { for ; len(s) > 0; s = s[1:] {
switch c := s[0]; { switch c := s[0]; {
case c == '"': case c == '"':
@ -45,18 +45,18 @@ func Quote(s string) string {
buf.WriteString(`\v`) buf.WriteString(`\v`)
case c >= utf8.RuneSelf && utf8.FullRuneInString(s): case c >= utf8.RuneSelf && utf8.FullRuneInString(s):
r, size := utf8.DecodeRuneInString(s); r, size := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && size == 1 { if r == utf8.RuneError && size == 1 {
goto EscX goto EscX
} }
s = s[size-1:]; // next iteration will slice off 1 more s = s[size-1:] // next iteration will slice off 1 more
if r < 0x10000 { if r < 0x10000 {
buf.WriteString(`\u`); buf.WriteString(`\u`)
for j := uint(0); j < 4; j++ { for j := uint(0); j < 4; j++ {
buf.WriteByte(lowerhex[(r>>(12-4*j))&0xF]) buf.WriteByte(lowerhex[(r>>(12-4*j))&0xF])
} }
} else { } else {
buf.WriteString(`\U`); buf.WriteString(`\U`)
for j := uint(0); j < 8; j++ { for j := uint(0); j < 8; j++ {
buf.WriteByte(lowerhex[(r>>(28-4*j))&0xF]) buf.WriteByte(lowerhex[(r>>(28-4*j))&0xF])
} }
@ -64,13 +64,13 @@ func Quote(s string) string {
default: default:
EscX: EscX:
buf.WriteString(`\x`); buf.WriteString(`\x`)
buf.WriteByte(lowerhex[c>>4]); buf.WriteByte(lowerhex[c>>4])
buf.WriteByte(lowerhex[c&0xF]); buf.WriteByte(lowerhex[c&0xF])
} }
} }
buf.WriteByte('"'); buf.WriteByte('"')
return buf.String(); return buf.String()
} }
// CanBackquote returns whether the string s would be // CanBackquote returns whether the string s would be
@ -81,11 +81,11 @@ func CanBackquote(s string) bool {
return false return false
} }
} }
return true; return true
} }
func unhex(b byte) (v int, ok bool) { func unhex(b byte) (v int, ok bool) {
c := int(b); c := int(b)
switch { switch {
case '0' <= c && c <= '9': case '0' <= c && c <= '9':
return c - '0', true return c - '0', true
@ -94,7 +94,7 @@ func unhex(b byte) (v int, ok bool) {
case 'A' <= c && c <= 'F': case 'A' <= c && c <= 'F':
return c - 'A' + 10, true return c - 'A' + 10, true
} }
return; return
} }
// UnquoteChar decodes the first character or byte in the escaped string // UnquoteChar decodes the first character or byte in the escaped string
@ -114,22 +114,22 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
// easy cases // easy cases
switch c := s[0]; { switch c := s[0]; {
case c == quote && (quote == '\'' || quote == '"'): case c == quote && (quote == '\'' || quote == '"'):
err = os.EINVAL; err = os.EINVAL
return; return
case c >= utf8.RuneSelf: case c >= utf8.RuneSelf:
r, size := utf8.DecodeRuneInString(s); r, size := utf8.DecodeRuneInString(s)
return r, true, s[size:], nil; return r, true, s[size:], nil
case c != '\\': case c != '\\':
return int(s[0]), false, s[1:], nil return int(s[0]), false, s[1:], nil
} }
// hard case: c is backslash // hard case: c is backslash
if len(s) <= 1 { if len(s) <= 1 {
err = os.EINVAL; err = os.EINVAL
return; return
} }
c := s[1]; c := s[1]
s = s[2:]; s = s[2:]
switch c { switch c {
case 'a': case 'a':
@ -147,7 +147,7 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
case 'v': case 'v':
value = '\v' value = '\v'
case 'x', 'u', 'U': case 'x', 'u', 'U':
n := 0; n := 0
switch c { switch c {
case 'x': case 'x':
n = 2 n = 2
@ -156,64 +156,64 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
case 'U': case 'U':
n = 8 n = 8
} }
v := 0; v := 0
if len(s) < n { if len(s) < n {
err = os.EINVAL; err = os.EINVAL
return; return
} }
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
x, ok := unhex(s[j]); x, ok := unhex(s[j])
if !ok { if !ok {
err = os.EINVAL; err = os.EINVAL
return; return
} }
v = v<<4 | x; v = v<<4 | x
} }
s = s[n:]; s = s[n:]
if c == 'x' { if c == 'x' {
// single-byte string, possibly not UTF-8 // single-byte string, possibly not UTF-8
value = v; value = v
break; break
} }
if v > unicode.MaxRune { if v > unicode.MaxRune {
err = os.EINVAL; err = os.EINVAL
return; return
} }
value = v; value = v
multibyte = true; multibyte = true
case '0', '1', '2', '3', '4', '5', '6', '7': case '0', '1', '2', '3', '4', '5', '6', '7':
v := int(c) - '0'; v := int(c) - '0'
if len(s) < 2 { if len(s) < 2 {
err = os.EINVAL; err = os.EINVAL
return; return
} }
for j := 0; j < 2; j++ { // one digit already; two more for j := 0; j < 2; j++ { // one digit already; two more
x := int(s[j]) - '0'; x := int(s[j]) - '0'
if x < 0 || x > 7 { if x < 0 || x > 7 {
return return
} }
v = (v << 3) | x; v = (v << 3) | x
} }
s = s[2:]; s = s[2:]
if v > 255 { if v > 255 {
err = os.EINVAL; err = os.EINVAL
return; return
} }
value = v; value = v
case '\\': case '\\':
value = '\\' value = '\\'
case '\'', '"': case '\'', '"':
if c != quote { if c != quote {
err = os.EINVAL; err = os.EINVAL
return; return
} }
value = int(c); value = int(c)
default: default:
err = os.EINVAL; err = os.EINVAL
return; return
} }
tail = s; tail = s
return; return
} }
// Unquote interprets s as a single-quoted, double-quoted, // Unquote interprets s as a single-quoted, double-quoted,
@ -222,33 +222,33 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
// character literal; Unquote returns the corresponding // character literal; Unquote returns the corresponding
// one-character string.) // one-character string.)
func Unquote(s string) (t string, err os.Error) { func Unquote(s string) (t string, err os.Error) {
n := len(s); n := len(s)
if n < 2 { if n < 2 {
return "", os.EINVAL return "", os.EINVAL
} }
quote := s[0]; quote := s[0]
if quote != s[n-1] { if quote != s[n-1] {
return "", os.EINVAL return "", os.EINVAL
} }
s = s[1 : n-1]; s = s[1 : n-1]
if quote == '`' { if quote == '`' {
if strings.Index(s, "`") >= 0 { if strings.Index(s, "`") >= 0 {
return "", os.EINVAL return "", os.EINVAL
} }
return s, nil; return s, nil
} }
if quote != '"' && quote != '\'' { if quote != '"' && quote != '\'' {
return "", err return "", err
} }
var buf bytes.Buffer; var buf bytes.Buffer
for len(s) > 0 { for len(s) > 0 {
c, multibyte, ss, err := UnquoteChar(s, quote); c, multibyte, ss, err := UnquoteChar(s, quote)
if err != nil { if err != nil {
return "", err return "", err
} }
s = ss; s = ss
if c < utf8.RuneSelf || !multibyte { if c < utf8.RuneSelf || !multibyte {
buf.WriteByte(byte(c)) buf.WriteByte(byte(c))
} else { } else {
@ -259,5 +259,5 @@ func Unquote(s string) (t string, err os.Error) {
return "", os.EINVAL return "", os.EINVAL
} }
} }
return buf.String(), nil; return buf.String(), nil
} }

View File

@ -5,14 +5,14 @@
package strconv_test package strconv_test
import ( import (
"os"; "os"
. "strconv"; . "strconv"
"testing"; "testing"
) )
type quoteTest struct { type quoteTest struct {
in string; in string
out string; out string
} }
var quotetests = []quoteTest{ var quotetests = []quoteTest{
@ -26,7 +26,7 @@ var quotetests = []quoteTest{
func TestQuote(t *testing.T) { func TestQuote(t *testing.T) {
for i := 0; i < len(quotetests); i++ { for i := 0; i < len(quotetests); i++ {
tt := quotetests[i]; tt := quotetests[i]
if out := Quote(tt.in); out != tt.out { if out := Quote(tt.in); out != tt.out {
t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out) t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
} }
@ -34,8 +34,8 @@ func TestQuote(t *testing.T) {
} }
type canBackquoteTest struct { type canBackquoteTest struct {
in string; in string
out bool; out bool
} }
var canbackquotetests = []canBackquoteTest{ var canbackquotetests = []canBackquoteTest{
@ -49,7 +49,7 @@ var canbackquotetests = []canBackquoteTest{
canBackquoteTest{string(6), false}, canBackquoteTest{string(6), false},
canBackquoteTest{string(7), false}, canBackquoteTest{string(7), false},
canBackquoteTest{string(8), false}, canBackquoteTest{string(8), false},
canBackquoteTest{string(9), true}, // \t canBackquoteTest{string(9), true}, // \t
canBackquoteTest{string(10), false}, canBackquoteTest{string(10), false},
canBackquoteTest{string(11), false}, canBackquoteTest{string(11), false},
canBackquoteTest{string(12), false}, canBackquoteTest{string(12), false},
@ -81,7 +81,7 @@ var canbackquotetests = []canBackquoteTest{
func TestCanBackquote(t *testing.T) { func TestCanBackquote(t *testing.T) {
for i := 0; i < len(canbackquotetests); i++ { for i := 0; i < len(canbackquotetests); i++ {
tt := canbackquotetests[i]; tt := canbackquotetests[i]
if out := CanBackquote(tt.in); out != tt.out { if out := CanBackquote(tt.in); out != tt.out {
t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out) t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
} }
@ -147,7 +147,7 @@ var misquoted = []string{
func TestUnquote(t *testing.T) { func TestUnquote(t *testing.T) {
for i := 0; i < len(unquotetests); i++ { for i := 0; i < len(unquotetests); i++ {
tt := unquotetests[i]; tt := unquotetests[i]
if out, err := Unquote(tt.in); err != nil && out != tt.out { if out, err := Unquote(tt.in); err != nil && out != tt.out {
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out) t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
} }
@ -155,14 +155,14 @@ func TestUnquote(t *testing.T) {
// run the quote tests too, backward // run the quote tests too, backward
for i := 0; i < len(quotetests); i++ { for i := 0; i < len(quotetests); i++ {
tt := quotetests[i]; tt := quotetests[i]
if in, err := Unquote(tt.out); in != tt.in { if in, err := Unquote(tt.out); in != tt.in {
t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in) t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
} }
} }
for i := 0; i < len(misquoted); i++ { for i := 0; i < len(misquoted); i++ {
s := misquoted[i]; s := misquoted[i]
if out, err := Unquote(s); out != "" || err != os.EINVAL { if out, err := Unquote(s); out != "" || err != os.EINVAL {
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL) t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
} }

View File

@ -11,28 +11,28 @@ import "os"
type Reader string type Reader string
func (r *Reader) Read(b []byte) (n int, err os.Error) { func (r *Reader) Read(b []byte) (n int, err os.Error) {
s := *r; s := *r
if len(s) == 0 { if len(s) == 0 {
return 0, os.EOF return 0, os.EOF
} }
for n < len(s) && n < len(b) { for n < len(s) && n < len(b) {
b[n] = s[n]; b[n] = s[n]
n++; n++
} }
*r = s[n:]; *r = s[n:]
return; return
} }
func (r *Reader) ReadByte() (b byte, err os.Error) { func (r *Reader) ReadByte() (b byte, err os.Error) {
s := *r; s := *r
if len(s) == 0 { if len(s) == 0 {
return 0, os.EOF return 0, os.EOF
} }
b = s[0]; b = s[0]
*r = s[1:]; *r = s[1:]
return; return
} }
// NewReader returns a new Reader reading from s. // NewReader returns a new Reader reading from s.
// It is similar to bytes.NewBufferString but more efficient and read-only. // It is similar to bytes.NewBufferString but more efficient and read-only.
func NewReader(s string) *Reader { return (*Reader)(&s) } func NewReader(s string) *Reader { return (*Reader)(&s) }

View File

@ -6,8 +6,8 @@
package strings package strings
import ( import (
"unicode"; "unicode"
"utf8"; "utf8"
) )
// explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n <= 0 means no limit). // explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n <= 0 means no limit).
@ -16,21 +16,21 @@ func explode(s string, n int) []string {
if n <= 0 { if n <= 0 {
n = len(s) n = len(s)
} }
a := make([]string, n); a := make([]string, n)
var size, rune int; var size, rune int
na := 0; na := 0
for len(s) > 0 { for len(s) > 0 {
if na+1 >= n { if na+1 >= n {
a[na] = s; a[na] = s
na++; na++
break; break
} }
rune, size = utf8.DecodeRuneInString(s); rune, size = utf8.DecodeRuneInString(s)
s = s[size:]; s = s[size:]
a[na] = string(rune); a[na] = string(rune)
na++; na++
} }
return a[0:na]; return a[0:na]
} }
// Count counts the number of non-overlapping instances of sep in s. // Count counts the number of non-overlapping instances of sep in s.
@ -38,24 +38,24 @@ func Count(s, sep string) int {
if sep == "" { if sep == "" {
return utf8.RuneCountInString(s) + 1 return utf8.RuneCountInString(s) + 1
} }
c := sep[0]; c := sep[0]
n := 0; n := 0
for i := 0; i+len(sep) <= len(s); i++ { for i := 0; i+len(sep) <= len(s); i++ {
if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) { if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
n++; n++
i += len(sep) - 1; i += len(sep) - 1
} }
} }
return n; return n
} }
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
func Index(s, sep string) int { func Index(s, sep string) int {
n := len(sep); n := len(sep)
if n == 0 { if n == 0 {
return 0 return 0
} }
c := sep[0]; c := sep[0]
if n == 1 { if n == 1 {
// special case worth making fast // special case worth making fast
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
@ -63,23 +63,23 @@ func Index(s, sep string) int {
return i return i
} }
} }
return -1; return -1
} }
for i := 0; i+n <= len(s); i++ { for i := 0; i+n <= len(s); i++ {
if s[i] == c && (n == 1 || s[i:i+n] == sep) { if s[i] == c && (n == 1 || s[i:i+n] == sep) {
return i return i
} }
} }
return -1; return -1
} }
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s. // LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
func LastIndex(s, sep string) int { func LastIndex(s, sep string) int {
n := len(sep); n := len(sep)
if n == 0 { if n == 0 {
return len(s) return len(s)
} }
c := sep[0]; c := sep[0]
if n == 1 { if n == 1 {
// special case worth making fast // special case worth making fast
for i := len(s) - 1; i >= 0; i-- { for i := len(s) - 1; i >= 0; i-- {
@ -87,14 +87,14 @@ func LastIndex(s, sep string) int {
return i return i
} }
} }
return -1; return -1
} }
for i := len(s) - n; i >= 0; i-- { for i := len(s) - n; i >= 0; i-- {
if s[i] == c && (n == 1 || s[i:i+n] == sep) { if s[i] == c && (n == 1 || s[i:i+n] == sep) {
return i return i
} }
} }
return -1; return -1
} }
// Generic split: splits after each instance of sep, // Generic split: splits after each instance of sep,
@ -106,26 +106,26 @@ func genSplit(s, sep string, sepSave, n int) []string {
if n <= 0 { if n <= 0 {
n = Count(s, sep) + 1 n = Count(s, sep) + 1
} }
c := sep[0]; c := sep[0]
start := 0; start := 0
a := make([]string, n); a := make([]string, n)
na := 0; na := 0
for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ { for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) { if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
a[na] = s[start : i+sepSave]; a[na] = s[start : i+sepSave]
na++; na++
start = i + len(sep); start = i + len(sep)
i += len(sep) - 1; i += len(sep) - 1
} }
} }
a[na] = s[start:]; a[na] = s[start:]
return a[0 : na+1]; return a[0 : na+1]
} }
// Split splits the string s around each instance of sep, returning an array of substrings of s. // Split splits the string s around each instance of sep, returning an array of substrings of s.
// If sep is empty, Split splits s after each UTF-8 sequence. // If sep is empty, Split splits s after each UTF-8 sequence.
// If n > 0, Split splits s into at most n substrings; the last substring will be the unsplit remainder. // If n > 0, Split splits s into at most n substrings; the last substring will be the unsplit remainder.
func Split(s, sep string, n int) []string { return genSplit(s, sep, 0, n) } func Split(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
// SplitAfter splits the string s after each instance of sep, returning an array of substrings of s. // SplitAfter splits the string s after each instance of sep, returning an array of substrings of s.
// If sep is empty, SplitAfter splits s after each UTF-8 sequence. // If sep is empty, SplitAfter splits s after each UTF-8 sequence.
@ -143,28 +143,28 @@ func Join(a []string, sep string) string {
if len(a) == 1 { if len(a) == 1 {
return a[0] return a[0]
} }
n := len(sep) * (len(a) - 1); n := len(sep) * (len(a) - 1)
for i := 0; i < len(a); i++ { for i := 0; i < len(a); i++ {
n += len(a[i]) n += len(a[i])
} }
b := make([]byte, n); b := make([]byte, n)
bp := 0; bp := 0
for i := 0; i < len(a); i++ { for i := 0; i < len(a); i++ {
s := a[i]; s := a[i]
for j := 0; j < len(s); j++ { for j := 0; j < len(s); j++ {
b[bp] = s[j]; b[bp] = s[j]
bp++; bp++
} }
if i+1 < len(a) { if i+1 < len(a) {
s = sep; s = sep
for j := 0; j < len(s); j++ { for j := 0; j < len(s); j++ {
b[bp] = s[j]; b[bp] = s[j]
bp++; bp++
} }
} }
} }
return string(b); return string(b)
} }
// HasPrefix tests whether the string s begins with prefix. // HasPrefix tests whether the string s begins with prefix.
@ -184,105 +184,105 @@ func Map(mapping func(rune int) int, s string) string {
// In the worst case, the string can grow when mapped, making // In the worst case, the string can grow when mapped, making
// things unpleasant. But it's so rare we barge in assuming it's // things unpleasant. But it's so rare we barge in assuming it's
// fine. It could also shrink but that falls out naturally. // fine. It could also shrink but that falls out naturally.
maxbytes := len(s); // length of b maxbytes := len(s) // length of b
nbytes := 0; // number of bytes encoded in b nbytes := 0 // number of bytes encoded in b
b := make([]byte, maxbytes); b := make([]byte, maxbytes)
for _, c := range s { for _, c := range s {
rune := mapping(c); rune := mapping(c)
if rune >= 0 { if rune >= 0 {
wid := 1; wid := 1
if rune >= utf8.RuneSelf { if rune >= utf8.RuneSelf {
wid = utf8.RuneLen(rune) wid = utf8.RuneLen(rune)
} }
if nbytes+wid > maxbytes { if nbytes+wid > maxbytes {
// Grow the buffer. // Grow the buffer.
maxbytes = maxbytes*2 + utf8.UTFMax; maxbytes = maxbytes*2 + utf8.UTFMax
nb := make([]byte, maxbytes); nb := make([]byte, maxbytes)
for i, c := range b[0:nbytes] { for i, c := range b[0:nbytes] {
nb[i] = c nb[i] = c
} }
b = nb; b = nb
} }
nbytes += utf8.EncodeRune(rune, b[nbytes:maxbytes]); nbytes += utf8.EncodeRune(rune, b[nbytes:maxbytes])
} }
} }
return string(b[0:nbytes]); return string(b[0:nbytes])
} }
// Repeat returns a new string consisting of count copies of the string s. // Repeat returns a new string consisting of count copies of the string s.
func Repeat(s string, count int) string { func Repeat(s string, count int) string {
b := make([]byte, len(s)*count); b := make([]byte, len(s)*count)
bp := 0; bp := 0
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
for j := 0; j < len(s); j++ { for j := 0; j < len(s); j++ {
b[bp] = s[j]; b[bp] = s[j]
bp++; bp++
} }
} }
return string(b); return string(b)
} }
// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case. // ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.
func ToUpper(s string) string { return Map(unicode.ToUpper, s) } func ToUpper(s string) string { return Map(unicode.ToUpper, s) }
// ToLower returns a copy of the string s with all Unicode letters mapped to their lower case. // ToLower returns a copy of the string s with all Unicode letters mapped to their lower case.
func ToLower(s string) string { return Map(unicode.ToLower, s) } func ToLower(s string) string { return Map(unicode.ToLower, s) }
// ToTitle returns a copy of the string s with all Unicode letters mapped to their title case. // ToTitle returns a copy of the string s with all Unicode letters mapped to their title case.
func ToTitle(s string) string { return Map(unicode.ToTitle, s) } func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
// Trim returns a slice of the string s, with all leading and trailing white space // Trim returns a slice of the string s, with all leading and trailing white space
// removed, as defined by Unicode. // removed, as defined by Unicode.
func TrimSpace(s string) string { func TrimSpace(s string) string {
start, end := 0, len(s); start, end := 0, len(s)
for start < end { for start < end {
wid := 1; wid := 1
rune := int(s[start]); rune := int(s[start])
if rune >= utf8.RuneSelf { if rune >= utf8.RuneSelf {
rune, wid = utf8.DecodeRuneInString(s[start:end]) rune, wid = utf8.DecodeRuneInString(s[start:end])
} }
if !unicode.IsSpace(rune) { if !unicode.IsSpace(rune) {
break break
} }
start += wid; start += wid
} }
for start < end { for start < end {
wid := 1; wid := 1
rune := int(s[end-1]); rune := int(s[end-1])
if rune >= utf8.RuneSelf { if rune >= utf8.RuneSelf {
// Back up carefully looking for beginning of rune. Mustn't pass start. // Back up carefully looking for beginning of rune. Mustn't pass start.
for wid = 2; start <= end-wid && !utf8.RuneStart(s[end-wid]); wid++ { for wid = 2; start <= end-wid && !utf8.RuneStart(s[end-wid]); wid++ {
} }
if start > end-wid { // invalid UTF-8 sequence; stop processing if start > end-wid { // invalid UTF-8 sequence; stop processing
return s[start:end] return s[start:end]
} }
rune, wid = utf8.DecodeRuneInString(s[end-wid : end]); rune, wid = utf8.DecodeRuneInString(s[end-wid : end])
} }
if !unicode.IsSpace(rune) { if !unicode.IsSpace(rune) {
break break
} }
end -= wid; end -= wid
} }
return s[start:end]; return s[start:end]
} }
// Bytes returns a new slice containing the bytes in s. // Bytes returns a new slice containing the bytes in s.
func Bytes(s string) []byte { func Bytes(s string) []byte {
b := make([]byte, len(s)); b := make([]byte, len(s))
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
b[i] = s[i] b[i] = s[i]
} }
return b; return b
} }
// Runes returns a slice of runes (Unicode code points) equivalent to the string s. // Runes returns a slice of runes (Unicode code points) equivalent to the string s.
func Runes(s string) []int { func Runes(s string) []int {
t := make([]int, utf8.RuneCountInString(s)); t := make([]int, utf8.RuneCountInString(s))
i := 0; i := 0
for _, r := range s { for _, r := range s {
t[i] = r; t[i] = r
i++; i++
} }
return t; return t
} }

View File

@ -5,10 +5,10 @@
package strings_test package strings_test
import ( import (
. "strings"; . "strings"
"testing"; "testing"
"unicode"; "unicode"
"utf8"; "utf8"
) )
func eq(a, b []string) bool { func eq(a, b []string) bool {
@ -20,7 +20,7 @@ func eq(a, b []string) bool {
return false return false
} }
} }
return true; return true
} }
var abcd = "abcd" var abcd = "abcd"
@ -29,9 +29,9 @@ var commas = "1,2,3,4"
var dots = "1....2....3....4" var dots = "1....2....3....4"
type IndexTest struct { type IndexTest struct {
s string; s string
sep string; sep string
out int; out int
} }
var indexTests = []IndexTest{ var indexTests = []IndexTest{
@ -76,22 +76,22 @@ var lastIndexTests = []IndexTest{
// in failure reports. // in failure reports.
func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) { func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) {
for _, test := range testCases { for _, test := range testCases {
actual := f(test.s, test.sep); actual := f(test.s, test.sep)
if actual != test.out { if actual != test.out {
t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out) t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out)
} }
} }
} }
func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) } func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) } func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
type ExplodeTest struct { type ExplodeTest struct {
s string; s string
n int; n int
a []string; a []string
} }
var explodetests = []ExplodeTest{ var explodetests = []ExplodeTest{
@ -102,12 +102,12 @@ var explodetests = []ExplodeTest{
func TestExplode(t *testing.T) { func TestExplode(t *testing.T) {
for _, tt := range explodetests { for _, tt := range explodetests {
a := Split(tt.s, "", tt.n); a := Split(tt.s, "", tt.n)
if !eq(a, tt.a) { if !eq(a, tt.a) {
t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a); t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a)
continue; continue
} }
s := Join(a, ""); s := Join(a, "")
if s != tt.s { if s != tt.s {
t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s) t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s)
} }
@ -115,10 +115,10 @@ func TestExplode(t *testing.T) {
} }
type SplitTest struct { type SplitTest struct {
s string; s string
sep string; sep string
n int; n int
a []string; a []string
} }
var splittests = []SplitTest{ var splittests = []SplitTest{
@ -138,12 +138,12 @@ var splittests = []SplitTest{
func TestSplit(t *testing.T) { func TestSplit(t *testing.T) {
for _, tt := range splittests { for _, tt := range splittests {
a := Split(tt.s, tt.sep, tt.n); a := Split(tt.s, tt.sep, tt.n)
if !eq(a, tt.a) { if !eq(a, tt.a) {
t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a); t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a)
continue; continue
} }
s := Join(a, tt.sep); s := Join(a, tt.sep)
if s != tt.s { if s != tt.s {
t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s) t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s)
} }
@ -168,12 +168,12 @@ var splitaftertests = []SplitTest{
func TestSplitAfter(t *testing.T) { func TestSplitAfter(t *testing.T) {
for _, tt := range splitaftertests { for _, tt := range splitaftertests {
a := SplitAfter(tt.s, tt.sep, tt.n); a := SplitAfter(tt.s, tt.sep, tt.n)
if !eq(a, tt.a) { if !eq(a, tt.a) {
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a); t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a)
continue; continue
} }
s := Join(a, ""); s := Join(a, "")
if s != tt.s { if s != tt.s {
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
} }
@ -182,14 +182,14 @@ func TestSplitAfter(t *testing.T) {
// Test case for any function which accepts and returns a single string. // Test case for any function which accepts and returns a single string.
type StringTest struct { type StringTest struct {
in, out string; in, out string
} }
// Execute f on each test case. funcName should be the name of f; it's used // Execute f on each test case. funcName should be the name of f; it's used
// in failure reports. // in failure reports.
func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) { func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) {
for _, tc := range testCases { for _, tc := range testCases {
actual := f(tc.in); actual := f(tc.in)
if actual != tc.out { if actual != tc.out {
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
} }
@ -201,7 +201,7 @@ var upperTests = []StringTest{
StringTest{"abc", "ABC"}, StringTest{"abc", "ABC"},
StringTest{"AbC123", "ABC123"}, StringTest{"AbC123", "ABC123"},
StringTest{"azAZ09_", "AZAZ09_"}, StringTest{"azAZ09_", "AZAZ09_"},
StringTest{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char StringTest{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
} }
var lowerTests = []StringTest{ var lowerTests = []StringTest{
@ -209,7 +209,7 @@ var lowerTests = []StringTest{
StringTest{"abc", "abc"}, StringTest{"abc", "abc"},
StringTest{"AbC123", "abc123"}, StringTest{"AbC123", "abc123"},
StringTest{"azAZ09_", "azaz09_"}, StringTest{"azAZ09_", "azaz09_"},
StringTest{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char StringTest{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
} }
const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
@ -223,59 +223,59 @@ var trimSpaceTests = []StringTest{
StringTest{" \t\r\n x\t\t\r\r\n\n ", "x"}, StringTest{" \t\r\n x\t\t\r\r\n\n ", "x"},
StringTest{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, StringTest{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
StringTest{"1 \t\r\n2", "1 \t\r\n2"}, StringTest{"1 \t\r\n2", "1 \t\r\n2"},
StringTest{" x\x80", "x\x80"}, // invalid UTF-8 on end StringTest{" x\x80", "x\x80"}, // invalid UTF-8 on end
StringTest{" x\xc0", "x\xc0"}, // invalid UTF-8 on end StringTest{" x\xc0", "x\xc0"}, // invalid UTF-8 on end
} }
func tenRunes(rune int) string { func tenRunes(rune int) string {
r := make([]int, 10); r := make([]int, 10)
for i := range r { for i := range r {
r[i] = rune r[i] = rune
} }
return string(r); return string(r)
} }
// User-defined self-inverse mapping function // User-defined self-inverse mapping function
func rot13(rune int) int { func rot13(rune int) int {
step := 13; step := 13
if rune >= 'a' && rune <= 'z' { if rune >= 'a' && rune <= 'z' {
return ((rune - 'a' + step) % 26) + 'a' return ((rune - 'a' + step) % 26) + 'a'
} }
if rune >= 'A' && rune <= 'Z' { if rune >= 'A' && rune <= 'Z' {
return ((rune - 'A' + step) % 26) + 'A' return ((rune - 'A' + step) % 26) + 'A'
} }
return rune; return rune
} }
func TestMap(t *testing.T) { func TestMap(t *testing.T) {
// Run a couple of awful growth/shrinkage tests // Run a couple of awful growth/shrinkage tests
a := tenRunes('a'); a := tenRunes('a')
// 1. Grow. This triggers two reallocations in Map. // 1. Grow. This triggers two reallocations in Map.
maxRune := func(rune int) int { return unicode.MaxRune }; maxRune := func(rune int) int { return unicode.MaxRune }
m := Map(maxRune, a); m := Map(maxRune, a)
expect := tenRunes(unicode.MaxRune); expect := tenRunes(unicode.MaxRune)
if m != expect { if m != expect {
t.Errorf("growing: expected %q got %q", expect, m) t.Errorf("growing: expected %q got %q", expect, m)
} }
// 2. Shrink // 2. Shrink
minRune := func(rune int) int { return 'a' }; minRune := func(rune int) int { return 'a' }
m = Map(minRune, tenRunes(unicode.MaxRune)); m = Map(minRune, tenRunes(unicode.MaxRune))
expect = a; expect = a
if m != expect { if m != expect {
t.Errorf("shrinking: expected %q got %q", expect, m) t.Errorf("shrinking: expected %q got %q", expect, m)
} }
// 3. Rot13 // 3. Rot13
m = Map(rot13, "a to zed"); m = Map(rot13, "a to zed")
expect = "n gb mrq"; expect = "n gb mrq"
if m != expect { if m != expect {
t.Errorf("rot13: expected %q got %q", expect, m) t.Errorf("rot13: expected %q got %q", expect, m)
} }
// 4. Rot13^2 // 4. Rot13^2
m = Map(rot13, Map(rot13, "a to zed")); m = Map(rot13, Map(rot13, "a to zed"))
expect = "a to zed"; expect = "a to zed"
if m != expect { if m != expect {
t.Errorf("rot13: expected %q got %q", expect, m) t.Errorf("rot13: expected %q got %q", expect, m)
} }
@ -285,50 +285,50 @@ func TestMap(t *testing.T) {
if unicode.Is(unicode.Latin, rune) { if unicode.Is(unicode.Latin, rune) {
return rune return rune
} }
return -1; return -1
}; }
m = Map(dropNotLatin, "Hello, 세계"); m = Map(dropNotLatin, "Hello, 세계")
expect = "Hello"; expect = "Hello"
if m != expect { if m != expect {
t.Errorf("drop: expected %q got %q", expect, m) t.Errorf("drop: expected %q got %q", expect, m)
} }
} }
func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) } func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) } func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
func equal(m string, s1, s2 string, t *testing.T) bool { func equal(m string, s1, s2 string, t *testing.T) bool {
if s1 == s2 { if s1 == s2 {
return true return true
} }
e1 := Split(s1, "", 0); e1 := Split(s1, "", 0)
e2 := Split(s2, "", 0); e2 := Split(s2, "", 0)
for i, c1 := range e1 { for i, c1 := range e1 {
if i > len(e2) { if i > len(e2) {
break break
} }
r1, _ := utf8.DecodeRuneInString(c1); r1, _ := utf8.DecodeRuneInString(c1)
r2, _ := utf8.DecodeRuneInString(e2[i]); r2, _ := utf8.DecodeRuneInString(e2[i])
if r1 != r2 { if r1 != r2 {
t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2) t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2)
} }
} }
return false; return false
} }
func TestCaseConsistency(t *testing.T) { func TestCaseConsistency(t *testing.T) {
// Make a string of all the runes. // Make a string of all the runes.
a := make([]int, unicode.MaxRune+1); a := make([]int, unicode.MaxRune+1)
for i := range a { for i := range a {
a[i] = i a[i] = i
} }
s := string(a); s := string(a)
// convert the cases. // convert the cases.
upper := ToUpper(s); upper := ToUpper(s)
lower := ToLower(s); lower := ToLower(s)
// Consistency checks // Consistency checks
if n := utf8.RuneCountInString(upper); n != unicode.MaxRune+1 { if n := utf8.RuneCountInString(upper); n != unicode.MaxRune+1 {
@ -360,8 +360,8 @@ func TestCaseConsistency(t *testing.T) {
} }
type RepeatTest struct { type RepeatTest struct {
in, out string; in, out string
count int; count int
} }
var RepeatTests = []RepeatTest{ var RepeatTests = []RepeatTest{
@ -376,10 +376,10 @@ var RepeatTests = []RepeatTest{
func TestRepeat(t *testing.T) { func TestRepeat(t *testing.T) {
for _, tt := range RepeatTests { for _, tt := range RepeatTests {
a := Repeat(tt.in, tt.count); a := Repeat(tt.in, tt.count)
if !equal("Repeat(s)", a, tt.out, t) { if !equal("Repeat(s)", a, tt.out, t) {
t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out); t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out)
continue; continue
} }
} }
} }
@ -393,13 +393,13 @@ func runesEqual(a, b []int) bool {
return false return false
} }
} }
return true; return true
} }
type RunesTest struct { type RunesTest struct {
in string; in string
out []int; out []int
lossy bool; lossy bool
} }
var RunesTests = []RunesTest{ var RunesTests = []RunesTest{
@ -414,14 +414,14 @@ var RunesTests = []RunesTest{
func TestRunes(t *testing.T) { func TestRunes(t *testing.T) {
for _, tt := range RunesTests { for _, tt := range RunesTests {
a := Runes(tt.in); a := Runes(tt.in)
if !runesEqual(a, tt.out) { if !runesEqual(a, tt.out) {
t.Errorf("Runes(%q) = %v; want %v", tt.in, a, tt.out); t.Errorf("Runes(%q) = %v; want %v", tt.in, a, tt.out)
continue; continue
} }
if !tt.lossy { if !tt.lossy {
// can only test reassembly if we didn't lose information // can only test reassembly if we didn't lose information
s := string(a); s := string(a)
if s != tt.in { if s != tt.in {
t.Errorf("string(Runes(%q)) = %x; want %x", tt.in, s, tt.in) t.Errorf("string(Runes(%q)) = %x; want %x", tt.in, s, tt.in)
} }

View File

@ -16,8 +16,8 @@ func cas(val *uint32, old, new uint32) bool
// Mutexes can be created as part of other structures; // Mutexes can be created as part of other structures;
// the zero value for a Mutex is an unlocked mutex. // the zero value for a Mutex is an unlocked mutex.
type Mutex struct { type Mutex struct {
key uint32; key uint32
sema uint32; sema uint32
} }
// Add delta to *val, and return the new *val in a thread-safe way. If multiple // Add delta to *val, and return the new *val in a thread-safe way. If multiple
@ -25,13 +25,13 @@ type Mutex struct {
// serialized, and all the deltas will be added in an undefined order. // serialized, and all the deltas will be added in an undefined order.
func xadd(val *uint32, delta int32) (new uint32) { func xadd(val *uint32, delta int32) (new uint32) {
for { for {
v := *val; v := *val
nv := v + uint32(delta); nv := v + uint32(delta)
if cas(val, v, nv) { if cas(val, v, nv) {
return nv return nv
} }
} }
panic("unreached"); panic("unreached")
} }
// Lock locks m. // Lock locks m.
@ -42,7 +42,7 @@ func (m *Mutex) Lock() {
// changed from 0 to 1; we hold lock // changed from 0 to 1; we hold lock
return return
} }
runtime.Semacquire(&m.sema); runtime.Semacquire(&m.sema)
} }
// Unlock unlocks m. // Unlock unlocks m.
@ -56,5 +56,5 @@ func (m *Mutex) Unlock() {
// changed from 1 to 0; no contention // changed from 1 to 0; no contention
return return
} }
runtime.Semrelease(&m.sema); runtime.Semrelease(&m.sema)
} }

View File

@ -7,23 +7,23 @@
package sync_test package sync_test
import ( import (
"runtime"; "runtime"
. "sync"; . "sync"
"testing"; "testing"
) )
func HammerSemaphore(s *uint32, loops int, cdone chan bool) { func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
for i := 0; i < loops; i++ { for i := 0; i < loops; i++ {
runtime.Semacquire(s); runtime.Semacquire(s)
runtime.Semrelease(s); runtime.Semrelease(s)
} }
cdone <- true; cdone <- true
} }
func TestSemaphore(t *testing.T) { func TestSemaphore(t *testing.T) {
s := new(uint32); s := new(uint32)
*s = 1; *s = 1
c := make(chan bool); c := make(chan bool)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
go HammerSemaphore(s, 1000, c) go HammerSemaphore(s, 1000, c)
} }
@ -33,37 +33,37 @@ func TestSemaphore(t *testing.T) {
} }
func BenchmarkUncontendedSemaphore(b *testing.B) { func BenchmarkUncontendedSemaphore(b *testing.B) {
s := new(uint32); s := new(uint32)
*s = 1; *s = 1
HammerSemaphore(s, b.N, make(chan bool, 2)); HammerSemaphore(s, b.N, make(chan bool, 2))
} }
func BenchmarkContendedSemaphore(b *testing.B) { func BenchmarkContendedSemaphore(b *testing.B) {
b.StopTimer(); b.StopTimer()
s := new(uint32); s := new(uint32)
*s = 1; *s = 1
c := make(chan bool); c := make(chan bool)
runtime.GOMAXPROCS(2); runtime.GOMAXPROCS(2)
b.StartTimer(); b.StartTimer()
go HammerSemaphore(s, b.N/2, c); go HammerSemaphore(s, b.N/2, c)
go HammerSemaphore(s, b.N/2, c); go HammerSemaphore(s, b.N/2, c)
<-c; <-c
<-c; <-c
} }
func HammerMutex(m *Mutex, loops int, cdone chan bool) { func HammerMutex(m *Mutex, loops int, cdone chan bool) {
for i := 0; i < loops; i++ { for i := 0; i < loops; i++ {
m.Lock(); m.Lock()
m.Unlock(); m.Unlock()
} }
cdone <- true; cdone <- true
} }
func TestMutex(t *testing.T) { func TestMutex(t *testing.T) {
m := new(Mutex); m := new(Mutex)
c := make(chan bool); c := make(chan bool)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
go HammerMutex(m, 1000, c) go HammerMutex(m, 1000, c)
} }
@ -73,19 +73,19 @@ func TestMutex(t *testing.T) {
} }
func BenchmarkUncontendedMutex(b *testing.B) { func BenchmarkUncontendedMutex(b *testing.B) {
m := new(Mutex); m := new(Mutex)
HammerMutex(m, b.N, make(chan bool, 2)); HammerMutex(m, b.N, make(chan bool, 2))
} }
func BenchmarkContendedMutex(b *testing.B) { func BenchmarkContendedMutex(b *testing.B) {
b.StopTimer(); b.StopTimer()
m := new(Mutex); m := new(Mutex)
c := make(chan bool); c := make(chan bool)
runtime.GOMAXPROCS(2); runtime.GOMAXPROCS(2)
b.StartTimer(); b.StartTimer()
go HammerMutex(m, b.N/2, c); go HammerMutex(m, b.N/2, c)
go HammerMutex(m, b.N/2, c); go HammerMutex(m, b.N/2, c)
<-c; <-c
<-c; <-c
} }

View File

@ -14,9 +14,9 @@ package sync
// Writers take priority over Readers: no new RLocks // Writers take priority over Readers: no new RLocks
// are granted while a blocked Lock call is waiting. // are granted while a blocked Lock call is waiting.
type RWMutex struct { type RWMutex struct {
w Mutex; // held if there are pending readers or writers w Mutex // held if there are pending readers or writers
r Mutex; // held if the w is being rd r Mutex // held if the w is being rd
readerCount uint32; // number of pending readers readerCount uint32 // number of pending readers
} }
// RLock locks rw for reading. // RLock locks rw for reading.
@ -32,13 +32,13 @@ func (rw *RWMutex) RLock() {
// C: rw.RLock() // granted // C: rw.RLock() // granted
// B: rw.RUnlock() // B: rw.RUnlock()
// ... (new readers come and go indefinitely, W is starving) // ... (new readers come and go indefinitely, W is starving)
rw.r.Lock(); rw.r.Lock()
if xadd(&rw.readerCount, 1) == 1 { if xadd(&rw.readerCount, 1) == 1 {
// The first reader locks rw.w, so writers will be blocked // The first reader locks rw.w, so writers will be blocked
// while the readers have the RLock. // while the readers have the RLock.
rw.w.Lock() rw.w.Lock()
} }
rw.r.Unlock(); rw.r.Unlock()
} }
// RUnlock undoes a single RLock call; // RUnlock undoes a single RLock call;
@ -59,9 +59,9 @@ func (rw *RWMutex) RUnlock() {
// a blocked Lock call excludes new readers from acquiring // a blocked Lock call excludes new readers from acquiring
// the lock. // the lock.
func (rw *RWMutex) Lock() { func (rw *RWMutex) Lock() {
rw.r.Lock(); rw.r.Lock()
rw.w.Lock(); rw.w.Lock()
rw.r.Unlock(); rw.r.Unlock()
} }
// Unlock unlocks rw for writing. // Unlock unlocks rw for writing.
@ -72,4 +72,4 @@ func (rw *RWMutex) Lock() {
// a locked RWMutex is not associated with a particular goroutine. // a locked RWMutex is not associated with a particular goroutine.
// It is allowed for one goroutine to RLock (Lock) an RWMutex and then // It is allowed for one goroutine to RLock (Lock) an RWMutex and then
// arrange for another goroutine to RUnlock (Unlock) it. // arrange for another goroutine to RUnlock (Unlock) it.
func (rw *RWMutex) Unlock() { rw.w.Unlock() } func (rw *RWMutex) Unlock() { rw.w.Unlock() }

View File

@ -7,26 +7,26 @@
package sync_test package sync_test
import ( import (
"fmt"; "fmt"
"runtime"; "runtime"
. "sync"; . "sync"
"testing"; "testing"
) )
func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) { func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) {
m.RLock(); m.RLock()
clocked <- true; clocked <- true
<-cunlock; <-cunlock
m.RUnlock(); m.RUnlock()
cdone <- true; cdone <- true
} }
func doTestParallelReaders(numReaders, gomaxprocs int) { func doTestParallelReaders(numReaders, gomaxprocs int) {
runtime.GOMAXPROCS(gomaxprocs); runtime.GOMAXPROCS(gomaxprocs)
var m RWMutex; var m RWMutex
clocked := make(chan bool); clocked := make(chan bool)
cunlock := make(chan bool); cunlock := make(chan bool)
cdone := make(chan bool); cdone := make(chan bool)
for i := 0; i < numReaders; i++ { for i := 0; i < numReaders; i++ {
go parallelReader(&m, clocked, cunlock, cdone) go parallelReader(&m, clocked, cunlock, cdone)
} }
@ -44,53 +44,53 @@ func doTestParallelReaders(numReaders, gomaxprocs int) {
} }
func TestParallelReaders(t *testing.T) { func TestParallelReaders(t *testing.T) {
doTestParallelReaders(1, 4); doTestParallelReaders(1, 4)
doTestParallelReaders(3, 4); doTestParallelReaders(3, 4)
doTestParallelReaders(4, 2); doTestParallelReaders(4, 2)
} }
func reader(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) { func reader(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) {
for i := 0; i < num_iterations; i++ { for i := 0; i < num_iterations; i++ {
rwm.RLock(); rwm.RLock()
n := Xadd(activity, 1); n := Xadd(activity, 1)
if n < 1 || n >= 10000 { if n < 1 || n >= 10000 {
panic(fmt.Sprintf("wlock(%d)\n", n)) panic(fmt.Sprintf("wlock(%d)\n", n))
} }
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
} }
Xadd(activity, -1); Xadd(activity, -1)
rwm.RUnlock(); rwm.RUnlock()
} }
cdone <- true; cdone <- true
} }
func writer(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) { func writer(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) {
for i := 0; i < num_iterations; i++ { for i := 0; i < num_iterations; i++ {
rwm.Lock(); rwm.Lock()
n := Xadd(activity, 10000); n := Xadd(activity, 10000)
if n != 10000 { if n != 10000 {
panic(fmt.Sprintf("wlock(%d)\n", n)) panic(fmt.Sprintf("wlock(%d)\n", n))
} }
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
} }
Xadd(activity, -10000); Xadd(activity, -10000)
rwm.Unlock(); rwm.Unlock()
} }
cdone <- true; cdone <- true
} }
func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) { func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
runtime.GOMAXPROCS(gomaxprocs); runtime.GOMAXPROCS(gomaxprocs)
// Number of active readers + 10000 * number of active writers. // Number of active readers + 10000 * number of active writers.
var activity uint32; var activity uint32
var rwm RWMutex; var rwm RWMutex
cdone := make(chan bool); cdone := make(chan bool)
go writer(&rwm, num_iterations, &activity, cdone); go writer(&rwm, num_iterations, &activity, cdone)
var i int; var i int
for i = 0; i < numReaders/2; i++ { for i = 0; i < numReaders/2; i++ {
go reader(&rwm, num_iterations, &activity, cdone) go reader(&rwm, num_iterations, &activity, cdone)
} }
go writer(&rwm, num_iterations, &activity, cdone); go writer(&rwm, num_iterations, &activity, cdone)
for ; i < numReaders; i++ { for ; i < numReaders; i++ {
go reader(&rwm, num_iterations, &activity, cdone) go reader(&rwm, num_iterations, &activity, cdone)
} }
@ -101,14 +101,14 @@ func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
} }
func TestRWMutex(t *testing.T) { func TestRWMutex(t *testing.T) {
HammerRWMutex(1, 1, 1000); HammerRWMutex(1, 1, 1000)
HammerRWMutex(1, 3, 1000); HammerRWMutex(1, 3, 1000)
HammerRWMutex(1, 10, 1000); HammerRWMutex(1, 10, 1000)
HammerRWMutex(4, 1, 1000); HammerRWMutex(4, 1, 1000)
HammerRWMutex(4, 3, 1000); HammerRWMutex(4, 3, 1000)
HammerRWMutex(4, 10, 1000); HammerRWMutex(4, 10, 1000)
HammerRWMutex(10, 1, 1000); HammerRWMutex(10, 1, 1000)
HammerRWMutex(10, 3, 1000); HammerRWMutex(10, 3, 1000)
HammerRWMutex(10, 10, 1000); HammerRWMutex(10, 10, 1000)
HammerRWMutex(10, 5, 10000); HammerRWMutex(10, 5, 10000)
} }

View File

@ -5,24 +5,24 @@
package syscall package syscall
func str(val int) string { // do it here rather than with fmt to avoid dependency func str(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 { if val < 0 {
return "-" + str(-val) return "-" + str(-val)
} }
var buf [32]byte; // big enough for int64 var buf [32]byte // big enough for int64
i := len(buf) - 1; i := len(buf) - 1
for val >= 10 { for val >= 10 {
buf[i] = byte(val%10 + '0'); buf[i] = byte(val%10 + '0')
i--; i--
val /= 10; val /= 10
} }
buf[i] = byte(val + '0'); buf[i] = byte(val + '0')
return string(buf[i:]); return string(buf[i:])
} }
func Errstr(errno int) string { func Errstr(errno int) string {
if errno < 0 || errno >= int(len(errors)) { if errno < 0 || errno >= int(len(errors)) {
return "error " + str(errno) return "error " + str(errno)
} }
return errors[errno]; return errors[errno]
} }

View File

@ -7,8 +7,8 @@
package syscall package syscall
import ( import (
"sync"; "sync"
"unsafe"; "unsafe"
) )
// Lock synchronizing creation of new file descriptors with fork. // Lock synchronizing creation of new file descriptors with fork.
@ -63,18 +63,18 @@ var ForkLock sync.RWMutex
// Convert array of string to array // Convert array of string to array
// of NUL-terminated byte pointer. // of NUL-terminated byte pointer.
func StringArrayPtr(ss []string) []*byte { func StringArrayPtr(ss []string) []*byte {
bb := make([]*byte, len(ss)+1); bb := make([]*byte, len(ss)+1)
for i := 0; i < len(ss); i++ { for i := 0; i < len(ss); i++ {
bb[i] = StringBytePtr(ss[i]) bb[i] = StringBytePtr(ss[i])
} }
bb[len(ss)] = nil; bb[len(ss)] = nil
return bb; return bb
} }
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
func SetNonblock(fd int, nonblocking bool) (errno int) { func SetNonblock(fd int, nonblocking bool) (errno int) {
flag, err := fcntl(fd, F_GETFL, 0); flag, err := fcntl(fd, F_GETFL, 0)
if err != 0 { if err != 0 {
return err return err
} }
@ -83,8 +83,8 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
} else { } else {
flag &= ^O_NONBLOCK flag &= ^O_NONBLOCK
} }
_, err = fcntl(fd, F_SETFL, flag); _, err = fcntl(fd, F_SETFL, flag)
return err; return err
} }
@ -99,15 +99,15 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, dir *byte, fd []int, pipe int) (pid int, err int) { func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, dir *byte, fd []int, pipe int) (pid int, err int) {
// Declare all variables at top in case any // Declare all variables at top in case any
// declarations require heap allocation (e.g., err1). // declarations require heap allocation (e.g., err1).
var r1, r2, err1 uintptr; var r1, r2, err1 uintptr
var nextfd int; var nextfd int
var i int; var i int
darwin := OS == "darwin"; darwin := OS == "darwin"
// About to call fork. // About to call fork.
// No more allocation or calls of non-assembly functions. // No more allocation or calls of non-assembly functions.
r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0); r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
if err1 != 0 { if err1 != 0 {
return 0, int(err1) return 0, int(err1)
} }
@ -129,7 +129,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
// Enable tracing if requested. // Enable tracing if requested.
if traceme { if traceme {
_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0); _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
if err1 != 0 { if err1 != 0 {
goto childerror goto childerror
} }
@ -137,7 +137,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
// Chdir // Chdir
if dir != nil { if dir != nil {
_, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0); _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
if err1 != 0 { if err1 != 0 {
goto childerror goto childerror
} }
@ -145,26 +145,26 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
// Pass 1: look for fd[i] < i and move those up above len(fd) // Pass 1: look for fd[i] < i and move those up above len(fd)
// so that pass 2 won't stomp on an fd it needs later. // so that pass 2 won't stomp on an fd it needs later.
nextfd = int(len(fd)); nextfd = int(len(fd))
if pipe < nextfd { if pipe < nextfd {
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0); _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
if err1 != 0 { if err1 != 0 {
goto childerror goto childerror
} }
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC); RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
pipe = nextfd; pipe = nextfd
nextfd++; nextfd++
} }
for i = 0; i < len(fd); i++ { for i = 0; i < len(fd); i++ {
if fd[i] >= 0 && fd[i] < int(i) { if fd[i] >= 0 && fd[i] < int(i) {
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0); _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
if err1 != 0 { if err1 != 0 {
goto childerror goto childerror
} }
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC); RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
fd[i] = nextfd; fd[i] = nextfd
nextfd++; nextfd++
if nextfd == pipe { // don't stomp on pipe if nextfd == pipe { // don't stomp on pipe
nextfd++ nextfd++
} }
} }
@ -173,21 +173,21 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
// Pass 2: dup fd[i] down onto i. // Pass 2: dup fd[i] down onto i.
for i = 0; i < len(fd); i++ { for i = 0; i < len(fd); i++ {
if fd[i] == -1 { if fd[i] == -1 {
RawSyscall(SYS_CLOSE, uintptr(i), 0, 0); RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
continue; continue
} }
if fd[i] == int(i) { if fd[i] == int(i) {
// dup2(i, i) won't clear close-on-exec flag on Linux, // dup2(i, i) won't clear close-on-exec flag on Linux,
// probably not elsewhere either. // probably not elsewhere either.
_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0); _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
if err1 != 0 { if err1 != 0 {
goto childerror goto childerror
} }
continue; continue
} }
// The new fd is created NOT close-on-exec, // The new fd is created NOT close-on-exec,
// which is exactly what we want. // which is exactly what we want.
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0); _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
if err1 != 0 { if err1 != 0 {
goto childerror goto childerror
} }
@ -205,11 +205,11 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
_, _, err1 = RawSyscall(SYS_EXECVE, _, _, err1 = RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(argv0)), uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])), uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&envv[0]))); uintptr(unsafe.Pointer(&envv[0])))
childerror: childerror:
// send error code on pipe // send error code on pipe
RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1))); RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)))
for { for {
RawSyscall(SYS_EXIT, 253, 0, 0) RawSyscall(SYS_EXIT, 253, 0, 0)
} }
@ -217,23 +217,23 @@ childerror:
// Calling panic is not actually safe, // Calling panic is not actually safe,
// but the for loop above won't break // but the for loop above won't break
// and this shuts up the compiler. // and this shuts up the compiler.
panic("unreached"); panic("unreached")
} }
func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) { func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
var p [2]int; var p [2]int
var n int; var n int
var err1 uintptr; var err1 uintptr
var wstatus WaitStatus; var wstatus WaitStatus
p[0] = -1; p[0] = -1
p[1] = -1; p[1] = -1
// Convert args to C form. // Convert args to C form.
argv0p := StringBytePtr(argv0); argv0p := StringBytePtr(argv0)
argvp := StringArrayPtr(argv); argvp := StringArrayPtr(argv)
envvp := StringArrayPtr(envv); envvp := StringArrayPtr(envv)
var dirp *byte; var dirp *byte
if len(dir) > 0 { if len(dir) > 0 {
dirp = StringBytePtr(dir) dirp = StringBytePtr(dir)
} }
@ -241,7 +241,7 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
// Acquire the fork lock so that no other threads // Acquire the fork lock so that no other threads
// create new fds that are not yet close-on-exec // create new fds that are not yet close-on-exec
// before we fork. // before we fork.
ForkLock.Lock(); ForkLock.Lock()
// Allocate child status pipe close on exec. // Allocate child status pipe close on exec.
if err = Pipe(&p); err != 0 { if err = Pipe(&p); err != 0 {
@ -255,22 +255,22 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
} }
// Kick off child. // Kick off child.
pid, err = forkAndExecInChild(argv0p, argvp, envvp, traceme, dirp, fd, p[1]); pid, err = forkAndExecInChild(argv0p, argvp, envvp, traceme, dirp, fd, p[1])
if err != 0 { if err != 0 {
error: error:
if p[0] >= 0 { if p[0] >= 0 {
Close(p[0]); Close(p[0])
Close(p[1]); Close(p[1])
} }
ForkLock.Unlock(); ForkLock.Unlock()
return 0, err; return 0, err
} }
ForkLock.Unlock(); ForkLock.Unlock()
// Read child error status from pipe. // Read child error status from pipe.
Close(p[1]); Close(p[1])
n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), unsafe.Sizeof(err1)); n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
Close(p[0]); Close(p[0])
if err != 0 || n != 0 { if err != 0 || n != 0 {
if n == unsafe.Sizeof(err1) { if n == unsafe.Sizeof(err1) {
err = int(err1) err = int(err1)
@ -281,15 +281,15 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
// Child failed; wait for it to exit, to make sure // Child failed; wait for it to exit, to make sure
// the zombies don't accumulate. // the zombies don't accumulate.
_, err1 := Wait4(pid, &wstatus, 0, nil); _, err1 := Wait4(pid, &wstatus, 0, nil)
for err1 == EINTR { for err1 == EINTR {
_, err1 = Wait4(pid, &wstatus, 0, nil) _, err1 = Wait4(pid, &wstatus, 0, nil)
} }
return 0, err; return 0, err
} }
// Read got EOF, so pipe closed on exec, so exec succeeded. // Read got EOF, so pipe closed on exec, so exec succeeded.
return pid, 0; return pid, 0
} }
// Combination of fork and exec, careful to be thread safe. // Combination of fork and exec, careful to be thread safe.
@ -307,6 +307,6 @@ func Exec(argv0 string, argv []string, envv []string) (err int) {
_, _, err1 := RawSyscall(SYS_EXECVE, _, _, err1 := RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(StringBytePtr(argv0))), uintptr(unsafe.Pointer(StringBytePtr(argv0))),
uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0])), uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0])),
uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0]))); uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])))
return int(err1); return int(err1)
} }

View File

@ -18,13 +18,13 @@ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
// StringByteSlice returns a NUL-terminated slice of bytes // StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s. // containing the text of s.
func StringByteSlice(s string) []byte { func StringByteSlice(s string) []byte {
a := make([]byte, len(s)+1); a := make([]byte, len(s)+1)
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
a[i] = s[i] a[i] = s[i]
} }
return a; return a
} }
// StringBytePtr returns a pointer to a NUL-terminated array of bytes // StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s. // containing the text of s.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] } func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }

View File

@ -23,7 +23,7 @@ const OS = "darwin"
// even linking this function into the binary. See ../os/getwd.go. // even linking this function into the binary. See ../os/getwd.go.
const ImplementsGetwd = false const ImplementsGetwd = false
func Getwd() (string, int) { return "", ENOTSUP } func Getwd() (string, int) { return "", ENOTSUP }
/* /*
@ -34,7 +34,7 @@ func Getwd() (string, int) { return "", ENOTSUP }
//sys setgroups(ngid int, gid *_Gid_t) (errno int) //sys setgroups(ngid int, gid *_Gid_t) (errno int)
func Getgroups() (gids []int, errno int) { func Getgroups() (gids []int, errno int) {
n, err := getgroups(0, nil); n, err := getgroups(0, nil)
if err != 0 { if err != 0 {
return nil, errno return nil, errno
} }
@ -47,16 +47,16 @@ func Getgroups() (gids []int, errno int) {
return nil, EINVAL return nil, EINVAL
} }
a := make([]_Gid_t, n); a := make([]_Gid_t, n)
n, err = getgroups(n, &a[0]); n, err = getgroups(n, &a[0])
if err != 0 { if err != 0 {
return nil, errno return nil, errno
} }
gids = make([]int, n); gids = make([]int, n)
for i, v := range a[0:n] { for i, v := range a[0:n] {
gids[i] = int(v) gids[i] = int(v)
} }
return; return
} }
func Setgroups(gids []int) (errno int) { func Setgroups(gids []int) (errno int) {
@ -64,11 +64,11 @@ func Setgroups(gids []int) (errno int) {
return setgroups(0, nil) return setgroups(0, nil)
} }
a := make([]_Gid_t, len(gids)); a := make([]_Gid_t, len(gids))
for i, v := range gids { for i, v := range gids {
a[i] = _Gid_t(v) a[i] = _Gid_t(v)
} }
return setgroups(len(a), &a[0]); return setgroups(len(a), &a[0])
} }
// Wait status is 7 bits at bottom, either 0 (exited), // Wait status is 7 bits at bottom, either 0 (exited),
@ -80,44 +80,44 @@ func Setgroups(gids []int) (errno int) {
type WaitStatus uint32 type WaitStatus uint32
const ( const (
mask = 0x7F; mask = 0x7F
core = 0x80; core = 0x80
shift = 8; shift = 8
exited = 0; exited = 0
stopped = 0x7F; stopped = 0x7F
) )
func (w WaitStatus) Exited() bool { return w&mask == exited } func (w WaitStatus) Exited() bool { return w&mask == exited }
func (w WaitStatus) ExitStatus() int { func (w WaitStatus) ExitStatus() int {
if w&mask != exited { if w&mask != exited {
return -1 return -1
} }
return int(w >> shift); return int(w >> shift)
} }
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
func (w WaitStatus) Signal() int { func (w WaitStatus) Signal() int {
sig := int(w & mask); sig := int(w & mask)
if sig == stopped || sig == 0 { if sig == stopped || sig == 0 {
return -1 return -1
} }
return sig; return sig
} }
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
func (w WaitStatus) Stopped() bool { return w&mask == stopped && w>>shift != SIGSTOP } func (w WaitStatus) Stopped() bool { return w&mask == stopped && w>>shift != SIGSTOP }
func (w WaitStatus) Continued() bool { return w&mask == stopped && w>>shift == SIGSTOP } func (w WaitStatus) Continued() bool { return w&mask == stopped && w>>shift == SIGSTOP }
func (w WaitStatus) StopSignal() int { func (w WaitStatus) StopSignal() int {
if !w.Stopped() { if !w.Stopped() {
return -1 return -1
} }
return int(w>>shift) & 0xFF; return int(w>>shift) & 0xFF
} }
func (w WaitStatus) TrapCause() int { func (w WaitStatus) TrapCause() int {
@ -128,12 +128,12 @@ func (w WaitStatus) TrapCause() int {
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) //sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status _C_int; var status _C_int
wpid, errno = wait4(pid, &status, options, rusage); wpid, errno = wait4(pid, &status, options, rusage)
if wstatus != nil { if wstatus != nil {
*wstatus = WaitStatus(status) *wstatus = WaitStatus(status)
} }
return; return
} }
//sys pipe() (r int, w int, errno int) //sys pipe() (r int, w int, errno int)
@ -142,13 +142,13 @@ func Pipe(p []int) (errno int) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
} }
p[0], p[1], errno = pipe(); p[0], p[1], errno = pipe()
return; return
} }
func Sleep(ns int64) (errno int) { func Sleep(ns int64) (errno int) {
tv := NsecToTimeval(ns); tv := NsecToTimeval(ns)
return Select(0, nil, nil, nil, &tv); return Select(0, nil, nil, nil, &tv)
} }
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
@ -165,173 +165,173 @@ func Sleep(ns int64) (errno int) {
var SocketDisableIPv6 bool var SocketDisableIPv6 bool
type Sockaddr interface { type Sockaddr interface {
sockaddr() (ptr uintptr, len _Socklen, errno int); // lowercase; only we can define Sockaddrs sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
} }
type SockaddrInet4 struct { type SockaddrInet4 struct {
Port int; Port int
Addr [4]byte; Addr [4]byte
raw RawSockaddrInet4; raw RawSockaddrInet4
} }
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
if sa.Port < 0 || sa.Port > 0xFFFF { if sa.Port < 0 || sa.Port > 0xFFFF {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Len = SizeofSockaddrInet4; sa.raw.Len = SizeofSockaddrInet4
sa.raw.Family = AF_INET; sa.raw.Family = AF_INET
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8); p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port); p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i] sa.raw.Addr[i] = sa.Addr[i]
} }
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0; return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
} }
type SockaddrInet6 struct { type SockaddrInet6 struct {
Port int; Port int
Addr [16]byte; Addr [16]byte
raw RawSockaddrInet6; raw RawSockaddrInet6
} }
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
if sa.Port < 0 || sa.Port > 0xFFFF { if sa.Port < 0 || sa.Port > 0xFFFF {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Len = SizeofSockaddrInet6; sa.raw.Len = SizeofSockaddrInet6
sa.raw.Family = AF_INET6; sa.raw.Family = AF_INET6
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8); p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port); p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i] sa.raw.Addr[i] = sa.Addr[i]
} }
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0; return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
} }
type SockaddrUnix struct { type SockaddrUnix struct {
Name string; Name string
raw RawSockaddrUnix; raw RawSockaddrUnix
} }
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
name := sa.Name; name := sa.Name
n := len(name); n := len(name)
if n >= len(sa.raw.Path) || n == 0 { if n >= len(sa.raw.Path) || n == 0 {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
sa.raw.Family = AF_UNIX; sa.raw.Family = AF_UNIX
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i]) sa.raw.Path[i] = int8(name[i])
} }
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0; return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
} }
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) { func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_UNIX: case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)); pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
if pp.Len < 3 || pp.Len > SizeofSockaddrUnix { if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
return nil, EINVAL return nil, EINVAL
} }
sa := new(SockaddrUnix); sa := new(SockaddrUnix)
n := int(pp.Len) - 3; // subtract leading Family, Len, terminating NUL n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if pp.Path[i] == 0 { if pp.Path[i] == 0 {
// found early NUL; assume Len is overestimating // found early NUL; assume Len is overestimating
n = i; n = i
break; break
} }
} }
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0])); bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
sa.Name = string(bytes[0:n]); sa.Name = string(bytes[0:n])
return sa, 0; return sa, 0
case AF_INET: case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)); pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4); sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)); p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]); sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, 0; return sa, 0
case AF_INET6: case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)); pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6); sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)); p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]); sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, 0; return sa, 0
} }
return nil, EAFNOSUPPORT; return nil, EAFNOSUPPORT
} }
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
nfd, errno = accept(fd, &rsa, &len); nfd, errno = accept(fd, &rsa, &len)
if errno != 0 { if errno != 0 {
return return
} }
sa, errno = anyToSockaddr(&rsa); sa, errno = anyToSockaddr(&rsa)
if errno != 0 { if errno != 0 {
Close(nfd); Close(nfd)
nfd = 0; nfd = 0
} }
return; return
} }
func Getsockname(fd int) (sa Sockaddr, errno int) { func Getsockname(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if errno = getsockname(fd, &rsa, &len); errno != 0 { if errno = getsockname(fd, &rsa, &len); errno != 0 {
return return
} }
return anyToSockaddr(&rsa); return anyToSockaddr(&rsa)
} }
func Getpeername(fd int) (sa Sockaddr, errno int) { func Getpeername(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if errno = getpeername(fd, &rsa, &len); errno != 0 { if errno = getpeername(fd, &rsa, &len); errno != 0 {
return return
} }
return anyToSockaddr(&rsa); return anyToSockaddr(&rsa)
} }
func Bind(fd int, sa Sockaddr) (errno int) { func Bind(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr(); ptr, n, err := sa.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return bind(fd, ptr, n); return bind(fd, ptr, n)
} }
func Connect(fd int, sa Sockaddr) (errno int) { func Connect(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr(); ptr, n, err := sa.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return connect(fd, ptr, n); return connect(fd, ptr, n)
} }
func Socket(domain, typ, proto int) (fd, errno int) { func Socket(domain, typ, proto int) (fd, errno int) {
if domain == AF_INET6 && SocketDisableIPv6 { if domain == AF_INET6 && SocketDisableIPv6 {
return -1, EAFNOSUPPORT return -1, EAFNOSUPPORT
} }
fd, errno = socket(domain, typ, proto); fd, errno = socket(domain, typ, proto)
return; return
} }
func SetsockoptInt(fd, level, opt int, value int) (errno int) { func SetsockoptInt(fd, level, opt int, value int) (errno int) {
var n = int32(value); var n = int32(value)
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4); return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
} }
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) { func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
@ -346,44 +346,44 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) { func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 { if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
return return
} }
from, errno = anyToSockaddr(&rsa); from, errno = anyToSockaddr(&rsa)
return; return
} }
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) //sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) { func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
ptr, n, err := to.sockaddr(); ptr, n, err := to.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return sendto(fd, p, flags, ptr, n); return sendto(fd, p, flags, ptr, n)
} }
//sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) //sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) { func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
var change, event uintptr; var change, event uintptr
if len(changes) > 0 { if len(changes) > 0 {
change = uintptr(unsafe.Pointer(&changes[0])) change = uintptr(unsafe.Pointer(&changes[0]))
} }
if len(events) > 0 { if len(events) > 0 {
event = uintptr(unsafe.Pointer(&events[0])) event = uintptr(unsafe.Pointer(&events[0]))
} }
return kevent(kq, change, len(changes), event, len(events), timeout); return kevent(kq, change, len(changes), event, len(events), timeout)
} }
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
// Translate "kern.hostname" to []_C_int{0,1,2,3}. // Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, errno int) { func nametomib(name string) (mib []_C_int, errno int) {
const CTL_MAXNAME = 12; const CTL_MAXNAME = 12
const siz = uintptr(unsafe.Sizeof(mib[0])); const siz = uintptr(unsafe.Sizeof(mib[0]))
// NOTE(rsc): It seems strange to set the buffer to have // NOTE(rsc): It seems strange to set the buffer to have
// size CTL_MAXNAME+2 but use only CTL_MAXNAME // size CTL_MAXNAME+2 but use only CTL_MAXNAME
@ -392,29 +392,29 @@ func nametomib(name string) (mib []_C_int, errno int) {
// I am scared that if we don't include the +2 here, the kernel // I am scared that if we don't include the +2 here, the kernel
// will silently write 2 words farther than we specify // will silently write 2 words farther than we specify
// and we'll get memory corruption. // and we'll get memory corruption.
var buf [CTL_MAXNAME + 2]_C_int; var buf [CTL_MAXNAME + 2]_C_int
n := uintptr(CTL_MAXNAME) * siz; n := uintptr(CTL_MAXNAME) * siz
p := (*byte)(unsafe.Pointer(&buf[0])); p := (*byte)(unsafe.Pointer(&buf[0]))
bytes := StringByteSlice(name); bytes := StringByteSlice(name)
// Magic sysctl: "setting" 0.3 to a string name // Magic sysctl: "setting" 0.3 to a string name
// lets you read back the array of integers form. // lets you read back the array of integers form.
if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 { if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
return nil, errno return nil, errno
} }
return buf[0 : n/siz], 0; return buf[0 : n/siz], 0
} }
func Sysctl(name string) (value string, errno int) { func Sysctl(name string) (value string, errno int) {
// Translate name to mib number. // Translate name to mib number.
mib, errno := nametomib(name); mib, errno := nametomib(name)
if errno != 0 { if errno != 0 {
return "", errno return "", errno
} }
// Find size. // Find size.
n := uintptr(0); n := uintptr(0)
if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 { if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
return "", errno return "", errno
} }
@ -423,7 +423,7 @@ func Sysctl(name string) (value string, errno int) {
} }
// Read into buffer of that size. // Read into buffer of that size.
buf := make([]byte, n); buf := make([]byte, n)
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 { if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
return "", errno return "", errno
} }
@ -432,26 +432,26 @@ func Sysctl(name string) (value string, errno int) {
if n > 0 && buf[n-1] == '\x00' { if n > 0 && buf[n-1] == '\x00' {
n-- n--
} }
return string(buf[0:n]), 0; return string(buf[0:n]), 0
} }
func SysctlUint32(name string) (value uint32, errno int) { func SysctlUint32(name string) (value uint32, errno int) {
// Translate name to mib number. // Translate name to mib number.
mib, errno := nametomib(name); mib, errno := nametomib(name)
if errno != 0 { if errno != 0 {
return 0, errno return 0, errno
} }
// Read into buffer of that size. // Read into buffer of that size.
n := uintptr(4); n := uintptr(4)
buf := make([]byte, 4); buf := make([]byte, 4)
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 { if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
return 0, errno return 0, errno
} }
if n != 4 { if n != 4 {
return 0, EIO return 0, EIO
} }
return *(*uint32)(unsafe.Pointer(&buf[0])), 0; return *(*uint32)(unsafe.Pointer(&buf[0])), 0
} }
// TODO: wrap // TODO: wrap

View File

@ -4,23 +4,23 @@
package syscall package syscall
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9); ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9); ts.Nsec = int32(nsec % 1e9)
return; return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3); tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int32(nsec / 1e9); tv.Sec = int32(nsec / 1e9)
return; return
} }
//sys gettimeofday(tp *Timeval) (sec int32, usec int32, errno int) //sys gettimeofday(tp *Timeval) (sec int32, usec int32, errno int)
@ -28,14 +28,14 @@ func Gettimeofday(tv *Timeval) (errno int) {
// The tv passed to gettimeofday must be non-nil // The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back // but is otherwise unused. The answers come back
// in the two registers. // in the two registers.
sec, usec, err := gettimeofday(tv); sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec); tv.Sec = int32(sec)
tv.Usec = int32(usec); tv.Usec = int32(usec)
return err; return err
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd); k.Ident = uint32(fd)
k.Filter = int16(mode); k.Filter = int16(mode)
k.Flags = uint16(flags); k.Flags = uint16(flags)
} }

View File

@ -4,23 +4,23 @@
package syscall package syscall
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = nsec / 1e9; ts.Sec = nsec / 1e9
ts.Nsec = nsec % 1e9; ts.Nsec = nsec % 1e9
return; return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3); tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int64(nsec / 1e9); tv.Sec = int64(nsec / 1e9)
return; return
} }
//sys gettimeofday(tp *Timeval) (sec int64, usec int32, errno int) //sys gettimeofday(tp *Timeval) (sec int64, usec int32, errno int)
@ -28,14 +28,14 @@ func Gettimeofday(tv *Timeval) (errno int) {
// The tv passed to gettimeofday must be non-nil // The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back // but is otherwise unused. The answers come back
// in the two registers. // in the two registers.
sec, usec, err := gettimeofday(tv); sec, usec, err := gettimeofday(tv)
tv.Sec = sec; tv.Sec = sec
tv.Usec = usec; tv.Usec = usec
return err; return err
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd); k.Ident = uint64(fd)
k.Filter = int16(mode); k.Filter = int16(mode)
k.Flags = uint16(flags); k.Flags = uint16(flags)
} }

View File

@ -23,7 +23,7 @@ const OS = "freebsd"
// even linking this function into the binary. See ../os/getwd.go. // even linking this function into the binary. See ../os/getwd.go.
const ImplementsGetwd = false const ImplementsGetwd = false
func Getwd() (string, int) { return "", ENOTSUP } func Getwd() (string, int) { return "", ENOTSUP }
/* /*
@ -34,7 +34,7 @@ func Getwd() (string, int) { return "", ENOTSUP }
//sys setgroups(ngid int, gid *_Gid_t) (errno int) //sys setgroups(ngid int, gid *_Gid_t) (errno int)
func Getgroups() (gids []int, errno int) { func Getgroups() (gids []int, errno int) {
n, err := getgroups(0, nil); n, err := getgroups(0, nil)
if err != 0 { if err != 0 {
return nil, errno return nil, errno
} }
@ -47,16 +47,16 @@ func Getgroups() (gids []int, errno int) {
return nil, EINVAL return nil, EINVAL
} }
a := make([]_Gid_t, n); a := make([]_Gid_t, n)
n, err = getgroups(n, &a[0]); n, err = getgroups(n, &a[0])
if err != 0 { if err != 0 {
return nil, errno return nil, errno
} }
gids = make([]int, n); gids = make([]int, n)
for i, v := range a[0:n] { for i, v := range a[0:n] {
gids[i] = int(v) gids[i] = int(v)
} }
return; return
} }
func Setgroups(gids []int) (errno int) { func Setgroups(gids []int) (errno int) {
@ -64,11 +64,11 @@ func Setgroups(gids []int) (errno int) {
return setgroups(0, nil) return setgroups(0, nil)
} }
a := make([]_Gid_t, len(gids)); a := make([]_Gid_t, len(gids))
for i, v := range gids { for i, v := range gids {
a[i] = _Gid_t(v) a[i] = _Gid_t(v)
} }
return setgroups(len(a), &a[0]); return setgroups(len(a), &a[0])
} }
// Wait status is 7 bits at bottom, either 0 (exited), // Wait status is 7 bits at bottom, either 0 (exited),
@ -80,44 +80,44 @@ func Setgroups(gids []int) (errno int) {
type WaitStatus uint32 type WaitStatus uint32
const ( const (
mask = 0x7F; mask = 0x7F
core = 0x80; core = 0x80
shift = 8; shift = 8
exited = 0; exited = 0
stopped = 0x7F; stopped = 0x7F
) )
func (w WaitStatus) Exited() bool { return w&mask == exited } func (w WaitStatus) Exited() bool { return w&mask == exited }
func (w WaitStatus) ExitStatus() int { func (w WaitStatus) ExitStatus() int {
if w&mask != exited { if w&mask != exited {
return -1 return -1
} }
return int(w >> shift); return int(w >> shift)
} }
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
func (w WaitStatus) Signal() int { func (w WaitStatus) Signal() int {
sig := int(w & mask); sig := int(w & mask)
if sig == stopped || sig == 0 { if sig == stopped || sig == 0 {
return -1 return -1
} }
return sig; return sig
} }
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
func (w WaitStatus) Stopped() bool { return w&mask == stopped && w>>shift != SIGSTOP } func (w WaitStatus) Stopped() bool { return w&mask == stopped && w>>shift != SIGSTOP }
func (w WaitStatus) Continued() bool { return w&mask == stopped && w>>shift == SIGSTOP } func (w WaitStatus) Continued() bool { return w&mask == stopped && w>>shift == SIGSTOP }
func (w WaitStatus) StopSignal() int { func (w WaitStatus) StopSignal() int {
if !w.Stopped() { if !w.Stopped() {
return -1 return -1
} }
return int(w>>shift) & 0xFF; return int(w>>shift) & 0xFF
} }
func (w WaitStatus) TrapCause() int { func (w WaitStatus) TrapCause() int {
@ -128,12 +128,12 @@ func (w WaitStatus) TrapCause() int {
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) //sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status _C_int; var status _C_int
wpid, errno = wait4(pid, &status, options, rusage); wpid, errno = wait4(pid, &status, options, rusage)
if wstatus != nil { if wstatus != nil {
*wstatus = WaitStatus(status) *wstatus = WaitStatus(status)
} }
return; return
} }
//sys pipe() (r int, w int, errno int) //sys pipe() (r int, w int, errno int)
@ -142,13 +142,13 @@ func Pipe(p []int) (errno int) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
} }
p[0], p[1], errno = pipe(); p[0], p[1], errno = pipe()
return; return
} }
func Sleep(ns int64) (errno int) { func Sleep(ns int64) (errno int) {
tv := NsecToTimeval(ns); tv := NsecToTimeval(ns)
return Select(0, nil, nil, nil, &tv); return Select(0, nil, nil, nil, &tv)
} }
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
@ -165,173 +165,173 @@ func Sleep(ns int64) (errno int) {
var SocketDisableIPv6 bool var SocketDisableIPv6 bool
type Sockaddr interface { type Sockaddr interface {
sockaddr() (ptr uintptr, len _Socklen, errno int); // lowercase; only we can define Sockaddrs sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
} }
type SockaddrInet4 struct { type SockaddrInet4 struct {
Port int; Port int
Addr [4]byte; Addr [4]byte
raw RawSockaddrInet4; raw RawSockaddrInet4
} }
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
if sa.Port < 0 || sa.Port > 0xFFFF { if sa.Port < 0 || sa.Port > 0xFFFF {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Len = SizeofSockaddrInet4; sa.raw.Len = SizeofSockaddrInet4
sa.raw.Family = AF_INET; sa.raw.Family = AF_INET
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8); p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port); p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i] sa.raw.Addr[i] = sa.Addr[i]
} }
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0; return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
} }
type SockaddrInet6 struct { type SockaddrInet6 struct {
Port int; Port int
Addr [16]byte; Addr [16]byte
raw RawSockaddrInet6; raw RawSockaddrInet6
} }
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
if sa.Port < 0 || sa.Port > 0xFFFF { if sa.Port < 0 || sa.Port > 0xFFFF {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Len = SizeofSockaddrInet6; sa.raw.Len = SizeofSockaddrInet6
sa.raw.Family = AF_INET6; sa.raw.Family = AF_INET6
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8); p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port); p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i] sa.raw.Addr[i] = sa.Addr[i]
} }
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0; return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
} }
type SockaddrUnix struct { type SockaddrUnix struct {
Name string; Name string
raw RawSockaddrUnix; raw RawSockaddrUnix
} }
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
name := sa.Name; name := sa.Name
n := len(name); n := len(name)
if n >= len(sa.raw.Path) || n == 0 { if n >= len(sa.raw.Path) || n == 0 {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
sa.raw.Family = AF_UNIX; sa.raw.Family = AF_UNIX
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i]) sa.raw.Path[i] = int8(name[i])
} }
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0; return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
} }
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) { func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_UNIX: case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)); pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
if pp.Len < 3 || pp.Len > SizeofSockaddrUnix { if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
return nil, EINVAL return nil, EINVAL
} }
sa := new(SockaddrUnix); sa := new(SockaddrUnix)
n := int(pp.Len) - 3; // subtract leading Family, Len, terminating NUL n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if pp.Path[i] == 0 { if pp.Path[i] == 0 {
// found early NUL; assume Len is overestimating // found early NUL; assume Len is overestimating
n = i; n = i
break; break
} }
} }
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0])); bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
sa.Name = string(bytes[0:n]); sa.Name = string(bytes[0:n])
return sa, 0; return sa, 0
case AF_INET: case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)); pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4); sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)); p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]); sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, 0; return sa, 0
case AF_INET6: case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)); pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6); sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)); p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]); sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, 0; return sa, 0
} }
return nil, EAFNOSUPPORT; return nil, EAFNOSUPPORT
} }
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
nfd, errno = accept(fd, &rsa, &len); nfd, errno = accept(fd, &rsa, &len)
if errno != 0 { if errno != 0 {
return return
} }
sa, errno = anyToSockaddr(&rsa); sa, errno = anyToSockaddr(&rsa)
if errno != 0 { if errno != 0 {
Close(nfd); Close(nfd)
nfd = 0; nfd = 0
} }
return; return
} }
func Getsockname(fd int) (sa Sockaddr, errno int) { func Getsockname(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if errno = getsockname(fd, &rsa, &len); errno != 0 { if errno = getsockname(fd, &rsa, &len); errno != 0 {
return return
} }
return anyToSockaddr(&rsa); return anyToSockaddr(&rsa)
} }
func Getpeername(fd int) (sa Sockaddr, errno int) { func Getpeername(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if errno = getpeername(fd, &rsa, &len); errno != 0 { if errno = getpeername(fd, &rsa, &len); errno != 0 {
return return
} }
return anyToSockaddr(&rsa); return anyToSockaddr(&rsa)
} }
func Bind(fd int, sa Sockaddr) (errno int) { func Bind(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr(); ptr, n, err := sa.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return bind(fd, ptr, n); return bind(fd, ptr, n)
} }
func Connect(fd int, sa Sockaddr) (errno int) { func Connect(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr(); ptr, n, err := sa.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return connect(fd, ptr, n); return connect(fd, ptr, n)
} }
func Socket(domain, typ, proto int) (fd, errno int) { func Socket(domain, typ, proto int) (fd, errno int) {
if domain == AF_INET6 && SocketDisableIPv6 { if domain == AF_INET6 && SocketDisableIPv6 {
return -1, EAFNOSUPPORT return -1, EAFNOSUPPORT
} }
fd, errno = socket(domain, typ, proto); fd, errno = socket(domain, typ, proto)
return; return
} }
func SetsockoptInt(fd, level, opt int, value int) (errno int) { func SetsockoptInt(fd, level, opt int, value int) (errno int) {
var n = int32(value); var n = int32(value)
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4); return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
} }
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) { func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
@ -346,44 +346,44 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) { func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 { if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
return return
} }
from, errno = anyToSockaddr(&rsa); from, errno = anyToSockaddr(&rsa)
return; return
} }
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) //sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) { func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
ptr, n, err := to.sockaddr(); ptr, n, err := to.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return sendto(fd, p, flags, ptr, n); return sendto(fd, p, flags, ptr, n)
} }
//sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) //sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) { func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
var change, event uintptr; var change, event uintptr
if len(changes) > 0 { if len(changes) > 0 {
change = uintptr(unsafe.Pointer(&changes[0])) change = uintptr(unsafe.Pointer(&changes[0]))
} }
if len(events) > 0 { if len(events) > 0 {
event = uintptr(unsafe.Pointer(&events[0])) event = uintptr(unsafe.Pointer(&events[0]))
} }
return kevent(kq, change, len(changes), event, len(events), timeout); return kevent(kq, change, len(changes), event, len(events), timeout)
} }
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
// Translate "kern.hostname" to []_C_int{0,1,2,3}. // Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, errno int) { func nametomib(name string) (mib []_C_int, errno int) {
const CTL_MAXNAME = 12; const CTL_MAXNAME = 12
const siz = uintptr(unsafe.Sizeof(mib[0])); const siz = uintptr(unsafe.Sizeof(mib[0]))
// NOTE(rsc): It seems strange to set the buffer to have // NOTE(rsc): It seems strange to set the buffer to have
// size CTL_MAXNAME+2 but use only CTL_MAXNAME // size CTL_MAXNAME+2 but use only CTL_MAXNAME
@ -392,29 +392,29 @@ func nametomib(name string) (mib []_C_int, errno int) {
// I am scared that if we don't include the +2 here, the kernel // I am scared that if we don't include the +2 here, the kernel
// will silently write 2 words farther than we specify // will silently write 2 words farther than we specify
// and we'll get memory corruption. // and we'll get memory corruption.
var buf [CTL_MAXNAME + 2]_C_int; var buf [CTL_MAXNAME + 2]_C_int
n := uintptr(CTL_MAXNAME) * siz; n := uintptr(CTL_MAXNAME) * siz
p := (*byte)(unsafe.Pointer(&buf[0])); p := (*byte)(unsafe.Pointer(&buf[0]))
bytes := StringByteSlice(name); bytes := StringByteSlice(name)
// Magic sysctl: "setting" 0.3 to a string name // Magic sysctl: "setting" 0.3 to a string name
// lets you read back the array of integers form. // lets you read back the array of integers form.
if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 { if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
return nil, errno return nil, errno
} }
return buf[0 : n/siz], 0; return buf[0 : n/siz], 0
} }
func Sysctl(name string) (value string, errno int) { func Sysctl(name string) (value string, errno int) {
// Translate name to mib number. // Translate name to mib number.
mib, errno := nametomib(name); mib, errno := nametomib(name)
if errno != 0 { if errno != 0 {
return "", errno return "", errno
} }
// Find size. // Find size.
n := uintptr(0); n := uintptr(0)
if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 { if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
return "", errno return "", errno
} }
@ -423,7 +423,7 @@ func Sysctl(name string) (value string, errno int) {
} }
// Read into buffer of that size. // Read into buffer of that size.
buf := make([]byte, n); buf := make([]byte, n)
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 { if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
return "", errno return "", errno
} }
@ -432,26 +432,26 @@ func Sysctl(name string) (value string, errno int) {
if n > 0 && buf[n-1] == '\x00' { if n > 0 && buf[n-1] == '\x00' {
n-- n--
} }
return string(buf[0:n]), 0; return string(buf[0:n]), 0
} }
func SysctlUint32(name string) (value uint32, errno int) { func SysctlUint32(name string) (value uint32, errno int) {
// Translate name to mib number. // Translate name to mib number.
mib, errno := nametomib(name); mib, errno := nametomib(name)
if errno != 0 { if errno != 0 {
return 0, errno return 0, errno
} }
// Read into buffer of that size. // Read into buffer of that size.
n := uintptr(4); n := uintptr(4)
buf := make([]byte, 4); buf := make([]byte, 4)
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 { if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
return 0, errno return 0, errno
} }
if n != 4 { if n != 4 {
return 0, EIO return 0, EIO
} }
return *(*uint32)(unsafe.Pointer(&buf[0])), 0; return *(*uint32)(unsafe.Pointer(&buf[0])), 0
} }
// TODO: wrap // TODO: wrap

View File

@ -4,27 +4,27 @@
package syscall package syscall
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9); ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9); ts.Nsec = int32(nsec % 1e9)
return; return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3); tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int32(nsec / 1e9); tv.Sec = int32(nsec / 1e9)
return; return
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd); k.Ident = uint32(fd)
k.Filter = int16(mode); k.Filter = int16(mode)
k.Flags = uint16(flags); k.Flags = uint16(flags)
} }

View File

@ -4,27 +4,27 @@
package syscall package syscall
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = nsec / 1e9; ts.Sec = nsec / 1e9
ts.Nsec = nsec % 1e9; ts.Nsec = nsec % 1e9
return; return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = nsec % 1e9 / 1e3; tv.Usec = nsec % 1e9 / 1e3
tv.Sec = int64(nsec / 1e9); tv.Sec = int64(nsec / 1e9)
return; return
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd); k.Ident = uint64(fd)
k.Filter = int16(mode); k.Filter = int16(mode)
k.Flags = uint16(flags); k.Flags = uint16(flags)
} }

View File

@ -24,11 +24,11 @@ func Pipe(p []int) (errno int) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
} }
var pp [2]_C_int; var pp [2]_C_int
errno = pipe(&pp); errno = pipe(&pp)
p[0] = int(pp[0]); p[0] = int(pp[0])
p[1] = int(pp[1]); p[1] = int(pp[1])
return; return
} }
//sys utimes(path string, times *[2]Timeval) (errno int) //sys utimes(path string, times *[2]Timeval) (errno int)
@ -36,7 +36,7 @@ func Utimes(path string, tv []Timeval) (errno int) {
if len(tv) != 2 { if len(tv) != 2 {
return EINVAL return EINVAL
} }
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))); return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
} }
//sys futimesat(dirfd int, path string, times *[2]Timeval) (errno int) //sys futimesat(dirfd int, path string, times *[2]Timeval) (errno int)
@ -44,15 +44,15 @@ func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
if len(tv) != 2 { if len(tv) != 2 {
return EINVAL return EINVAL
} }
return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))); return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
} }
const ImplementsGetwd = true const ImplementsGetwd = true
//sys Getcwd(buf []byte) (n int, errno int) //sys Getcwd(buf []byte) (n int, errno int)
func Getwd() (wd string, errno int) { func Getwd() (wd string, errno int) {
var buf [PathMax]byte; var buf [PathMax]byte
n, err := Getcwd(&buf); n, err := Getcwd(&buf)
if err != 0 { if err != 0 {
return "", err return "", err
} }
@ -60,11 +60,11 @@ func Getwd() (wd string, errno int) {
if n < 1 || n > len(buf) || buf[n-1] != 0 { if n < 1 || n > len(buf) || buf[n-1] != 0 {
return "", EINVAL return "", EINVAL
} }
return string(buf[0 : n-1]), 0; return string(buf[0 : n-1]), 0
} }
func Getgroups() (gids []int, errno int) { func Getgroups() (gids []int, errno int) {
n, err := getgroups(0, nil); n, err := getgroups(0, nil)
if err != 0 { if err != 0 {
return nil, errno return nil, errno
} }
@ -77,16 +77,16 @@ func Getgroups() (gids []int, errno int) {
return nil, EINVAL return nil, EINVAL
} }
a := make([]_Gid_t, n); a := make([]_Gid_t, n)
n, err = getgroups(n, &a[0]); n, err = getgroups(n, &a[0])
if err != 0 { if err != 0 {
return nil, errno return nil, errno
} }
gids = make([]int, n); gids = make([]int, n)
for i, v := range a[0:n] { for i, v := range a[0:n] {
gids[i] = int(v) gids[i] = int(v)
} }
return; return
} }
func Setgroups(gids []int) (errno int) { func Setgroups(gids []int) (errno int) {
@ -94,11 +94,11 @@ func Setgroups(gids []int) (errno int) {
return setgroups(0, nil) return setgroups(0, nil)
} }
a := make([]_Gid_t, len(gids)); a := make([]_Gid_t, len(gids))
for i, v := range gids { for i, v := range gids {
a[i] = _Gid_t(v) a[i] = _Gid_t(v)
} }
return setgroups(len(a), &a[0]); return setgroups(len(a), &a[0])
} }
type WaitStatus uint32 type WaitStatus uint32
@ -113,65 +113,65 @@ type WaitStatus uint32
// from stopped via the core dump bit. // from stopped via the core dump bit.
const ( const (
mask = 0x7F; mask = 0x7F
core = 0x80; core = 0x80
exited = 0x00; exited = 0x00
stopped = 0x7F; stopped = 0x7F
shift = 8; shift = 8
) )
func (w WaitStatus) Exited() bool { return w&mask == exited } func (w WaitStatus) Exited() bool { return w&mask == exited }
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
func (w WaitStatus) Continued() bool { return w == 0xFFFF } func (w WaitStatus) Continued() bool { return w == 0xFFFF }
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
func (w WaitStatus) ExitStatus() int { func (w WaitStatus) ExitStatus() int {
if !w.Exited() { if !w.Exited() {
return -1 return -1
} }
return int(w>>shift) & 0xFF; return int(w>>shift) & 0xFF
} }
func (w WaitStatus) Signal() int { func (w WaitStatus) Signal() int {
if !w.Signaled() { if !w.Signaled() {
return -1 return -1
} }
return int(w & mask); return int(w & mask)
} }
func (w WaitStatus) StopSignal() int { func (w WaitStatus) StopSignal() int {
if !w.Stopped() { if !w.Stopped() {
return -1 return -1
} }
return int(w>>shift) & 0xFF; return int(w>>shift) & 0xFF
} }
func (w WaitStatus) TrapCause() int { func (w WaitStatus) TrapCause() int {
if w.StopSignal() != SIGTRAP { if w.StopSignal() != SIGTRAP {
return -1 return -1
} }
return int(w>>shift) >> 8; return int(w>>shift) >> 8
} }
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) //sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status _C_int; var status _C_int
wpid, errno = wait4(pid, &status, options, rusage); wpid, errno = wait4(pid, &status, options, rusage)
if wstatus != nil { if wstatus != nil {
*wstatus = WaitStatus(status) *wstatus = WaitStatus(status)
} }
return; return
} }
func Sleep(nsec int64) (errno int) { func Sleep(nsec int64) (errno int) {
tv := NsecToTimeval(nsec); tv := NsecToTimeval(nsec)
_, err := Select(0, nil, nil, nil, &tv); _, err := Select(0, nil, nil, nil, &tv)
return err; return err
} }
// For testing: clients can set this flag to force // For testing: clients can set this flag to force
@ -179,61 +179,61 @@ func Sleep(nsec int64) (errno int) {
var SocketDisableIPv6 bool var SocketDisableIPv6 bool
type Sockaddr interface { type Sockaddr interface {
sockaddr() (ptr uintptr, len _Socklen, errno int); // lowercase; only we can define Sockaddrs sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
} }
type SockaddrInet4 struct { type SockaddrInet4 struct {
Port int; Port int
Addr [4]byte; Addr [4]byte
raw RawSockaddrInet4; raw RawSockaddrInet4
} }
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
if sa.Port < 0 || sa.Port > 0xFFFF { if sa.Port < 0 || sa.Port > 0xFFFF {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Family = AF_INET; sa.raw.Family = AF_INET
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8); p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port); p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i] sa.raw.Addr[i] = sa.Addr[i]
} }
return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0; return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0
} }
type SockaddrInet6 struct { type SockaddrInet6 struct {
Port int; Port int
Addr [16]byte; Addr [16]byte
raw RawSockaddrInet6; raw RawSockaddrInet6
} }
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
if sa.Port < 0 || sa.Port > 0xFFFF { if sa.Port < 0 || sa.Port > 0xFFFF {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Family = AF_INET6; sa.raw.Family = AF_INET6
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8); p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port); p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i] sa.raw.Addr[i] = sa.Addr[i]
} }
return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0; return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0
} }
type SockaddrUnix struct { type SockaddrUnix struct {
Name string; Name string
raw RawSockaddrUnix; raw RawSockaddrUnix
} }
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) { func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
name := sa.Name; name := sa.Name
n := len(name); n := len(name)
if n >= len(sa.raw.Path) || n == 0 { if n >= len(sa.raw.Path) || n == 0 {
return 0, 0, EINVAL return 0, 0, EINVAL
} }
sa.raw.Family = AF_UNIX; sa.raw.Family = AF_UNIX
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i]) sa.raw.Path[i] = int8(name[i])
} }
@ -242,14 +242,14 @@ func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
} }
// length is family, name, NUL. // length is family, name, NUL.
return uintptr(unsafe.Pointer(&sa.raw)), 1 + _Socklen(n) + 1, 0; return uintptr(unsafe.Pointer(&sa.raw)), 1 + _Socklen(n) + 1, 0
} }
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) { func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_UNIX: case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)); pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
sa := new(SockaddrUnix); sa := new(SockaddrUnix)
if pp.Path[0] == 0 { if pp.Path[0] == 0 {
// "Abstract" Unix domain socket. // "Abstract" Unix domain socket.
// Rewrite leading NUL as @ for textual display. // Rewrite leading NUL as @ for textual display.
@ -264,97 +264,97 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
// abstract Unix domain sockets--they are supposed // abstract Unix domain sockets--they are supposed
// to be uninterpreted fixed-size binary blobs--but // to be uninterpreted fixed-size binary blobs--but
// everyone uses this convention. // everyone uses this convention.
n := 0; n := 0
for n < len(pp.Path) && pp.Path[n] != 0 { for n < len(pp.Path) && pp.Path[n] != 0 {
n++ n++
} }
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0])); bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
sa.Name = string(bytes[0:n]); sa.Name = string(bytes[0:n])
return sa, 0; return sa, 0
case AF_INET: case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)); pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4); sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)); p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]); sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, 0; return sa, 0
case AF_INET6: case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)); pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6); sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)); p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]); sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i] sa.Addr[i] = pp.Addr[i]
} }
return sa, 0; return sa, 0
} }
return nil, EAFNOSUPPORT; return nil, EAFNOSUPPORT
} }
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
nfd, errno = accept(fd, &rsa, &len); nfd, errno = accept(fd, &rsa, &len)
if errno != 0 { if errno != 0 {
return return
} }
sa, errno = anyToSockaddr(&rsa); sa, errno = anyToSockaddr(&rsa)
if errno != 0 { if errno != 0 {
Close(nfd); Close(nfd)
nfd = 0; nfd = 0
} }
return; return
} }
func Getsockname(fd int) (sa Sockaddr, errno int) { func Getsockname(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if errno = getsockname(fd, &rsa, &len); errno != 0 { if errno = getsockname(fd, &rsa, &len); errno != 0 {
return return
} }
return anyToSockaddr(&rsa); return anyToSockaddr(&rsa)
} }
func Getpeername(fd int) (sa Sockaddr, errno int) { func Getpeername(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if errno = getpeername(fd, &rsa, &len); errno != 0 { if errno = getpeername(fd, &rsa, &len); errno != 0 {
return return
} }
return anyToSockaddr(&rsa); return anyToSockaddr(&rsa)
} }
func Bind(fd int, sa Sockaddr) (errno int) { func Bind(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr(); ptr, n, err := sa.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return bind(fd, ptr, n); return bind(fd, ptr, n)
} }
func Connect(fd int, sa Sockaddr) (errno int) { func Connect(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr(); ptr, n, err := sa.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return connect(fd, ptr, n); return connect(fd, ptr, n)
} }
func Socket(domain, typ, proto int) (fd, errno int) { func Socket(domain, typ, proto int) (fd, errno int) {
if domain == AF_INET6 && SocketDisableIPv6 { if domain == AF_INET6 && SocketDisableIPv6 {
return -1, EAFNOSUPPORT return -1, EAFNOSUPPORT
} }
fd, errno = socket(domain, typ, proto); fd, errno = socket(domain, typ, proto)
return; return
} }
func SetsockoptInt(fd, level, opt int, value int) (errno int) { func SetsockoptInt(fd, level, opt int, value int) (errno int) {
var n = int32(value); var n = int32(value)
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4); return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
} }
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) { func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
@ -366,21 +366,21 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
} }
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) { func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
var rsa RawSockaddrAny; var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny; var len _Socklen = SizeofSockaddrAny
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 { if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
return return
} }
from, errno = anyToSockaddr(&rsa); from, errno = anyToSockaddr(&rsa)
return; return
} }
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) { func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
ptr, n, err := to.sockaddr(); ptr, n, err := to.sockaddr()
if err != 0 { if err != 0 {
return err return err
} }
return sendto(fd, p, flags, ptr, n); return sendto(fd, p, flags, ptr, n)
} }
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int) //sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
@ -392,37 +392,37 @@ func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno in
// The ptrace syscall differs from glibc's ptrace. // The ptrace syscall differs from glibc's ptrace.
// Peeks returns the word in *data, not as the return value. // Peeks returns the word in *data, not as the return value.
var buf [sizeofPtr]byte; var buf [sizeofPtr]byte
// Leading edge. PEEKTEXT/PEEKDATA don't require aligned // Leading edge. PEEKTEXT/PEEKDATA don't require aligned
// access (PEEKUSER warns that it might), but if we don't // access (PEEKUSER warns that it might), but if we don't
// align our reads, we might straddle an unmapped page // align our reads, we might straddle an unmapped page
// boundary and not get the bytes leading up to the page // boundary and not get the bytes leading up to the page
// boundary. // boundary.
n := 0; n := 0
if addr%sizeofPtr != 0 { if addr%sizeofPtr != 0 {
errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0]))); errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 { if errno != 0 {
return 0, errno return 0, errno
} }
n += copy(out, buf[addr%sizeofPtr:]); n += copy(out, buf[addr%sizeofPtr:])
out = out[n:]; out = out[n:]
} }
// Remainder. // Remainder.
for len(out) > 0 { for len(out) > 0 {
// We use an internal buffer to gaurantee alignment. // We use an internal buffer to gaurantee alignment.
// It's not documented if this is necessary, but we're paranoid. // It's not documented if this is necessary, but we're paranoid.
errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))); errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 { if errno != 0 {
return n, errno return n, errno
} }
copied := copy(out, &buf); copied := copy(out, &buf)
n += copied; n += copied
out = out[copied:]; out = out[copied:]
} }
return n, 0; return n, 0
} }
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) { func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
@ -438,50 +438,50 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c
// with the possibility of straddling an invalid page. // with the possibility of straddling an invalid page.
// Leading edge. // Leading edge.
n := 0; n := 0
if addr%sizeofPtr != 0 { if addr%sizeofPtr != 0 {
var buf [sizeofPtr]byte; var buf [sizeofPtr]byte
errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0]))); errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 { if errno != 0 {
return 0, errno return 0, errno
} }
n += copy(buf[addr%sizeofPtr:], data); n += copy(buf[addr%sizeofPtr:], data)
word := *((*uintptr)(unsafe.Pointer(&buf[0]))); word := *((*uintptr)(unsafe.Pointer(&buf[0])))
errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word); errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
if errno != 0 { if errno != 0 {
return 0, errno return 0, errno
} }
data = data[n:]; data = data[n:]
} }
// Interior. // Interior.
for len(data) > sizeofPtr { for len(data) > sizeofPtr {
word := *((*uintptr)(unsafe.Pointer(&data[0]))); word := *((*uintptr)(unsafe.Pointer(&data[0])))
errno = ptrace(pokeReq, pid, addr+uintptr(n), word); errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
if errno != 0 { if errno != 0 {
return n, errno return n, errno
} }
n += sizeofPtr; n += sizeofPtr
data = data[sizeofPtr:]; data = data[sizeofPtr:]
} }
// Trailing edge. // Trailing edge.
if len(data) > 0 { if len(data) > 0 {
var buf [sizeofPtr]byte; var buf [sizeofPtr]byte
errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))); errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 { if errno != 0 {
return n, errno return n, errno
} }
copy(&buf, data); copy(&buf, data)
word := *((*uintptr)(unsafe.Pointer(&buf[0]))); word := *((*uintptr)(unsafe.Pointer(&buf[0])))
errno = ptrace(pokeReq, pid, addr+uintptr(n), word); errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
if errno != 0 { if errno != 0 {
return n, errno return n, errno
} }
n += len(data); n += len(data)
} }
return n, 0; return n, 0
} }
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) { func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
@ -505,21 +505,21 @@ func PtraceSetOptions(pid int, options int) (errno int) {
} }
func PtraceGetEventMsg(pid int) (msg uint, errno int) { func PtraceGetEventMsg(pid int) (msg uint, errno int) {
var data _C_long; var data _C_long
errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data))); errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
msg = uint(data); msg = uint(data)
return; return
} }
func PtraceCont(pid int, signal int) (errno int) { func PtraceCont(pid int, signal int) (errno int) {
return ptrace(PTRACE_CONT, pid, 0, uintptr(signal)) return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
} }
func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) } func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
// Sendto // Sendto
// Recvfrom // Recvfrom

View File

@ -6,23 +6,23 @@ package syscall
import "unsafe" import "unsafe"
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9); ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9); ts.Nsec = int32(nsec % 1e9)
return; return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = int32(nsec / 1e9); tv.Sec = int32(nsec / 1e9)
tv.Usec = int32(nsec % 1e9 / 1e3); tv.Usec = int32(nsec % 1e9 / 1e3)
return; return
} }
// 64-bit file system and 32-bit uid calls // 64-bit file system and 32-bit uid calls
@ -64,102 +64,102 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
const ( const (
// see linux/net.h // see linux/net.h
_SOCKET = 1; _SOCKET = 1
_BIND = 2; _BIND = 2
_CONNECT = 3; _CONNECT = 3
_LISTEN = 4; _LISTEN = 4
_ACCEPT = 5; _ACCEPT = 5
_GETSOCKNAME = 6; _GETSOCKNAME = 6
_GETPEERNAME = 7; _GETPEERNAME = 7
_SOCKETPAIR = 8; _SOCKETPAIR = 8
_SEND = 9; _SEND = 9
_RECV = 10; _RECV = 10
_SENDTO = 11; _SENDTO = 11
_RECVFROM = 12; _RECVFROM = 12
_SHUTDOWN = 13; _SHUTDOWN = 13
_SETSOCKOPT = 14; _SETSOCKOPT = 14
_GETSOCKOPT = 15; _GETSOCKOPT = 15
_SENDMSG = 16; _SENDMSG = 16
_RECVMSG = 17; _RECVMSG = 17
) )
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int) func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) { func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
fd, errno = socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0); fd, errno = socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
return; return
} }
func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) { func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
_, errno = socketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0); _, errno = socketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
return; return
} }
func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) { func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
_, errno = socketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0); _, errno = socketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
return; return
} }
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) { func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
_, errno = socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0); _, errno = socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
return; return
} }
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) { func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
_, errno = socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0); _, errno = socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
return; return
} }
func socket(domain int, typ int, proto int) (fd int, errno int) { func socket(domain int, typ int, proto int) (fd int, errno int) {
fd, errno = socketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0); fd, errno = socketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
return; return
} }
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) { func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
_, errno = socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0); _, errno = socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
return; return
} }
func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) { func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
var base uintptr; var base uintptr
if len(p) > 0 { if len(p) > 0 {
base = uintptr(unsafe.Pointer(&p[0])) base = uintptr(unsafe.Pointer(&p[0]))
} }
n, errno = socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))); n, errno = socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
return; return
} }
func sendto(s int, p []byte, flags int, to uintptr, addrlen _Socklen) (errno int) { func sendto(s int, p []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
var base uintptr; var base uintptr
if len(p) > 0 { if len(p) > 0 {
base = uintptr(unsafe.Pointer(&p[0])) base = uintptr(unsafe.Pointer(&p[0]))
} }
_, errno = socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), to, uintptr(addrlen)); _, errno = socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), to, uintptr(addrlen))
return; return
} }
func Listen(s int, n int) (errno int) { func Listen(s int, n int) (errno int) {
_, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0); _, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0)
return; return
} }
func Shutdown(s, how int) (errno int) { func Shutdown(s, how int) (errno int) {
_, errno = socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0); _, errno = socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0)
return; return
} }
func Fstatfs(fd int, buf *Statfs_t) (errno int) { func Fstatfs(fd int, buf *Statfs_t) (errno int) {
_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf))); _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf)))
errno = int(e1); errno = int(e1)
return; return
} }
func Statfs(path string, buf *Statfs_t) (errno int) { func Statfs(path string, buf *Statfs_t) (errno int) {
_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf))); _, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf)))
errno = int(e1); errno = int(e1)
return; return
} }
func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) } func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) }
func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) } func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) }

View File

@ -42,25 +42,25 @@ package syscall
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) //sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = nsec / 1e9; ts.Sec = nsec / 1e9
ts.Nsec = nsec % 1e9; ts.Nsec = nsec % 1e9
return; return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = nsec / 1e9; tv.Sec = nsec / 1e9
tv.Usec = nsec % 1e9 / 1e3; tv.Usec = nsec % 1e9 / 1e3
return; return
} }
func (r *PtraceRegs) PC() uint64 { return r.Rip } func (r *PtraceRegs) PC() uint64 { return r.Rip }
func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc }

View File

@ -4,21 +4,21 @@
package syscall package syscall
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9); ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9); ts.Nsec = int32(nsec % 1e9)
return; return
} }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999; // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = int32(nsec / 1e9); tv.Sec = int32(nsec / 1e9)
tv.Usec = int32(nsec % 1e9 / 1e3); tv.Usec = int32(nsec % 1e9 / 1e3)
return; return
} }
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
@ -58,6 +58,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
//sys Statfs(path string, buf *Statfs_t) (errno int) //sys Statfs(path string, buf *Statfs_t) (errno int)
// TODO(kaib): add support for tracing // TODO(kaib): add support for tracing
func (r *PtraceRegs) PC() uint64 { return 0 } func (r *PtraceRegs) PC() uint64 { return 0 }
func (r *PtraceRegs) SetPC(pc uint64) {} func (r *PtraceRegs) SetPC(pc uint64) {}

View File

@ -54,8 +54,8 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
if int64(int32(offset)) != offset { if int64(int32(offset)) != offset {
return 0, ERANGE return 0, ERANGE
} }
o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence)); o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
return int64(o), int(e); return int64(o), int(e)
} }
// Sleep by waiting on a condition variable that will never be signaled. // Sleep by waiting on a condition variable that will never be signaled.
@ -63,34 +63,34 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
var tcv, tmu int var tcv, tmu int
func init() { func init() {
tmu, _ = MutexCreate(); tmu, _ = MutexCreate()
tcv, _ = CondCreate(); tcv, _ = CondCreate()
} }
func Sleep(ns int64) (errno int) { func Sleep(ns int64) (errno int) {
ts := NsecToTimespec(ns); ts := NsecToTimespec(ns)
var tv Timeval; var tv Timeval
if errno = Gettimeofday(&tv); errno != 0 { if errno = Gettimeofday(&tv); errno != 0 {
return return
} }
ts.Sec += tv.Sec; ts.Sec += tv.Sec
ts.Nsec += tv.Usec * 1000; ts.Nsec += tv.Usec * 1000
switch { switch {
case ts.Nsec >= 1e9: case ts.Nsec >= 1e9:
ts.Nsec -= 1e9; ts.Nsec -= 1e9
ts.Sec++; ts.Sec++
case ts.Nsec <= -1e9: case ts.Nsec <= -1e9:
ts.Nsec += 1e9; ts.Nsec += 1e9
ts.Sec--; ts.Sec--
} }
if errno = MutexLock(tmu); errno != 0 { if errno = MutexLock(tmu); errno != 0 {
return return
} }
errno = CondTimedWaitAbs(tcv, tmu, &ts); errno = CondTimedWaitAbs(tcv, tmu, &ts)
if e := MutexUnlock(tmu); e != 0 && errno == 0 { if e := MutexUnlock(tmu); e != 0 && errno == 0 {
errno = e errno = e
} }
return; return
} }
// Implemented in NaCl but not here; maybe later: // Implemented in NaCl but not here; maybe later:
@ -111,10 +111,10 @@ func Sleep(ns int64) (errno int) {
// Not implemented in NaCl but needed to compile other packages. // Not implemented in NaCl but needed to compile other packages.
const ( const (
SIGTRAP = 5; SIGTRAP = 5
) )
func Pipe(p []int) (errno int) { return ENACL } func Pipe(p []int) (errno int) { return ENACL }
func fcntl(fd, cmd, arg int) (val int, errno int) { func fcntl(fd, cmd, arg int) (val int, errno int) {
return 0, ENACL return 0, ENACL
@ -128,25 +128,25 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
return 0, ENACL return 0, ENACL
} }
func Mkdir(path string, mode int) (errno int) { return ENACL } func Mkdir(path string, mode int) (errno int) { return ENACL }
func Lstat(path string, stat *Stat_t) (errno int) { func Lstat(path string, stat *Stat_t) (errno int) {
return ENACL return ENACL
} }
func Chdir(path string) (errno int) { return ENACL } func Chdir(path string) (errno int) { return ENACL }
func Fchdir(fd int) (errno int) { return ENACL } func Fchdir(fd int) (errno int) { return ENACL }
func Unlink(path string) (errno int) { return ENACL } func Unlink(path string) (errno int) { return ENACL }
func Rmdir(path string) (errno int) { return ENACL } func Rmdir(path string) (errno int) { return ENACL }
func Link(oldpath, newpath string) (errno int) { func Link(oldpath, newpath string) (errno int) {
return ENACL return ENACL
} }
func Symlink(path, link string) (errno int) { return ENACL } func Symlink(path, link string) (errno int) { return ENACL }
func Readlink(path string, buf []byte) (n int, errno int) { func Readlink(path string, buf []byte) (n int, errno int) {
return 0, ENACL return 0, ENACL
@ -156,7 +156,7 @@ func Rename(oldpath, newpath string) (errno int) {
return ENACL return ENACL
} }
func Fchmod(fd int, mode int) (errno int) { return ENACL } func Fchmod(fd int, mode int) (errno int) { return ENACL }
func Chown(path string, uid int, gid int) (errno int) { func Chown(path string, uid int, gid int) (errno int) {
return ENACL return ENACL
@ -184,65 +184,65 @@ func Ftruncate(fd int, length int64) (errno int) {
const ImplementsGetwd = true const ImplementsGetwd = true
func Getwd() (wd string, errno int) { return "", ENACL } func Getwd() (wd string, errno int) { return "", ENACL }
func Getuid() (uid int) { return -1 } func Getuid() (uid int) { return -1 }
func Geteuid() (euid int) { return -1 } func Geteuid() (euid int) { return -1 }
func Getgid() (gid int) { return -1 } func Getgid() (gid int) { return -1 }
func Getegid() (egid int) { return -1 } func Getegid() (egid int) { return -1 }
func Getppid() (ppid int) { return -1 } func Getppid() (ppid int) { return -1 }
func Getgroups() (gids []int, errno int) { return nil, ENACL } func Getgroups() (gids []int, errno int) { return nil, ENACL }
type Sockaddr interface { type Sockaddr interface {
sockaddr(); sockaddr()
} }
type SockaddrInet4 struct { type SockaddrInet4 struct {
Port int; Port int
Addr [4]byte; Addr [4]byte
} }
func (*SockaddrInet4) sockaddr() {} func (*SockaddrInet4) sockaddr() {}
type SockaddrInet6 struct { type SockaddrInet6 struct {
Port int; Port int
Addr [16]byte; Addr [16]byte
} }
func (*SockaddrInet6) sockaddr() {} func (*SockaddrInet6) sockaddr() {}
type SockaddrUnix struct { type SockaddrUnix struct {
Name string; Name string
} }
func (*SockaddrUnix) sockaddr() {} func (*SockaddrUnix) sockaddr() {}
const ( const (
AF_INET = 1 + iota; AF_INET = 1 + iota
AF_INET6; AF_INET6
AF_UNIX; AF_UNIX
IPPROTO_TCP; IPPROTO_TCP
SOCK_DGRAM; SOCK_DGRAM
SOCK_STREAM; SOCK_STREAM
SOL_SOCKET; SOL_SOCKET
SOMAXCONN; SOMAXCONN
SO_DONTROUTE; SO_DONTROUTE
SO_KEEPALIVE; SO_KEEPALIVE
SO_LINGER; SO_LINGER
SO_RCVBUF; SO_RCVBUF
SO_REUSEADDR; SO_REUSEADDR
SO_SNDBUF; SO_SNDBUF
TCP_NODELAY; TCP_NODELAY
WNOHANG; WNOHANG
WSTOPPED; WSTOPPED
PTRACE_TRACEME; PTRACE_TRACEME
SO_BROADCAST = 0; SO_BROADCAST = 0
SHUT_RDWR = 0; SHUT_RDWR = 0
) )
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
@ -257,9 +257,9 @@ func Getpeername(fd int) (sa Sockaddr, errno int) {
return nil, ENACL return nil, ENACL
} }
func Bind(fd int, sa Sockaddr) (errno int) { return ENACL } func Bind(fd int, sa Sockaddr) (errno int) { return ENACL }
func Connect(fd int, sa Sockaddr) (errno int) { return ENACL } func Connect(fd int, sa Sockaddr) (errno int) { return ENACL }
func Socket(domain, typ, proto int) (fd, errno int) { func Socket(domain, typ, proto int) (fd, errno int) {
return 0, ENACL return 0, ENACL
@ -269,7 +269,7 @@ func SetsockoptInt(fd, level, opt int, value int) (errno int) {
return ENACL return ENACL
} }
func Shutdown(fd, how int) (errno int) { return ENACL } func Shutdown(fd, how int) (errno int) { return ENACL }
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) { func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
return 0, nil, ENACL return 0, nil, ENACL
@ -284,33 +284,33 @@ func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
} }
type Linger struct { type Linger struct {
Onoff int32; Onoff int32
Linger int32; Linger int32
} }
func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) { func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
return ENACL return ENACL
} }
func Listen(s int, n int) (errno int) { return ENACL } func Listen(s int, n int) (errno int) { return ENACL }
type Rusage struct { type Rusage struct {
Utime Timeval; Utime Timeval
Stime Timeval; Stime Timeval
Maxrss int32; Maxrss int32
Ixrss int32; Ixrss int32
Idrss int32; Idrss int32
Isrss int32; Isrss int32
Minflt int32; Minflt int32
Majflt int32; Majflt int32
Nswap int32; Nswap int32
Inblock int32; Inblock int32
Oublock int32; Oublock int32
Msgsnd int32; Msgsnd int32
Msgrcv int32; Msgrcv int32
Nsignals int32; Nsignals int32
Nvcsw int32; Nvcsw int32
Nivcsw int32; Nivcsw int32
} }
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
@ -319,20 +319,20 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
type WaitStatus uint32 type WaitStatus uint32
func (WaitStatus) Exited() bool { return false } func (WaitStatus) Exited() bool { return false }
func (WaitStatus) ExitStatus() int { return -1 } func (WaitStatus) ExitStatus() int { return -1 }
func (WaitStatus) Signal() int { return -1 } func (WaitStatus) Signal() int { return -1 }
func (WaitStatus) CoreDump() bool { return false } func (WaitStatus) CoreDump() bool { return false }
func (WaitStatus) Stopped() bool { return false } func (WaitStatus) Stopped() bool { return false }
func (WaitStatus) Continued() bool { return false } func (WaitStatus) Continued() bool { return false }
func (WaitStatus) StopSignal() int { return -1 } func (WaitStatus) StopSignal() int { return -1 }
func (WaitStatus) Signaled() bool { return false } func (WaitStatus) Signaled() bool { return false }
func (WaitStatus) TrapCause() int { return -1 } func (WaitStatus) TrapCause() int { return -1 }

View File

@ -4,16 +4,16 @@
package syscall package syscall
func Getpagesize() int { return 4096 } func Getpagesize() int { return 4096 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
tv.Sec = int32(nsec / 1e9); tv.Sec = int32(nsec / 1e9)
tv.Usec = int32(nsec % 1e9 / 1e3); tv.Usec = int32(nsec % 1e9 / 1e3)
return; return
} }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9); ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9); ts.Nsec = int32(nsec % 1e9)
return; return
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,177 +9,177 @@ package syscall
// Constants // Constants
const ( const (
EMULTIHOP = 0x48; EMULTIHOP = 0x48
EUNATCH = 0x31; EUNATCH = 0x31
EAFNOSUPPORT = 0x61; EAFNOSUPPORT = 0x61
EREMCHG = 0x4e; EREMCHG = 0x4e
EACCES = 0xd; EACCES = 0xd
EL3RST = 0x2f; EL3RST = 0x2f
EDESTADDRREQ = 0x59; EDESTADDRREQ = 0x59
EILSEQ = 0x54; EILSEQ = 0x54
ESPIPE = 0x1d; ESPIPE = 0x1d
EMLINK = 0x1f; EMLINK = 0x1f
EOWNERDEAD = 0x82; EOWNERDEAD = 0x82
ENOTTY = 0x19; ENOTTY = 0x19
EBADE = 0x34; EBADE = 0x34
EBADF = 0x9; EBADF = 0x9
EBADR = 0x35; EBADR = 0x35
EADV = 0x44; EADV = 0x44
ERANGE = 0x22; ERANGE = 0x22
ECANCELED = 0x7d; ECANCELED = 0x7d
ETXTBSY = 0x1a; ETXTBSY = 0x1a
ENOMEM = 0xc; ENOMEM = 0xc
EINPROGRESS = 0x73; EINPROGRESS = 0x73
ENOTEMPTY = 0x27; ENOTEMPTY = 0x27
ENOTBLK = 0xf; ENOTBLK = 0xf
EPROTOTYPE = 0x5b; EPROTOTYPE = 0x5b
ERESTART = 0x55; ERESTART = 0x55
EISNAM = 0x78; EISNAM = 0x78
ENOMSG = 0x2a; ENOMSG = 0x2a
EALREADY = 0x72; EALREADY = 0x72
ETIMEDOUT = 0x6e; ETIMEDOUT = 0x6e
ENODATA = 0x3d; ENODATA = 0x3d
EINTR = 0x4; EINTR = 0x4
ENOLINK = 0x43; ENOLINK = 0x43
EPERM = 0x1; EPERM = 0x1
ELOOP = 0x28; ELOOP = 0x28
ENETDOWN = 0x64; ENETDOWN = 0x64
ESTALE = 0x74; ESTALE = 0x74
ENOTSOCK = 0x58; ENOTSOCK = 0x58
ENOSR = 0x3f; ENOSR = 0x3f
ECHILD = 0xa; ECHILD = 0xa
ELNRNG = 0x30; ELNRNG = 0x30
EPIPE = 0x20; EPIPE = 0x20
EBADMSG = 0x4a; EBADMSG = 0x4a
EBFONT = 0x3b; EBFONT = 0x3b
EREMOTE = 0x42; EREMOTE = 0x42
ETOOMANYREFS = 0x6d; ETOOMANYREFS = 0x6d
EPFNOSUPPORT = 0x60; EPFNOSUPPORT = 0x60
ENONET = 0x40; ENONET = 0x40
EXFULL = 0x36; EXFULL = 0x36
EBADSLT = 0x39; EBADSLT = 0x39
ENOTNAM = 0x76; ENOTNAM = 0x76
ENOCSI = 0x32; ENOCSI = 0x32
EADDRINUSE = 0x62; EADDRINUSE = 0x62
ENETRESET = 0x66; ENETRESET = 0x66
EISDIR = 0x15; EISDIR = 0x15
EIDRM = 0x2b; EIDRM = 0x2b
ECOMM = 0x46; ECOMM = 0x46
EBADFD = 0x4d; EBADFD = 0x4d
EL2HLT = 0x33; EL2HLT = 0x33
ENOKEY = 0x7e; ENOKEY = 0x7e
EINVAL = 0x16; EINVAL = 0x16
ESHUTDOWN = 0x6c; ESHUTDOWN = 0x6c
EKEYREJECTED = 0x81; EKEYREJECTED = 0x81
ELIBSCN = 0x51; ELIBSCN = 0x51
ENAVAIL = 0x77; ENAVAIL = 0x77
EOVERFLOW = 0x4b; EOVERFLOW = 0x4b
EUCLEAN = 0x75; EUCLEAN = 0x75
ENOMEDIUM = 0x7b; ENOMEDIUM = 0x7b
EBUSY = 0x10; EBUSY = 0x10
EPROTO = 0x47; EPROTO = 0x47
ENODEV = 0x13; ENODEV = 0x13
EKEYEXPIRED = 0x7f; EKEYEXPIRED = 0x7f
EROFS = 0x1e; EROFS = 0x1e
ELIBACC = 0x4f; ELIBACC = 0x4f
E2BIG = 0x7; E2BIG = 0x7
EDEADLK = 0x23; EDEADLK = 0x23
ENOTDIR = 0x14; ENOTDIR = 0x14
ECONNRESET = 0x68; ECONNRESET = 0x68
ENXIO = 0x6; ENXIO = 0x6
EBADRQC = 0x38; EBADRQC = 0x38
ENAMETOOLONG = 0x24; ENAMETOOLONG = 0x24
ESOCKTNOSUPPORT = 0x5e; ESOCKTNOSUPPORT = 0x5e
ELIBEXEC = 0x53; ELIBEXEC = 0x53
EDOTDOT = 0x49; EDOTDOT = 0x49
EADDRNOTAVAIL = 0x63; EADDRNOTAVAIL = 0x63
ETIME = 0x3e; ETIME = 0x3e
EPROTONOSUPPORT = 0x5d; EPROTONOSUPPORT = 0x5d
ENOTRECOVERABLE = 0x83; ENOTRECOVERABLE = 0x83
EIO = 0x5; EIO = 0x5
ENETUNREACH = 0x65; ENETUNREACH = 0x65
EXDEV = 0x12; EXDEV = 0x12
EDQUOT = 0x7a; EDQUOT = 0x7a
EREMOTEIO = 0x79; EREMOTEIO = 0x79
ENOSPC = 0x1c; ENOSPC = 0x1c
ENOEXEC = 0x8; ENOEXEC = 0x8
EMSGSIZE = 0x5a; EMSGSIZE = 0x5a
EDOM = 0x21; EDOM = 0x21
ENOSTR = 0x3c; ENOSTR = 0x3c
EFBIG = 0x1b; EFBIG = 0x1b
ESRCH = 0x3; ESRCH = 0x3
ECHRNG = 0x2c; ECHRNG = 0x2c
EHOSTDOWN = 0x70; EHOSTDOWN = 0x70
ENOLCK = 0x25; ENOLCK = 0x25
ENFILE = 0x17; ENFILE = 0x17
ENOSYS = 0x26; ENOSYS = 0x26
ENOTCONN = 0x6b; ENOTCONN = 0x6b
ENOTSUP = 0x5f; ENOTSUP = 0x5f
ESRMNT = 0x45; ESRMNT = 0x45
EDEADLOCK = 0x23; EDEADLOCK = 0x23
ECONNABORTED = 0x67; ECONNABORTED = 0x67
ENOANO = 0x37; ENOANO = 0x37
EISCONN = 0x6a; EISCONN = 0x6a
EUSERS = 0x57; EUSERS = 0x57
ENOPROTOOPT = 0x5c; ENOPROTOOPT = 0x5c
EMFILE = 0x18; EMFILE = 0x18
ENOBUFS = 0x69; ENOBUFS = 0x69
EL3HLT = 0x2e; EL3HLT = 0x2e
EFAULT = 0xe; EFAULT = 0xe
EWOULDBLOCK = 0xb; EWOULDBLOCK = 0xb
ELIBBAD = 0x50; ELIBBAD = 0x50
ESTRPIPE = 0x56; ESTRPIPE = 0x56
ECONNREFUSED = 0x6f; ECONNREFUSED = 0x6f
EAGAIN = 0xb; EAGAIN = 0xb
ELIBMAX = 0x52; ELIBMAX = 0x52
EEXIST = 0x11; EEXIST = 0x11
EL2NSYNC = 0x2d; EL2NSYNC = 0x2d
ENOENT = 0x2; ENOENT = 0x2
ENOPKG = 0x41; ENOPKG = 0x41
EKEYREVOKED = 0x80; EKEYREVOKED = 0x80
EHOSTUNREACH = 0x71; EHOSTUNREACH = 0x71
ENOTUNIQ = 0x4c; ENOTUNIQ = 0x4c
EOPNOTSUPP = 0x5f; EOPNOTSUPP = 0x5f
EMEDIUMTYPE = 0x7c; EMEDIUMTYPE = 0x7c
SIGBUS = 0x7; SIGBUS = 0x7
SIGTTIN = 0x15; SIGTTIN = 0x15
SIGPROF = 0x1b; SIGPROF = 0x1b
SIGFPE = 0x8; SIGFPE = 0x8
SIGHUP = 0x1; SIGHUP = 0x1
SIGTTOU = 0x16; SIGTTOU = 0x16
SIGSTKFLT = 0x10; SIGSTKFLT = 0x10
SIGUSR1 = 0xa; SIGUSR1 = 0xa
SIGURG = 0x17; SIGURG = 0x17
SIGIO = 0x1d; SIGIO = 0x1d
SIGQUIT = 0x3; SIGQUIT = 0x3
SIGCLD = 0x11; SIGCLD = 0x11
SHUT_RD = 0; SHUT_RD = 0
SHUT_RDWR = 0x2; SHUT_RDWR = 0x2
SHUT_WR = 0x1; SHUT_WR = 0x1
SIGABRT = 0x6; SIGABRT = 0x6
SIGTRAP = 0x5; SIGTRAP = 0x5
SIGVTALRM = 0x1a; SIGVTALRM = 0x1a
SIGPOLL = 0x1d; SIGPOLL = 0x1d
SIGSEGV = 0xb; SIGSEGV = 0xb
SIGCONT = 0x12; SIGCONT = 0x12
SIGPIPE = 0xd; SIGPIPE = 0xd
SIGWINCH = 0x1c; SIGWINCH = 0x1c
SIGXFSZ = 0x19; SIGXFSZ = 0x19
SIGCHLD = 0x11; SIGCHLD = 0x11
SIGSYS = 0x1f; SIGSYS = 0x1f
SIGSTOP = 0x13; SIGSTOP = 0x13
SIGALRM = 0xe; SIGALRM = 0xe
SIGUSR2 = 0xc; SIGUSR2 = 0xc
SIGTSTP = 0x14; SIGTSTP = 0x14
SIGKILL = 0x9; SIGKILL = 0x9
SIGXCPU = 0x18; SIGXCPU = 0x18
SIGUNUSED = 0x1f; SIGUNUSED = 0x1f
SIGPWR = 0x1e; SIGPWR = 0x1e
SIGILL = 0x4; SIGILL = 0x4
SIGINT = 0x2; SIGINT = 0x2
SIGIOT = 0x6; SIGIOT = 0x6
SIGTERM = 0xf; SIGTERM = 0xf
O_EXCL = 0x80; O_EXCL = 0x80
) )
// Types // Types

View File

@ -4,126 +4,126 @@
package syscall package syscall
const ( const (
EPERM = 1; EPERM = 1
ENOENT = 2; ENOENT = 2
ESRCH = 3; ESRCH = 3
EINTR = 4; EINTR = 4
EIO = 5; EIO = 5
ENXIO = 6; ENXIO = 6
E2BIG = 7; E2BIG = 7
ENOEXEC = 8; ENOEXEC = 8
EBADF = 9; EBADF = 9
ECHILD = 10; ECHILD = 10
EAGAIN = 11; EAGAIN = 11
ENOMEM = 12; ENOMEM = 12
EACCES = 13; EACCES = 13
EFAULT = 14; EFAULT = 14
EBUSY = 16; EBUSY = 16
EEXIST = 17; EEXIST = 17
EXDEV = 18; EXDEV = 18
ENODEV = 19; ENODEV = 19
ENOTDIR = 20; ENOTDIR = 20
EISDIR = 21; EISDIR = 21
EINVAL = 22; EINVAL = 22
ENFILE = 23; ENFILE = 23
EMFILE = 24; EMFILE = 24
ENOTTY = 25; ENOTTY = 25
EFBIG = 27; EFBIG = 27
ENOSPC = 28; ENOSPC = 28
ESPIPE = 29; ESPIPE = 29
EROFS = 30; EROFS = 30
EMLINK = 31; EMLINK = 31
EPIPE = 32; EPIPE = 32
ENAMETOOLONG = 36; ENAMETOOLONG = 36
ENOSYS = 38; ENOSYS = 38
EDQUOT = 122; EDQUOT = 122
EDOM = 33; EDOM = 33
ERANGE = 34; ERANGE = 34
ENOMSG = 35; ENOMSG = 35
ECHRNG = 37; ECHRNG = 37
EL3HLT = 39; EL3HLT = 39
EL3RST = 40; EL3RST = 40
ELNRNG = 41; ELNRNG = 41
EUNATCH = 42; EUNATCH = 42
ENOCSI = 43; ENOCSI = 43
EL2HLT = 44; EL2HLT = 44
EDEADLK = 45; EDEADLK = 45
ENOLCK = 46; ENOLCK = 46
EBADE = 50; EBADE = 50
EBADR = 51; EBADR = 51
EXFULL = 52; EXFULL = 52
ENOANO = 53; ENOANO = 53
EBADRQC = 54; EBADRQC = 54
EBADSLT = 55; EBADSLT = 55
EBFONT = 57; EBFONT = 57
ENOSTR = 60; ENOSTR = 60
ENODATA = 61; ENODATA = 61
ETIME = 62; ETIME = 62
ENOSR = 63; ENOSR = 63
ENONET = 64; ENONET = 64
ENOPKG = 65; ENOPKG = 65
EREMOTE = 66; EREMOTE = 66
ENOLINK = 67; ENOLINK = 67
EADV = 68; EADV = 68
ESRMNT = 69; ESRMNT = 69
ECOMM = 70; ECOMM = 70
EPROTO = 71; EPROTO = 71
EMULTIHOP = 74; EMULTIHOP = 74
ELBIN = 75; ELBIN = 75
EDOTDOT = 76; EDOTDOT = 76
EBADMSG = 77; EBADMSG = 77
EFTYPE = 79; EFTYPE = 79
ENOTUNIQ = 80; ENOTUNIQ = 80
EBADFD = 81; EBADFD = 81
EREMCHG = 82; EREMCHG = 82
ELIBACC = 83; ELIBACC = 83
ELIBBAD = 84; ELIBBAD = 84
ELIBSCN = 85; ELIBSCN = 85
ELIBMAX = 86; ELIBMAX = 86
ELIBEXEC = 87; ELIBEXEC = 87
ENMFILE = 89; ENMFILE = 89
ENOTEMPTY = 90; ENOTEMPTY = 90
ELOOP = 92; ELOOP = 92
EOPNOTSUPP = 95; EOPNOTSUPP = 95
EPFNOSUPPORT = 96; EPFNOSUPPORT = 96
ECONNRESET = 104; ECONNRESET = 104
ENOBUFS = 105; ENOBUFS = 105
EAFNOSUPPORT = 106; EAFNOSUPPORT = 106
EPROTOTYPE = 107; EPROTOTYPE = 107
ENOTSOCK = 108; ENOTSOCK = 108
ENOPROTOOPT = 109; ENOPROTOOPT = 109
ESHUTDOWN = 110; ESHUTDOWN = 110
ECONNREFUSED = 111; ECONNREFUSED = 111
EADDRINUSE = 112; EADDRINUSE = 112
ECONNABORTED = 113; ECONNABORTED = 113
ENETUNREACH = 114; ENETUNREACH = 114
ENETDOWN = 115; ENETDOWN = 115
ETIMEDOUT = 116; ETIMEDOUT = 116
EHOSTDOWN = 117; EHOSTDOWN = 117
EHOSTUNREACH = 118; EHOSTUNREACH = 118
EINPROGRESS = 119; EINPROGRESS = 119
EALREADY = 120; EALREADY = 120
EDESTADDRREQ = 121; EDESTADDRREQ = 121
EPROTONOSUPPORT = 123; EPROTONOSUPPORT = 123
ESOCKTNOSUPPORT = 124; ESOCKTNOSUPPORT = 124
EADDRNOTAVAIL = 125; EADDRNOTAVAIL = 125
ENETRESET = 126; ENETRESET = 126
EISCONN = 127; EISCONN = 127
ENOTCONN = 128; ENOTCONN = 128
ETOOMANYREFS = 129; ETOOMANYREFS = 129
EPROCLIM = 130; EPROCLIM = 130
EUSERS = 131; EUSERS = 131
ESTALE = 133; ESTALE = 133
ENOMEDIUM = 135; ENOMEDIUM = 135
ENOSHARE = 136; ENOSHARE = 136
ECASECLASH = 137; ECASECLASH = 137
EILSEQ = 138; EILSEQ = 138
EOVERFLOW = 139; EOVERFLOW = 139
ECANCELED = 140; ECANCELED = 140
EL2NSYNC = 88; EL2NSYNC = 88
EIDRM = 91; EIDRM = 91
EMSGSIZE = 132; EMSGSIZE = 132
ENACL = 99; /* otherwise unused */ ENACL = 99 /* otherwise unused */
) )

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,662 +6,662 @@ package syscall
import "unsafe" import "unsafe"
func getgroups(ngid int, gid *_Gid_t) (n int, errno int) { func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0); r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func setgroups(ngid int, gid *_Gid_t) (errno int) { func setgroups(ngid int, gid *_Gid_t) (errno int) {
_, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0); _, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) { func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0); r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
wpid = int(r0); wpid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func pipe() (r int, w int, errno int) { func pipe() (r int, w int, errno int) {
r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0); r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0)
r = int(r0); r = int(r0)
w = int(r1); w = int(r1)
errno = int(e1); errno = int(e1)
return; return
} }
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) { func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))); r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) { func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)); _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
errno = int(e1); errno = int(e1)
return; return
} }
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) { func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)); _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
errno = int(e1); errno = int(e1)
return; return
} }
func socket(domain int, typ int, proto int) (fd int, errno int) { func socket(domain int, typ int, proto int) (fd int, errno int) {
r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)); r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) { func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0); _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) { func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
_, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))); _, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
errno = int(e1); errno = int(e1)
return; return
} }
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) { func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
_, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))); _, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
errno = int(e1); errno = int(e1)
return; return
} }
func Shutdown(s int, how int) (errno int) { func Shutdown(s int, how int) (errno int) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0); _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) { func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))); r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) { func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
var _p0 *byte; var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)); _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
errno = int(e1); errno = int(e1)
return; return
} }
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) { func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))); r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) { func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
var _p0 *_C_int; var _p0 *_C_int
if len(mib) > 0 { if len(mib) > 0 {
_p0 = &mib[0] _p0 = &mib[0]
} }
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)); _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
errno = int(e1); errno = int(e1)
return; return
} }
func fcntl(fd int, cmd int, arg int) (val int, errno int) { func fcntl(fd int, cmd int, arg int) (val int, errno int) {
r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)); r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
val = int(r0); val = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Access(path string, flags int) (errno int) { func Access(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) { func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0); _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chdir(path string) (errno int) { func Chdir(path string) (errno int) {
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chflags(path string, flags int) (errno int) { func Chflags(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chmod(path string, mode int) (errno int) { func Chmod(path string, mode int) (errno int) {
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0); _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chown(path string, uid int, gid int) (errno int) { func Chown(path string, uid int, gid int) (errno int) {
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid)); _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
errno = int(e1); errno = int(e1)
return; return
} }
func Chroot(path string) (errno int) { func Chroot(path string) (errno int) {
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Close(fd int) (errno int) { func Close(fd int) (errno int) {
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0); _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Dup(fd int) (nfd int, errno int) { func Dup(fd int) (nfd int, errno int) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0); r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0)
nfd = int(r0); nfd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Dup2(from int, to int) (errno int) { func Dup2(from int, to int) (errno int) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0); _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Exit(code int) { func Exit(code int) {
Syscall(SYS_EXIT, uintptr(code), 0, 0); Syscall(SYS_EXIT, uintptr(code), 0, 0)
return; return
} }
func Fchdir(fd int) (errno int) { func Fchdir(fd int) (errno int) {
_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0); _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fchflags(path string, flags int) (errno int) { func Fchflags(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fchmod(fd int, mode int) (errno int) { func Fchmod(fd int, mode int) (errno int) {
_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0); _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fchown(fd int, uid int, gid int) (errno int) { func Fchown(fd int, uid int, gid int) (errno int) {
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)); _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
errno = int(e1); errno = int(e1)
return; return
} }
func Flock(fd int, how int) (errno int) { func Flock(fd int, how int) (errno int) {
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0); _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fpathconf(fd int, name int) (val int, errno int) { func Fpathconf(fd int, name int) (val int, errno int) {
r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0); r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
val = int(r0); val = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fstat(fd int, stat *Stat_t) (errno int) { func Fstat(fd int, stat *Stat_t) (errno int) {
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fstatfs(fd int, stat *Statfs_t) (errno int) { func Fstatfs(fd int, stat *Statfs_t) (errno int) {
_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fsync(fd int) (errno int) { func Fsync(fd int) (errno int) {
_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0); _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Ftruncate(fd int, length int64) (errno int) { func Ftruncate(fd int, length int64) (errno int) {
_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32)); _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32))
errno = int(e1); errno = int(e1)
return; return
} }
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) { func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0); r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getdtablesize() (size int) { func Getdtablesize() (size int) {
r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0); r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0)
size = int(r0); size = int(r0)
return; return
} }
func Getegid() (egid int) { func Getegid() (egid int) {
r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0)
egid = int(r0); egid = int(r0)
return; return
} }
func Geteuid() (uid int) { func Geteuid() (uid int) {
r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0)
uid = int(r0); uid = int(r0)
return; return
} }
func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) { func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
var _p0 *Statfs_t; var _p0 *Statfs_t
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags)); r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getgid() (gid int) { func Getgid() (gid int) {
r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0)
gid = int(r0); gid = int(r0)
return; return
} }
func Getpgid(pid int) (pgid int, errno int) { func Getpgid(pid int) (pgid int, errno int) {
r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0); r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0)
pgid = int(r0); pgid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getpgrp() (pgrp int) { func Getpgrp() (pgrp int) {
r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0); r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0)
pgrp = int(r0); pgrp = int(r0)
return; return
} }
func Getpid() (pid int) { func Getpid() (pid int) {
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0)
pid = int(r0); pid = int(r0)
return; return
} }
func Getppid() (ppid int) { func Getppid() (ppid int) {
r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0)
ppid = int(r0); ppid = int(r0)
return; return
} }
func Getpriority(which int, who int) (prio int, errno int) { func Getpriority(which int, who int) (prio int, errno int) {
r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0); r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
prio = int(r0); prio = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getrlimit(which int, lim *Rlimit) (errno int) { func Getrlimit(which int, lim *Rlimit) (errno int) {
_, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0); _, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getrusage(who int, rusage *Rusage) (errno int) { func Getrusage(who int, rusage *Rusage) (errno int) {
_, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0); _, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getsid(pid int) (sid int, errno int) { func Getsid(pid int) (sid int, errno int) {
r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0); r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0)
sid = int(r0); sid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Gettimeofday(tv *Timeval) (errno int) { func Gettimeofday(tv *Timeval) (errno int) {
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0); _, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getuid() (uid int) { func Getuid() (uid int) {
r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0)
uid = int(r0); uid = int(r0)
return; return
} }
func Issetugid() (tainted bool) { func Issetugid() (tainted bool) {
r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0); r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
tainted = bool(r0 != 0); tainted = bool(r0 != 0)
return; return
} }
func Kill(pid int, signum int, posix int) (errno int) { func Kill(pid int, signum int, posix int) (errno int) {
_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)); _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
errno = int(e1); errno = int(e1)
return; return
} }
func Kqueue() (fd int, errno int) { func Kqueue() (fd int, errno int) {
r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0); r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Lchown(path string, uid int, gid int) (errno int) { func Lchown(path string, uid int, gid int) (errno int) {
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid)); _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
errno = int(e1); errno = int(e1)
return; return
} }
func Link(path string, link string) (errno int) { func Link(path string, link string) (errno int) {
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0); _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Listen(s int, backlog int) (errno int) { func Listen(s int, backlog int) (errno int) {
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0); _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Lstat(path string, stat *Stat_t) (errno int) { func Lstat(path string, stat *Stat_t) (errno int) {
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Mkdir(path string, mode int) (errno int) { func Mkdir(path string, mode int) (errno int) {
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0); _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Mkfifo(path string, mode int) (errno int) { func Mkfifo(path string, mode int) (errno int) {
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0); _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Mknod(path string, mode int, dev int) (errno int) { func Mknod(path string, mode int, dev int) (errno int) {
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev)); _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
errno = int(e1); errno = int(e1)
return; return
} }
func Open(path string, mode int, perm int) (fd int, errno int) { func Open(path string, mode int, perm int) (fd int, errno int) {
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm)); r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Pathconf(path string, name int) (val int, errno int) { func Pathconf(path string, name int) (val int, errno int) {
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0); r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
val = int(r0); val = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Pread(fd int, p []byte, offset int64) (n int, errno int) { func Pread(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0); r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) { func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0); r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Read(fd int, p []byte) (n int, errno int) { func Read(fd int, p []byte) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p))); r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Readlink(path string, buf []byte) (n int, errno int) { func Readlink(path string, buf []byte) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf))); r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Rename(from string, to string) (errno int) { func Rename(from string, to string) (errno int) {
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0); _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Revoke(path string) (errno int) { func Revoke(path string) (errno int) {
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Rmdir(path string) (errno int) { func Rmdir(path string) (errno int) {
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) { func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0); r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0)
newoffset = int64(int64(r1)<<32 | int64(r0)); newoffset = int64(int64(r1)<<32 | int64(r0))
errno = int(e1); errno = int(e1)
return; return
} }
func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) { func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0); _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setegid(egid int) (errno int) { func Setegid(egid int) (errno int) {
_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0); _, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Seteuid(euid int) (errno int) { func Seteuid(euid int) (errno int) {
_, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0); _, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setgid(gid int) (errno int) { func Setgid(gid int) (errno int) {
_, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0); _, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setlogin(name string) (errno int) { func Setlogin(name string) (errno int) {
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0); _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setpgid(pid int, pgid int) (errno int) { func Setpgid(pid int, pgid int) (errno int) {
_, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0); _, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setpriority(which int, who int, prio int) (errno int) { func Setpriority(which int, who int, prio int) (errno int) {
_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)); _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
errno = int(e1); errno = int(e1)
return; return
} }
func Setregid(rgid int, egid int) (errno int) { func Setregid(rgid int, egid int) (errno int) {
_, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0); _, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setreuid(ruid int, euid int) (errno int) { func Setreuid(ruid int, euid int) (errno int) {
_, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0); _, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setrlimit(which int, lim *Rlimit) (errno int) { func Setrlimit(which int, lim *Rlimit) (errno int) {
_, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0); _, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setsid() (pid int, errno int) { func Setsid() (pid int, errno int) {
r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0); r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0)
pid = int(r0); pid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Settimeofday(tp *Timeval) (errno int) { func Settimeofday(tp *Timeval) (errno int) {
_, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0); _, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setuid(uid int) (errno int) { func Setuid(uid int) (errno int) {
_, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0); _, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Stat(path string, stat *Stat_t) (errno int) { func Stat(path string, stat *Stat_t) (errno int) {
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Statfs(path string, stat *Statfs_t) (errno int) { func Statfs(path string, stat *Statfs_t) (errno int) {
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Symlink(path string, link string) (errno int) { func Symlink(path string, link string) (errno int) {
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0); _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Sync() (errno int) { func Sync() (errno int) {
_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0); _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Truncate(path string, length int64) (errno int) { func Truncate(path string, length int64) (errno int) {
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32)); _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
errno = int(e1); errno = int(e1)
return; return
} }
func Umask(newmask int) (errno int) { func Umask(newmask int) (errno int) {
_, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0); _, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Undelete(path string) (errno int) { func Undelete(path string) (errno int) {
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Unlink(path string) (errno int) { func Unlink(path string) (errno int) {
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Unmount(path string, flags int) (errno int) { func Unmount(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Write(fd int, p []byte) (n int, errno int) { func Write(fd int, p []byte) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p))); r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func read(fd int, buf *byte, nbuf int) (n int, errno int) { func read(fd int, buf *byte, nbuf int) (n int, errno int) {
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)); r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func write(fd int, buf *byte, nbuf int) (n int, errno int) { func write(fd int, buf *byte, nbuf int) (n int, errno int) {
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)); r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }

View File

@ -6,662 +6,662 @@ package syscall
import "unsafe" import "unsafe"
func getgroups(ngid int, gid *_Gid_t) (n int, errno int) { func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0); r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func setgroups(ngid int, gid *_Gid_t) (errno int) { func setgroups(ngid int, gid *_Gid_t) (errno int) {
_, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0); _, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) { func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0); r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
wpid = int(r0); wpid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func pipe() (r int, w int, errno int) { func pipe() (r int, w int, errno int) {
r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0); r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0)
r = int(r0); r = int(r0)
w = int(r1); w = int(r1)
errno = int(e1); errno = int(e1)
return; return
} }
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) { func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))); r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) { func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)); _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
errno = int(e1); errno = int(e1)
return; return
} }
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) { func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)); _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
errno = int(e1); errno = int(e1)
return; return
} }
func socket(domain int, typ int, proto int) (fd int, errno int) { func socket(domain int, typ int, proto int) (fd int, errno int) {
r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)); r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) { func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0); _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) { func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
_, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))); _, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
errno = int(e1); errno = int(e1)
return; return
} }
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) { func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
_, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))); _, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
errno = int(e1); errno = int(e1)
return; return
} }
func Shutdown(s int, how int) (errno int) { func Shutdown(s int, how int) (errno int) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0); _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) { func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))); r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) { func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
var _p0 *byte; var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)); _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
errno = int(e1); errno = int(e1)
return; return
} }
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) { func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))); r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) { func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
var _p0 *_C_int; var _p0 *_C_int
if len(mib) > 0 { if len(mib) > 0 {
_p0 = &mib[0] _p0 = &mib[0]
} }
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)); _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
errno = int(e1); errno = int(e1)
return; return
} }
func fcntl(fd int, cmd int, arg int) (val int, errno int) { func fcntl(fd int, cmd int, arg int) (val int, errno int) {
r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)); r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
val = int(r0); val = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Access(path string, flags int) (errno int) { func Access(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) { func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0); _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chdir(path string) (errno int) { func Chdir(path string) (errno int) {
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chflags(path string, flags int) (errno int) { func Chflags(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chmod(path string, mode int) (errno int) { func Chmod(path string, mode int) (errno int) {
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0); _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Chown(path string, uid int, gid int) (errno int) { func Chown(path string, uid int, gid int) (errno int) {
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid)); _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
errno = int(e1); errno = int(e1)
return; return
} }
func Chroot(path string) (errno int) { func Chroot(path string) (errno int) {
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Close(fd int) (errno int) { func Close(fd int) (errno int) {
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0); _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Dup(fd int) (nfd int, errno int) { func Dup(fd int) (nfd int, errno int) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0); r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0)
nfd = int(r0); nfd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Dup2(from int, to int) (errno int) { func Dup2(from int, to int) (errno int) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0); _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Exit(code int) { func Exit(code int) {
Syscall(SYS_EXIT, uintptr(code), 0, 0); Syscall(SYS_EXIT, uintptr(code), 0, 0)
return; return
} }
func Fchdir(fd int) (errno int) { func Fchdir(fd int) (errno int) {
_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0); _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fchflags(path string, flags int) (errno int) { func Fchflags(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fchmod(fd int, mode int) (errno int) { func Fchmod(fd int, mode int) (errno int) {
_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0); _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fchown(fd int, uid int, gid int) (errno int) { func Fchown(fd int, uid int, gid int) (errno int) {
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)); _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
errno = int(e1); errno = int(e1)
return; return
} }
func Flock(fd int, how int) (errno int) { func Flock(fd int, how int) (errno int) {
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0); _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fpathconf(fd int, name int) (val int, errno int) { func Fpathconf(fd int, name int) (val int, errno int) {
r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0); r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
val = int(r0); val = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fstat(fd int, stat *Stat_t) (errno int) { func Fstat(fd int, stat *Stat_t) (errno int) {
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fstatfs(fd int, stat *Statfs_t) (errno int) { func Fstatfs(fd int, stat *Statfs_t) (errno int) {
_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Fsync(fd int) (errno int) { func Fsync(fd int) (errno int) {
_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0); _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Ftruncate(fd int, length int64) (errno int) { func Ftruncate(fd int, length int64) (errno int) {
_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0); _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) { func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0); r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getdtablesize() (size int) { func Getdtablesize() (size int) {
r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0); r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0)
size = int(r0); size = int(r0)
return; return
} }
func Getegid() (egid int) { func Getegid() (egid int) {
r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0)
egid = int(r0); egid = int(r0)
return; return
} }
func Geteuid() (uid int) { func Geteuid() (uid int) {
r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0)
uid = int(r0); uid = int(r0)
return; return
} }
func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) { func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
var _p0 *Statfs_t; var _p0 *Statfs_t
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags)); r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getgid() (gid int) { func Getgid() (gid int) {
r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0)
gid = int(r0); gid = int(r0)
return; return
} }
func Getpgid(pid int) (pgid int, errno int) { func Getpgid(pid int) (pgid int, errno int) {
r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0); r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0)
pgid = int(r0); pgid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getpgrp() (pgrp int) { func Getpgrp() (pgrp int) {
r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0); r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0)
pgrp = int(r0); pgrp = int(r0)
return; return
} }
func Getpid() (pid int) { func Getpid() (pid int) {
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0)
pid = int(r0); pid = int(r0)
return; return
} }
func Getppid() (ppid int) { func Getppid() (ppid int) {
r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0)
ppid = int(r0); ppid = int(r0)
return; return
} }
func Getpriority(which int, who int) (prio int, errno int) { func Getpriority(which int, who int) (prio int, errno int) {
r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0); r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
prio = int(r0); prio = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getrlimit(which int, lim *Rlimit) (errno int) { func Getrlimit(which int, lim *Rlimit) (errno int) {
_, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0); _, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getrusage(who int, rusage *Rusage) (errno int) { func Getrusage(who int, rusage *Rusage) (errno int) {
_, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0); _, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getsid(pid int) (sid int, errno int) { func Getsid(pid int) (sid int, errno int) {
r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0); r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0)
sid = int(r0); sid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Gettimeofday(tv *Timeval) (errno int) { func Gettimeofday(tv *Timeval) (errno int) {
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0); _, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Getuid() (uid int) { func Getuid() (uid int) {
r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0); r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0)
uid = int(r0); uid = int(r0)
return; return
} }
func Issetugid() (tainted bool) { func Issetugid() (tainted bool) {
r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0); r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
tainted = bool(r0 != 0); tainted = bool(r0 != 0)
return; return
} }
func Kill(pid int, signum int, posix int) (errno int) { func Kill(pid int, signum int, posix int) (errno int) {
_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)); _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
errno = int(e1); errno = int(e1)
return; return
} }
func Kqueue() (fd int, errno int) { func Kqueue() (fd int, errno int) {
r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0); r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Lchown(path string, uid int, gid int) (errno int) { func Lchown(path string, uid int, gid int) (errno int) {
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid)); _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
errno = int(e1); errno = int(e1)
return; return
} }
func Link(path string, link string) (errno int) { func Link(path string, link string) (errno int) {
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0); _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Listen(s int, backlog int) (errno int) { func Listen(s int, backlog int) (errno int) {
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0); _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Lstat(path string, stat *Stat_t) (errno int) { func Lstat(path string, stat *Stat_t) (errno int) {
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Mkdir(path string, mode int) (errno int) { func Mkdir(path string, mode int) (errno int) {
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0); _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Mkfifo(path string, mode int) (errno int) { func Mkfifo(path string, mode int) (errno int) {
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0); _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Mknod(path string, mode int, dev int) (errno int) { func Mknod(path string, mode int, dev int) (errno int) {
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev)); _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
errno = int(e1); errno = int(e1)
return; return
} }
func Open(path string, mode int, perm int) (fd int, errno int) { func Open(path string, mode int, perm int) (fd int, errno int) {
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm)); r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
fd = int(r0); fd = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Pathconf(path string, name int) (val int, errno int) { func Pathconf(path string, name int) (val int, errno int) {
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0); r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
val = int(r0); val = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Pread(fd int, p []byte, offset int64) (n int, errno int) { func Pread(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0); r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) { func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0); r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Read(fd int, p []byte) (n int, errno int) { func Read(fd int, p []byte) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p))); r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Readlink(path string, buf []byte) (n int, errno int) { func Readlink(path string, buf []byte) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &buf[0] _p0 = &buf[0]
} }
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf))); r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Rename(from string, to string) (errno int) { func Rename(from string, to string) (errno int) {
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0); _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Revoke(path string) (errno int) { func Revoke(path string) (errno int) {
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Rmdir(path string) (errno int) { func Rmdir(path string) (errno int) {
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) { func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence)); r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
newoffset = int64(r0); newoffset = int64(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) { func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0); _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setegid(egid int) (errno int) { func Setegid(egid int) (errno int) {
_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0); _, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Seteuid(euid int) (errno int) { func Seteuid(euid int) (errno int) {
_, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0); _, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setgid(gid int) (errno int) { func Setgid(gid int) (errno int) {
_, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0); _, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setlogin(name string) (errno int) { func Setlogin(name string) (errno int) {
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0); _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setpgid(pid int, pgid int) (errno int) { func Setpgid(pid int, pgid int) (errno int) {
_, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0); _, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setpriority(which int, who int, prio int) (errno int) { func Setpriority(which int, who int, prio int) (errno int) {
_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)); _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
errno = int(e1); errno = int(e1)
return; return
} }
func Setregid(rgid int, egid int) (errno int) { func Setregid(rgid int, egid int) (errno int) {
_, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0); _, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setreuid(ruid int, euid int) (errno int) { func Setreuid(ruid int, euid int) (errno int) {
_, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0); _, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setrlimit(which int, lim *Rlimit) (errno int) { func Setrlimit(which int, lim *Rlimit) (errno int) {
_, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0); _, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setsid() (pid int, errno int) { func Setsid() (pid int, errno int) {
r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0); r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0)
pid = int(r0); pid = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func Settimeofday(tp *Timeval) (errno int) { func Settimeofday(tp *Timeval) (errno int) {
_, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0); _, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Setuid(uid int) (errno int) { func Setuid(uid int) (errno int) {
_, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0); _, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Stat(path string, stat *Stat_t) (errno int) { func Stat(path string, stat *Stat_t) (errno int) {
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Statfs(path string, stat *Statfs_t) (errno int) { func Statfs(path string, stat *Statfs_t) (errno int) {
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0); _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Symlink(path string, link string) (errno int) { func Symlink(path string, link string) (errno int) {
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0); _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Sync() (errno int) { func Sync() (errno int) {
_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0); _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Truncate(path string, length int64) (errno int) { func Truncate(path string, length int64) (errno int) {
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0); _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Umask(newmask int) (errno int) { func Umask(newmask int) (errno int) {
_, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0); _, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Undelete(path string) (errno int) { func Undelete(path string) (errno int) {
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Unlink(path string) (errno int) { func Unlink(path string) (errno int) {
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0); _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Unmount(path string, flags int) (errno int) { func Unmount(path string, flags int) (errno int) {
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0); _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
errno = int(e1); errno = int(e1)
return; return
} }
func Write(fd int, p []byte) (n int, errno int) { func Write(fd int, p []byte) (n int, errno int) {
var _p0 *byte; var _p0 *byte
if len(p) > 0 { if len(p) > 0 {
_p0 = &p[0] _p0 = &p[0]
} }
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p))); r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func read(fd int, buf *byte, nbuf int) (n int, errno int) { func read(fd int, buf *byte, nbuf int) (n int, errno int) {
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)); r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }
func write(fd int, buf *byte, nbuf int) (n int, errno int) { func write(fd int, buf *byte, nbuf int) (n int, errno int) {
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)); r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
n = int(r0); n = int(r0)
errno = int(e1); errno = int(e1)
return; return
} }

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More