github.com/nibnait/go-learn@v0.0.0-20220227013611-dfa47ea6d2da/src/pkg/mod/golang.org/x/sys@v0.0.0-20210630005230-0f9fa26af87c/unix/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 // Generate system call table for DragonFly, NetBSD, 9 // FreeBSD or OpenBSD from master list (for example, 10 // /usr/src/sys/kern/syscalls.master or sys/syscall.h). 11 package main 12 13 import ( 14 "bufio" 15 "fmt" 16 "io" 17 "io/ioutil" 18 "net/http" 19 "os" 20 "regexp" 21 "strings" 22 ) 23 24 var ( 25 goos, goarch string 26 ) 27 28 // cmdLine returns this programs's commandline arguments 29 func cmdLine() string { 30 return "go run mksysnum.go " + strings.Join(os.Args[1:], " ") 31 } 32 33 // goBuildTags returns build tags in the go:build format. 34 func goBuildTags() string { 35 return fmt.Sprintf("%s && %s", goarch, goos) 36 } 37 38 // plusBuildTags returns build tags in the +build format. 39 func plusBuildTags() string { 40 return fmt.Sprintf("%s,%s", goarch, goos) 41 } 42 43 func checkErr(err error) { 44 if err != nil { 45 fmt.Fprintf(os.Stderr, "%v\n", err) 46 os.Exit(1) 47 } 48 } 49 50 // source string and substring slice for regexp 51 type re struct { 52 str string // source string 53 sub []string // matched sub-string 54 } 55 56 // Match performs regular expression match 57 func (r *re) Match(exp string) bool { 58 r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str) 59 if r.sub != nil { 60 return true 61 } 62 return false 63 } 64 65 // fetchFile fetches a text file from URL 66 func fetchFile(URL string) io.Reader { 67 resp, err := http.Get(URL) 68 checkErr(err) 69 defer resp.Body.Close() 70 body, err := ioutil.ReadAll(resp.Body) 71 checkErr(err) 72 return strings.NewReader(string(body)) 73 } 74 75 // readFile reads a text file from path 76 func readFile(path string) io.Reader { 77 file, err := os.Open(os.Args[1]) 78 checkErr(err) 79 return file 80 } 81 82 func format(name, num, proto string) string { 83 name = strings.ToUpper(name) 84 // There are multiple entries for enosys and nosys, so comment them out. 85 nm := re{str: name} 86 if nm.Match(`^SYS_E?NOSYS$`) { 87 name = fmt.Sprintf("// %s", name) 88 } 89 if name == `SYS_SYS_EXIT` { 90 name = `SYS_EXIT` 91 } 92 return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) 93 } 94 95 func main() { 96 // Get the OS (using GOOS_TARGET if it exist) 97 goos = os.Getenv("GOOS_TARGET") 98 if goos == "" { 99 goos = os.Getenv("GOOS") 100 } 101 // Get the architecture (using GOARCH_TARGET if it exists) 102 goarch = os.Getenv("GOARCH_TARGET") 103 if goarch == "" { 104 goarch = os.Getenv("GOARCH") 105 } 106 // Check if GOOS and GOARCH environment variables are defined 107 if goarch == "" || goos == "" { 108 fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") 109 os.Exit(1) 110 } 111 112 file := strings.TrimSpace(os.Args[1]) 113 var syscalls io.Reader 114 if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") { 115 // Download syscalls.master file 116 syscalls = fetchFile(file) 117 } else { 118 syscalls = readFile(file) 119 } 120 121 var text, line string 122 s := bufio.NewScanner(syscalls) 123 for s.Scan() { 124 t := re{str: line} 125 if t.Match(`^(.*)\\$`) { 126 // Handle continuation 127 line = t.sub[1] 128 line += strings.TrimLeft(s.Text(), " \t") 129 } else { 130 // New line 131 line = s.Text() 132 } 133 t = re{str: line} 134 if t.Match(`\\$`) { 135 continue 136 } 137 t = re{str: line} 138 139 switch goos { 140 case "dragonfly": 141 if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) { 142 num, proto := t.sub[1], t.sub[2] 143 name := fmt.Sprintf("SYS_%s", t.sub[3]) 144 text += format(name, num, proto) 145 } 146 case "freebsd": 147 if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) { 148 num, proto := t.sub[1], t.sub[2] 149 name := fmt.Sprintf("SYS_%s", t.sub[3]) 150 text += format(name, num, proto) 151 } 152 case "openbsd": 153 if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) { 154 num, proto, name := t.sub[1], t.sub[3], t.sub[4] 155 text += format(name, num, proto) 156 } 157 case "netbsd": 158 if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) { 159 num, proto, compat := t.sub[1], t.sub[6], t.sub[8] 160 name := t.sub[7] + "_" + t.sub[9] 161 if t.sub[11] != "" { 162 name = t.sub[7] + "_" + t.sub[11] 163 } 164 name = strings.ToUpper(name) 165 if compat == "" || compat == "13" || compat == "30" || compat == "50" { 166 text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) 167 } 168 } 169 default: 170 fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos) 171 os.Exit(1) 172 173 } 174 } 175 err := s.Err() 176 checkErr(err) 177 178 fmt.Printf(template, cmdLine(), goBuildTags(), plusBuildTags(), text) 179 } 180 181 const template = `// %s 182 // Code generated by the command above; see README.md. DO NOT EDIT. 183 184 //go:build %s 185 // +build %s 186 187 package unix 188 189 const( 190 %s)`