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
5package ld
6
7import (
8	"cmd/link/internal/loader"
9	"encoding/binary"
10	"fmt"
11	"os"
12)
13
14var atExitFuncs []func()
15
16func AtExit(f func()) {
17	atExitFuncs = append(atExitFuncs, f)
18}
19
20// runAtExitFuncs runs the queued set of AtExit functions.
21func runAtExitFuncs() {
22	for i := len(atExitFuncs) - 1; i >= 0; i-- {
23		atExitFuncs[i]()
24	}
25	atExitFuncs = nil
26}
27
28// Exit exits with code after executing all atExitFuncs.
29func Exit(code int) {
30	runAtExitFuncs()
31	os.Exit(code)
32}
33
34// Exitf logs an error message then calls Exit(2).
35func Exitf(format string, a ...interface{}) {
36	fmt.Fprintf(os.Stderr, os.Args[0]+": "+format+"\n", a...)
37	nerrors++
38	if *flagH {
39		panic("error")
40	}
41	Exit(2)
42}
43
44// afterErrorAction updates 'nerrors' on error and invokes exit or
45// panics in the proper circumstances.
46func afterErrorAction() {
47	nerrors++
48	if *flagH {
49		panic("error")
50	}
51	if nerrors > 20 {
52		Exitf("too many errors")
53	}
54}
55
56// Errorf logs an error message.
57//
58// If more than 20 errors have been printed, exit with an error.
59//
60// Logging an error means that on exit cmd/link will delete any
61// output file and return a non-zero error code.
62//
63// TODO: remove. Use ctxt.Errorf instead.
64// All remaining calls use nil as first arg.
65func Errorf(dummy *int, format string, args ...interface{}) {
66	format += "\n"
67	fmt.Fprintf(os.Stderr, format, args...)
68	afterErrorAction()
69}
70
71// Errorf method logs an error message.
72//
73// If more than 20 errors have been printed, exit with an error.
74//
75// Logging an error means that on exit cmd/link will delete any
76// output file and return a non-zero error code.
77func (ctxt *Link) Errorf(s loader.Sym, format string, args ...interface{}) {
78	if ctxt.loader != nil {
79		ctxt.loader.Errorf(s, format, args...)
80		return
81	}
82	// Note: this is not expected to happen very often.
83	format = fmt.Sprintf("sym %d: %s", s, format)
84	format += "\n"
85	fmt.Fprintf(os.Stderr, format, args...)
86	afterErrorAction()
87}
88
89func artrim(x []byte) string {
90	i := 0
91	j := len(x)
92	for i < len(x) && x[i] == ' ' {
93		i++
94	}
95	for j > i && x[j-1] == ' ' {
96		j--
97	}
98	return string(x[i:j])
99}
100
101func stringtouint32(x []uint32, s string) {
102	for i := 0; len(s) > 0; i++ {
103		var buf [4]byte
104		s = s[copy(buf[:], s):]
105		x[i] = binary.LittleEndian.Uint32(buf[:])
106	}
107}
108
109// contains reports whether v is in s.
110func contains(s []string, v string) bool {
111	for _, x := range s {
112		if x == v {
113			return true
114		}
115	}
116	return false
117}
118