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