// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package obj import ( "bufio" "fmt" "io" "log" "os" "strconv" "time" ) var start time.Time func Cputime() float64 { if start.IsZero() { start = time.Now() } return time.Since(start).Seconds() } type Biobuf struct { unget [2]int numUnget int f *os.File r *bufio.Reader w *bufio.Writer linelen int } func Bopenw(name string) (*Biobuf, error) { f, err := os.Create(name) if err != nil { return nil, err } return &Biobuf{f: f, w: bufio.NewWriter(f)}, nil } func Bopenr(name string) (*Biobuf, error) { f, err := os.Open(name) if err != nil { return nil, err } return &Biobuf{f: f, r: bufio.NewReader(f)}, nil } func Binitw(w io.Writer) *Biobuf { return &Biobuf{w: bufio.NewWriter(w)} } func (b *Biobuf) Write(p []byte) (int, error) { return b.w.Write(p) } func Bwritestring(b *Biobuf, p string) (int, error) { return b.w.WriteString(p) } func Bseek(b *Biobuf, offset int64, whence int) int64 { if b.w != nil { if err := b.w.Flush(); err != nil { log.Fatal("writing output: %v", err) } } else if b.r != nil { if whence == 1 { offset -= int64(b.r.Buffered()) } } off, err := b.f.Seek(offset, whence) if err != nil { log.Fatal("seeking in output: %v", err) } if b.r != nil { b.r.Reset(b.f) } return off } func Boffset(b *Biobuf) int64 { if err := b.w.Flush(); err != nil { log.Fatal("writing output: %v", err) } off, err := b.f.Seek(0, 1) if err != nil { log.Fatal("seeking in output: %v", err) } return off } func (b *Biobuf) Flush() error { return b.w.Flush() } func Bwrite(b *Biobuf, p []byte) (int, error) { return b.w.Write(p) } func Bputc(b *Biobuf, c byte) { b.w.WriteByte(c) } const Beof = -1 func Bread(b *Biobuf, p []byte) int { n, err := io.ReadFull(b.r, p) if n == 0 { if err != nil && err != io.EOF { n = -1 } } return n } func Bgetc(b *Biobuf) int { if b.numUnget > 0 { b.numUnget-- return int(b.unget[b.numUnget]) } c, err := b.r.ReadByte() r := int(c) if err != nil { r = -1 } b.unget[1] = b.unget[0] b.unget[0] = r return r } func Bgetrune(b *Biobuf) int { r, _, err := b.r.ReadRune() if err != nil { return -1 } return int(r) } func Bungetrune(b *Biobuf) { b.r.UnreadRune() } func (b *Biobuf) Read(p []byte) (int, error) { return b.r.Read(p) } func Brdline(b *Biobuf, delim int) string { s, err := b.r.ReadBytes(byte(delim)) if err != nil { log.Fatalf("reading input: %v", err) } b.linelen = len(s) return string(s) } func Brdstr(b *Biobuf, delim int, cut int) string { s, err := b.r.ReadString(byte(delim)) if err != nil { log.Fatalf("reading input: %v", err) } if len(s) > 0 && cut > 0 { s = s[:len(s)-1] } return s } func Access(name string, mode int) int { if mode != 0 { panic("bad access") } _, err := os.Stat(name) if err != nil { return -1 } return 0 } func Blinelen(b *Biobuf) int { return b.linelen } func Bungetc(b *Biobuf) { b.numUnget++ } func Bflush(b *Biobuf) error { return b.w.Flush() } func Bterm(b *Biobuf) error { var err error if b.w != nil { err = b.w.Flush() } err1 := b.f.Close() if err == nil { err = err1 } return err } func envOr(key, value string) string { if x := os.Getenv(key); x != "" { return x } return value } func Getgoroot() string { return envOr("GOROOT", defaultGOROOT) } func Getgoarch() string { return envOr("GOARCH", defaultGOARCH) } func Getgoos() string { return envOr("GOOS", defaultGOOS) } func Getgoarm() string { return envOr("GOARM", defaultGOARM) } func Getgo386() string { return envOr("GO386", defaultGO386) } func Getgoversion() string { return version } func Atoi(s string) int { i, _ := strconv.Atoi(s) return i } func (p *Prog) Line() string { return Linklinefmt(p.Ctxt, int(p.Lineno), false, false) } func (p *Prog) String() string { if p.Ctxt == nil { return fmt.Sprintf("") } return p.Ctxt.Arch.Pconv(p) } func (ctxt *Link) NewProg() *Prog { p := new(Prog) // should be the only call to this; all others should use ctxt.NewProg p.Ctxt = ctxt return p } func (ctxt *Link) Line(n int) string { return Linklinefmt(ctxt, n, false, false) } func (ctxt *Link) Dconv(a *Addr) string { return ctxt.Arch.Dconv(nil, 0, a) } func (ctxt *Link) Rconv(reg int) string { return ctxt.Arch.Rconv(reg) } func Getcallerpc(interface{}) uintptr { return 1 }