github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/internal/ld/util.go (about)

     1  // Copyright 2015 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ld
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"encoding/binary"
    11  	"io"
    12  	"log"
    13  	"os"
    14  	"runtime/pprof"
    15  	"strings"
    16  	"time"
    17  )
    18  
    19  func cstring(x []byte) string {
    20  	i := bytes.IndexByte(x, '\x00')
    21  	if i >= 0 {
    22  		x = x[:i]
    23  	}
    24  	return string(x)
    25  }
    26  
    27  func tokenize(s string) []string {
    28  	var f []string
    29  	for {
    30  		s = strings.TrimLeft(s, " \t\r\n")
    31  		if s == "" {
    32  			break
    33  		}
    34  		quote := false
    35  		i := 0
    36  		for ; i < len(s); i++ {
    37  			if s[i] == '\'' {
    38  				if quote && i+1 < len(s) && s[i+1] == '\'' {
    39  					i++
    40  					continue
    41  				}
    42  				quote = !quote
    43  			}
    44  			if !quote && (s[i] == ' ' || s[i] == '\t' || s[i] == '\r' || s[i] == '\n') {
    45  				break
    46  			}
    47  		}
    48  		next := s[:i]
    49  		s = s[i:]
    50  		if strings.Contains(next, "'") {
    51  			var buf []byte
    52  			quote := false
    53  			for i := 0; i < len(next); i++ {
    54  				if next[i] == '\'' {
    55  					if quote && i+1 < len(next) && next[i+1] == '\'' {
    56  						i++
    57  						buf = append(buf, '\'')
    58  					}
    59  					quote = !quote
    60  					continue
    61  				}
    62  				buf = append(buf, next[i])
    63  			}
    64  			next = string(buf)
    65  		}
    66  		f = append(f, next)
    67  	}
    68  	return f
    69  }
    70  
    71  func cutStringAtNUL(s string) string {
    72  	if i := strings.Index(s, "\x00"); i >= 0 {
    73  		s = s[:i]
    74  	}
    75  	return s
    76  }
    77  
    78  type Biobuf struct {
    79  	unget    [2]int
    80  	numUnget int
    81  	f        *os.File
    82  	r        *bufio.Reader
    83  	w        *bufio.Writer
    84  	linelen  int
    85  }
    86  
    87  func Bopenw(name string) (*Biobuf, error) {
    88  	f, err := os.Create(name)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	return &Biobuf{f: f, w: bufio.NewWriter(f)}, nil
    93  }
    94  
    95  func Bopenr(name string) (*Biobuf, error) {
    96  	f, err := os.Open(name)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	return &Biobuf{f: f, r: bufio.NewReader(f)}, nil
   101  }
   102  
   103  func Binitw(w *os.File) *Biobuf {
   104  	return &Biobuf{w: bufio.NewWriter(w), f: w}
   105  }
   106  
   107  func (b *Biobuf) Write(p []byte) (int, error) {
   108  	return b.w.Write(p)
   109  }
   110  
   111  func Bwritestring(b *Biobuf, p string) (int, error) {
   112  	return b.w.WriteString(p)
   113  }
   114  
   115  func Bseek(b *Biobuf, offset int64, whence int) int64 {
   116  	if b.w != nil {
   117  		if err := b.w.Flush(); err != nil {
   118  			log.Fatalf("writing output: %v", err)
   119  		}
   120  	} else if b.r != nil {
   121  		if whence == 1 {
   122  			offset -= int64(b.r.Buffered())
   123  		}
   124  	}
   125  	off, err := b.f.Seek(offset, whence)
   126  	if err != nil {
   127  		log.Panicf("seeking in output [%d %d %p]: %v", offset, whence, b.f, err)
   128  	}
   129  	if b.r != nil {
   130  		b.r.Reset(b.f)
   131  	}
   132  	return off
   133  }
   134  
   135  func Boffset(b *Biobuf) int64 {
   136  	if b.w != nil {
   137  		if err := b.w.Flush(); err != nil {
   138  			log.Fatalf("writing output: %v", err)
   139  		}
   140  	}
   141  	off, err := b.f.Seek(0, 1)
   142  	if err != nil {
   143  		log.Fatalf("seeking in output [0, 1]: %v", err)
   144  	}
   145  	if b.r != nil {
   146  		off -= int64(b.r.Buffered())
   147  	}
   148  	return off
   149  }
   150  
   151  func (b *Biobuf) Flush() error {
   152  	return b.w.Flush()
   153  }
   154  
   155  func Bwrite(b *Biobuf, p []byte) (int, error) {
   156  	return b.w.Write(p)
   157  }
   158  
   159  func Bputc(b *Biobuf, c byte) {
   160  	b.w.WriteByte(c)
   161  }
   162  
   163  const Beof = -1
   164  
   165  func Bread(b *Biobuf, p []byte) int {
   166  	if b.numUnget > 0 {
   167  		Bseek(b, -int64(b.numUnget), 1)
   168  		b.numUnget = 0
   169  	}
   170  	n, err := io.ReadFull(b.r, p)
   171  	if n == 0 {
   172  		if err != nil && err != io.EOF {
   173  			n = -1
   174  		}
   175  	}
   176  	return n
   177  }
   178  
   179  func Bgetc(b *Biobuf) int {
   180  	if b.numUnget > 0 {
   181  		b.numUnget--
   182  		return int(b.unget[b.numUnget])
   183  	}
   184  	c, err := b.r.ReadByte()
   185  	r := int(c)
   186  	if err != nil {
   187  		r = -1
   188  	}
   189  	b.unget[1] = b.unget[0]
   190  	b.unget[0] = r
   191  	return r
   192  }
   193  
   194  func Bgetrune(b *Biobuf) int {
   195  	if b.numUnget > 0 {
   196  		Bseek(b, -int64(b.numUnget), 1)
   197  		b.numUnget = 0
   198  	}
   199  	r, _, err := b.r.ReadRune()
   200  	if err != nil {
   201  		return -1
   202  	}
   203  	return int(r)
   204  }
   205  
   206  func Bungetrune(b *Biobuf) {
   207  	b.r.UnreadRune()
   208  }
   209  
   210  func (b *Biobuf) Read(p []byte) (int, error) {
   211  	return b.r.Read(p)
   212  }
   213  
   214  func Brdline(b *Biobuf, delim int) string {
   215  	if b.numUnget > 0 {
   216  		Bseek(b, -int64(b.numUnget), 1)
   217  		b.numUnget = 0
   218  	}
   219  	s, err := b.r.ReadBytes(byte(delim))
   220  	if err != nil {
   221  		log.Fatalf("reading input: %v", err)
   222  	}
   223  	b.linelen = len(s)
   224  	return string(s)
   225  }
   226  
   227  func Brdstr(b *Biobuf, delim int, cut int) string {
   228  	if b.numUnget > 0 {
   229  		Bseek(b, -int64(b.numUnget), 1)
   230  		b.numUnget = 0
   231  	}
   232  	s, err := b.r.ReadString(byte(delim))
   233  	if err != nil {
   234  		log.Fatalf("reading input: %v", err)
   235  	}
   236  	if len(s) > 0 && cut > 0 {
   237  		s = s[:len(s)-1]
   238  	}
   239  	return s
   240  }
   241  
   242  func Access(name string, mode int) int {
   243  	if mode != 0 {
   244  		panic("bad access")
   245  	}
   246  	_, err := os.Stat(name)
   247  	if err != nil {
   248  		return -1
   249  	}
   250  	return 0
   251  }
   252  
   253  func Blinelen(b *Biobuf) int {
   254  	return b.linelen
   255  }
   256  
   257  func Bungetc(b *Biobuf) {
   258  	b.numUnget++
   259  }
   260  
   261  func Bflush(b *Biobuf) error {
   262  	return b.w.Flush()
   263  }
   264  
   265  func Bterm(b *Biobuf) error {
   266  	var err error
   267  	if b.w != nil {
   268  		err = b.w.Flush()
   269  	}
   270  	err1 := b.f.Close()
   271  	if err == nil {
   272  		err = err1
   273  	}
   274  	return err
   275  }
   276  
   277  // strings.Compare, introduced in Go 1.5.
   278  func stringsCompare(a, b string) int {
   279  	if a == b {
   280  		return 0
   281  	}
   282  	if a < b {
   283  		return -1
   284  	}
   285  	return +1
   286  }
   287  
   288  var atExitFuncs []func()
   289  
   290  func AtExit(f func()) {
   291  	atExitFuncs = append(atExitFuncs, f)
   292  }
   293  
   294  func Exit(code int) {
   295  	for i := len(atExitFuncs) - 1; i >= 0; i-- {
   296  		f := atExitFuncs[i]
   297  		atExitFuncs = atExitFuncs[:i]
   298  		f()
   299  	}
   300  	os.Exit(code)
   301  }
   302  
   303  var cpuprofile string
   304  var memprofile string
   305  
   306  func startProfile() {
   307  	if cpuprofile != "" {
   308  		f, err := os.Create(cpuprofile)
   309  		if err != nil {
   310  			log.Fatalf("%v", err)
   311  		}
   312  		if err := pprof.StartCPUProfile(f); err != nil {
   313  			log.Fatalf("%v", err)
   314  		}
   315  		AtExit(pprof.StopCPUProfile)
   316  	}
   317  	if memprofile != "" {
   318  		f, err := os.Create(memprofile)
   319  		if err != nil {
   320  			log.Fatalf("%v", err)
   321  		}
   322  		AtExit(func() {
   323  			if err := pprof.WriteHeapProfile(f); err != nil {
   324  				log.Fatalf("%v", err)
   325  			}
   326  		})
   327  	}
   328  }
   329  
   330  func artrim(x []byte) string {
   331  	i := 0
   332  	j := len(x)
   333  	for i < len(x) && x[i] == ' ' {
   334  		i++
   335  	}
   336  	for j > i && x[j-1] == ' ' {
   337  		j--
   338  	}
   339  	return string(x[i:j])
   340  }
   341  
   342  func stringtouint32(x []uint32, s string) {
   343  	for i := 0; len(s) > 0; i++ {
   344  		var buf [4]byte
   345  		s = s[copy(buf[:], s):]
   346  		x[i] = binary.LittleEndian.Uint32(buf[:])
   347  	}
   348  }
   349  
   350  var start = time.Now()
   351  
   352  func elapsed() float64 {
   353  	return time.Since(start).Seconds()
   354  }