1 // Copyright 2018 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.
23 // cmdLine returns this programs's commandline arguments
24 func cmdLine() string {
25 return "go run linux/mksysnum.go " + strings.Join(os.Args[1:], " ")
28 // buildTags returns build tags
29 func buildTags() string {
30 return fmt.Sprintf("%s,%s", goarch, goos)
33 func format(name string, num int, offset int) string {
35 // ignore deprecated syscalls that are no longer implemented
36 // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h?id=refs/heads/master#n716
39 name = strings.ToUpper(name)
41 return fmt.Sprintf(" SYS_%s = %d;\n", name, num)
44 func checkErr(err error) {
46 fmt.Fprintf(os.Stderr, "%v\n", err)
51 // source string and substring slice for regexp
53 str string // source string
54 sub []string // matched sub-string
57 // Match performs regular expression match
58 func (r *re) Match(exp string) bool {
59 r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
67 // Get the OS and architecture (using GOARCH_TARGET if it exists)
68 goos = os.Getenv("GOOS")
69 goarch = os.Getenv("GOARCH_TARGET")
71 goarch = os.Getenv("GOARCH")
73 // Check if GOOS and GOARCH environment variables are defined
74 if goarch == "" || goos == "" {
75 fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
78 // Check that we are using the new build system if we should
79 if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
80 fmt.Fprintf(os.Stderr, "In the new build system, mksysnum should not be called directly.\n")
81 fmt.Fprintf(os.Stderr, "See README.md\n")
87 fmt.Fprintf(os.Stderr, "CC is not defined in environment\n")
91 args = append([]string{"-E", "-dD"}, args...)
92 cmd, err := exec.Command(cc, args...).Output() // execute command and capture output
94 fmt.Fprintf(os.Stderr, "can't run %s", cc)
98 s := bufio.NewScanner(strings.NewReader(string(cmd)))
101 t := re{str: s.Text()}
102 if t.Match(`^#define __NR_Linux\s+([0-9]+)`) {
103 // mips/mips64: extract offset
104 offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
105 } else if t.Match(`^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)`) {
106 // arm: extract offset
107 offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
108 } else if t.Match(`^#define __NR_syscalls\s+`) {
109 // ignore redefinitions of __NR_syscalls
110 } else if t.Match(`^#define __NR_(\w*)Linux_syscalls\s+`) {
111 // mips/mips64: ignore definitions about the number of syscalls
112 } else if t.Match(`^#define __NR_(\w+)\s+([0-9]+)`) {
113 prev, err = strconv.Atoi(t.sub[2])
115 text += format(t.sub[1], prev, offset)
116 } else if t.Match(`^#define __NR3264_(\w+)\s+([0-9]+)`) {
117 prev, err = strconv.Atoi(t.sub[2])
119 text += format(t.sub[1], prev, offset)
120 } else if t.Match(`^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)`) {
121 r2, err := strconv.Atoi(t.sub[2])
123 text += format(t.sub[1], prev+r2, offset)
124 } else if t.Match(`^#define __NR_(\w+)\s+\(__NR_(?:SYSCALL_BASE|Linux) \+ ([0-9]+)`) {
125 r2, err := strconv.Atoi(t.sub[2])
127 text += format(t.sub[1], r2, offset)
132 fmt.Printf(template, cmdLine(), buildTags(), text)
135 const template = `// %s
136 // Code generated by the command above; see README.md. DO NOT EDIT.