github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/util.go (about)

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