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 }