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 }