time: fix Plan 9 build for new API
I had to move readFile into sys_$GOOS.go
since syscall.Open takes only two arguments
on Plan 9.
R=lucio.dere, rsc, alex.brainman
CC=golang-dev
https://golang.org/cl/5447061
diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c
index 87ea8a2..07edb71 100644
--- a/src/pkg/runtime/plan9/thread.c
+++ b/src/pkg/runtime/plan9/thread.c
@@ -97,6 +97,18 @@
return (int64)hi<<32 | (int64)lo;
}
+void
+time·now(int64 sec, int32 nsec)
+{
+ int64 ns;
+
+ ns = runtime·nanotime();
+ sec = ns / 1000000000LL;
+ nsec = ns - sec * 1000000000LL;
+ FLUSH(&sec);
+ FLUSH(&nsec);
+}
+
extern Tos *_tos;
void
runtime·exit(int32)
diff --git a/src/pkg/time/Makefile b/src/pkg/time/Makefile
index 28c6afc..9f61329 100644
--- a/src/pkg/time/Makefile
+++ b/src/pkg/time/Makefile
@@ -8,7 +8,6 @@
GOFILES=\
format.go\
sleep.go\
- sys.go\
tick.go\
time.go\
zoneinfo.go\
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
index 844d964..b4680db 100644
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -4,6 +4,9 @@
package time
+// Sleep pauses the current goroutine for the duration d.
+func Sleep(d Duration)
+
func nano() int64 {
sec, nsec := now()
return sec*1e9 + int64(nsec)
diff --git a/src/pkg/time/sys.go b/src/pkg/time/sys.go
deleted file mode 100644
index fe6bc27..0000000
--- a/src/pkg/time/sys.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package time
-
-import "syscall"
-
-// Sleep pauses the current goroutine for the duration d.
-func Sleep(d Duration)
-
-// readFile reads and returns the content of the named file.
-// It is a trivial implementation of ioutil.ReadFile, reimplemented
-// here to avoid depending on io/ioutil or os.
-func readFile(name string) ([]byte, error) {
- f, err := syscall.Open(name, syscall.O_RDONLY, 0)
- if err != nil {
- return nil, err
- }
- defer syscall.Close(f)
- var (
- buf [4096]byte
- ret []byte
- n int
- )
- for {
- n, err = syscall.Read(f, buf[:])
- if n > 0 {
- ret = append(ret, buf[:n]...)
- }
- if n == 0 || err != nil {
- break
- }
- }
- return ret, err
-}
diff --git a/src/pkg/time/sys_plan9.go b/src/pkg/time/sys_plan9.go
index e58fb51..c7cfa79 100644
--- a/src/pkg/time/sys_plan9.go
+++ b/src/pkg/time/sys_plan9.go
@@ -2,9 +2,39 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build plan9
+
package time
+import "syscall"
+
// for testing: whatever interrupts a sleep
func interrupt() {
// cannot predict pid, don't want to kill group
}
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+ f, err := syscall.Open(name, syscall.O_RDONLY)
+ if err != nil {
+ return nil, err
+ }
+ defer syscall.Close(f)
+ var (
+ buf [4096]byte
+ ret []byte
+ n int
+ )
+ for {
+ n, err = syscall.Read(f, buf[:])
+ if n > 0 {
+ ret = append(ret, buf[:n]...)
+ }
+ if n == 0 || err != nil {
+ break
+ }
+ }
+ return ret, err
+}
diff --git a/src/pkg/time/sys_unix.go b/src/pkg/time/sys_unix.go
index 715d186..55ae5f7 100644
--- a/src/pkg/time/sys_unix.go
+++ b/src/pkg/time/sys_unix.go
@@ -12,3 +12,29 @@
func interrupt() {
syscall.Kill(syscall.Getpid(), syscall.SIGCHLD)
}
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+ f, err := syscall.Open(name, syscall.O_RDONLY, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer syscall.Close(f)
+ var (
+ buf [4096]byte
+ ret []byte
+ n int
+ )
+ for {
+ n, err = syscall.Read(f, buf[:])
+ if n > 0 {
+ ret = append(ret, buf[:n]...)
+ }
+ if n == 0 || err != nil {
+ break
+ }
+ }
+ return ret, err
+}
diff --git a/src/pkg/time/zoneinfo_plan9.go b/src/pkg/time/zoneinfo_plan9.go
index 38aefc7..9c052d4 100644
--- a/src/pkg/time/zoneinfo_plan9.go
+++ b/src/pkg/time/zoneinfo_plan9.go
@@ -6,61 +6,152 @@
package time
-//import (
-// "strconv"
-// "strings"
-//)
+import (
+ "errors"
+ "syscall"
+)
-func parseZones(s string) (zt []zonetime) {
- f := strings.Fields(s)
- if len(f) < 4 {
- return
- }
+var badData = errors.New("malformed time zone information")
- // standard timezone offset
- o, err := strconv.Atoi(f[1])
- if err != nil {
- return
- }
- std := &zone{name: f[0], utcoff: o, isdst: false}
-
- // alternate timezone offset
- o, err = strconv.Atoi(f[3])
- if err != nil {
- return
- }
- dst := &zone{name: f[2], utcoff: o, isdst: true}
-
- // transition time pairs
- f = f[4:]
- for i := 0; i < len(f); i++ {
- z := std
- if i%2 == 0 {
- z = dst
- }
- t, err := strconv.Atoi(f[i])
- if err != nil {
- return nil
- }
- t -= std.utcoff
- zt = append(zt, zonetime{time: int32(t), zone: z})
- }
- return
+func isSpace(r rune) bool {
+ return r == ' ' || r == '\t' || r == '\n'
}
-func initLocal() {
- t, err := os.Getenverror("timezone")
- if err != nil {
- // do nothing: use UTC
- return
+// Copied from strings to avoid a dependency.
+func fields(s string) []string {
+ // First count the fields.
+ n := 0
+ inField := false
+ for _, rune := range s {
+ wasInField := inField
+ inField = !isSpace(rune)
+ if inField && !wasInField {
+ n++
+ }
}
- zones = parseZones(t)
+
+ // Now create them.
+ a := make([]string, n)
+ na := 0
+ fieldStart := -1 // Set to -1 when looking for start of field.
+ for i, rune := range s {
+ if isSpace(rune) {
+ if fieldStart >= 0 {
+ a[na] = s[fieldStart:i]
+ na++
+ fieldStart = -1
+ }
+ } else if fieldStart == -1 {
+ fieldStart = i
+ }
+ }
+ if fieldStart >= 0 { // Last field might end at EOF.
+ a[na] = s[fieldStart:]
+ }
+ return a
+}
+
+func loadZoneData(s string) (l *Location, err error) {
+ f := fields(s)
+ if len(f) < 4 {
+ if len(f) == 2 && f[0] == "GMT" {
+ return UTC, nil
+ }
+ return nil, badData
+ }
+
+ var zones [2]zone
+
+ // standard timezone offset
+ o, err := atoi(f[1])
+ if err != nil {
+ return nil, badData
+ }
+ zones[0] = zone{name: f[0], offset: o, isDST: false}
+
+ // alternate timezone offset
+ o, err = atoi(f[3])
+ if err != nil {
+ return nil, badData
+ }
+ zones[1] = zone{name: f[2], offset: o, isDST: true}
+
+ // transition time pairs
+ var tx []zoneTrans
+ f = f[4:]
+ for i := 0; i < len(f); i++ {
+ zi := 0
+ if i%2 == 0 {
+ zi = 1
+ }
+ t, err := atoi(f[i])
+ if err != nil {
+ return nil, badData
+ }
+ t -= zones[0].offset
+ tx = append(tx, zoneTrans{when: int64(t), index: uint8(zi)})
+ }
+
+ // Committed to succeed.
+ l = &Location{zone: zones[:], tx: tx}
+
+ // Fill in the cache with information about right now,
+ // since that will be the most common lookup.
+ sec, _ := now()
+ for i := range tx {
+ if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
+ l.cacheStart = tx[i].when
+ l.cacheEnd = 1<<63 - 1
+ if i+1 < len(tx) {
+ l.cacheEnd = tx[i+1].when
+ }
+ l.cacheZone = &l.zone[tx[i].index]
+ }
+ }
+
+ return l, nil
+}
+
+func loadZoneFile(name string) (*Location, error) {
+ b, err := readFile(name)
+ if err != nil {
+ return nil, err
+ }
+ return loadZoneData(string(b))
}
func initTestingZone() {
- buf, err := readFile("/adm/timezone/US_Pacific")
- if err != nil {
+ if z, err := loadZoneFile("/adm/timezone/US_Pacific"); err == nil {
+ localLoc = *z
return
}
- zones = parseZones(string(buf))
+
+ // Fall back to UTC.
+ localLoc.name = "UTC"
+}
+
+func initLocal() {
+ t, ok := syscall.Getenv("timezone")
+ if ok {
+ if z, err := loadZoneData(t); err == nil {
+ localLoc = *z
+ return
+ }
+ } else {
+ if z, err := loadZoneFile("/adm/timezone/local"); err == nil {
+ localLoc = *z
+ localLoc.name = "Local"
+ return
+ }
+ }
+
+ // Fall back to UTC.
+ localLoc.name = "UTC"
+}
+
+func loadLocation(name string) (*Location, error) {
+ if z, err := loadZoneFile("/adm/timezone/" + name); err == nil {
+ return z, nil
+ }
+ return nil, errors.New("unknown time zone " + name)
}