blob: da9e94f55f7566fc6dad4feae3fe8ba4a9b349e7 [file] [log] [blame]
Visweswara Ra5c9d582018-11-28 16:24:42 +05301// 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.
4
5// +build ignore
6
7package main
8
9import (
10 "bufio"
11 "fmt"
12 "os"
13 "os/exec"
14 "regexp"
15 "strconv"
16 "strings"
17)
18
19var (
20 goos, goarch string
21)
22
23// cmdLine returns this programs's commandline arguments
24func cmdLine() string {
25 return "go run linux/mksysnum.go " + strings.Join(os.Args[1:], " ")
26}
27
Tobias Klauser68d13332021-03-08 11:20:37 +010028// goBuildTags returns build tags in the go:build format.
29func goBuildTags() string {
30 return fmt.Sprintf("%s && %s", goarch, goos)
31}
32
33// plusBuildTags returns build tags in the +build format.
34func plusBuildTags() string {
Visweswara Ra5c9d582018-11-28 16:24:42 +053035 return fmt.Sprintf("%s,%s", goarch, goos)
36}
37
38func format(name string, num int, offset int) string {
39 if num > 999 {
40 // ignore deprecated syscalls that are no longer implemented
41 // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h?id=refs/heads/master#n716
42 return ""
43 }
44 name = strings.ToUpper(name)
45 num = num + offset
46 return fmt.Sprintf(" SYS_%s = %d;\n", name, num)
47}
48
49func checkErr(err error) {
50 if err != nil {
51 fmt.Fprintf(os.Stderr, "%v\n", err)
52 os.Exit(1)
53 }
54}
55
56// source string and substring slice for regexp
57type re struct {
58 str string // source string
59 sub []string // matched sub-string
60}
61
62// Match performs regular expression match
63func (r *re) Match(exp string) bool {
64 r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
65 if r.sub != nil {
66 return true
67 }
68 return false
69}
70
71func main() {
72 // Get the OS and architecture (using GOARCH_TARGET if it exists)
73 goos = os.Getenv("GOOS")
74 goarch = os.Getenv("GOARCH_TARGET")
75 if goarch == "" {
76 goarch = os.Getenv("GOARCH")
77 }
78 // Check if GOOS and GOARCH environment variables are defined
79 if goarch == "" || goos == "" {
80 fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
81 os.Exit(1)
82 }
83 // Check that we are using the new build system if we should
84 if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
85 fmt.Fprintf(os.Stderr, "In the new build system, mksysnum should not be called directly.\n")
86 fmt.Fprintf(os.Stderr, "See README.md\n")
87 os.Exit(1)
88 }
89
90 cc := os.Getenv("CC")
91 if cc == "" {
92 fmt.Fprintf(os.Stderr, "CC is not defined in environment\n")
93 os.Exit(1)
94 }
95 args := os.Args[1:]
96 args = append([]string{"-E", "-dD"}, args...)
97 cmd, err := exec.Command(cc, args...).Output() // execute command and capture output
98 if err != nil {
99 fmt.Fprintf(os.Stderr, "can't run %s", cc)
100 os.Exit(1)
101 }
102 text := ""
103 s := bufio.NewScanner(strings.NewReader(string(cmd)))
104 var offset, prev int
105 for s.Scan() {
106 t := re{str: s.Text()}
107 if t.Match(`^#define __NR_Linux\s+([0-9]+)`) {
108 // mips/mips64: extract offset
109 offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
110 } else if t.Match(`^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)`) {
111 // arm: extract offset
112 offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
113 } else if t.Match(`^#define __NR_syscalls\s+`) {
114 // ignore redefinitions of __NR_syscalls
115 } else if t.Match(`^#define __NR_(\w*)Linux_syscalls\s+`) {
116 // mips/mips64: ignore definitions about the number of syscalls
117 } else if t.Match(`^#define __NR_(\w+)\s+([0-9]+)`) {
118 prev, err = strconv.Atoi(t.sub[2])
119 checkErr(err)
120 text += format(t.sub[1], prev, offset)
121 } else if t.Match(`^#define __NR3264_(\w+)\s+([0-9]+)`) {
122 prev, err = strconv.Atoi(t.sub[2])
123 checkErr(err)
124 text += format(t.sub[1], prev, offset)
125 } else if t.Match(`^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)`) {
126 r2, err := strconv.Atoi(t.sub[2])
127 checkErr(err)
128 text += format(t.sub[1], prev+r2, offset)
129 } else if t.Match(`^#define __NR_(\w+)\s+\(__NR_(?:SYSCALL_BASE|Linux) \+ ([0-9]+)`) {
130 r2, err := strconv.Atoi(t.sub[2])
131 checkErr(err)
132 text += format(t.sub[1], r2, offset)
133 }
134 }
135 err = s.Err()
136 checkErr(err)
Tobias Klauser68d13332021-03-08 11:20:37 +0100137 fmt.Printf(template, cmdLine(), goBuildTags(), plusBuildTags(), text)
Visweswara Ra5c9d582018-11-28 16:24:42 +0530138}
139
140const template = `// %s
141// Code generated by the command above; see README.md. DO NOT EDIT.
142
Tobias Klauser68d13332021-03-08 11:20:37 +0100143//go:build %s
Visweswara Ra5c9d582018-11-28 16:24:42 +0530144// +build %s
145
146package unix
147
148const(
149%s)`