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)
 }