1
2
3
4
5
6
7
8
9
10 package main
11
12 import (
13 "bufio"
14 "fmt"
15 "io"
16 "net/http"
17 "os"
18 "regexp"
19 "strings"
20 )
21
22 var (
23 goos, goarch string
24 )
25
26
27 func cmdLine() string {
28 return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
29 }
30
31
32 func goBuildTags() string {
33 return fmt.Sprintf("%s && %s", goarch, goos)
34 }
35
36 func checkErr(err error) {
37 if err != nil {
38 fmt.Fprintf(os.Stderr, "%v\n", err)
39 os.Exit(1)
40 }
41 }
42
43
44 type re struct {
45 str string
46 sub []string
47 }
48
49
50 func (r *re) Match(exp string) bool {
51 r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
52 if r.sub != nil {
53 return true
54 }
55 return false
56 }
57
58
59 func fetchFile(URL string) io.Reader {
60 resp, err := http.Get(URL)
61 checkErr(err)
62 defer resp.Body.Close()
63 body, err := io.ReadAll(resp.Body)
64 checkErr(err)
65 return strings.NewReader(string(body))
66 }
67
68
69 func readFile(path string) io.Reader {
70 file, err := os.Open(os.Args[1])
71 checkErr(err)
72 return file
73 }
74
75 func format(name, num, proto string) string {
76 name = strings.ToUpper(name)
77
78 nm := re{str: name}
79 if nm.Match(`^SYS_E?NOSYS$`) {
80 name = fmt.Sprintf("// %s", name)
81 }
82 if name == `SYS_SYS_EXIT` {
83 name = `SYS_EXIT`
84 }
85 return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
86 }
87
88 func main() {
89
90 goos = os.Getenv("GOOS_TARGET")
91 if goos == "" {
92 goos = os.Getenv("GOOS")
93 }
94
95 goarch = os.Getenv("GOARCH_TARGET")
96 if goarch == "" {
97 goarch = os.Getenv("GOARCH")
98 }
99
100 if goarch == "" || goos == "" {
101 fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
102 os.Exit(1)
103 }
104
105 file := strings.TrimSpace(os.Args[1])
106 var syscalls io.Reader
107 if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
108
109 syscalls = fetchFile(file)
110 } else {
111 syscalls = readFile(file)
112 }
113
114 var text, line string
115 s := bufio.NewScanner(syscalls)
116 for s.Scan() {
117 t := re{str: line}
118 if t.Match(`^(.*)\\$`) {
119
120 line = t.sub[1]
121 line += strings.TrimLeft(s.Text(), " \t")
122 } else {
123
124 line = s.Text()
125 }
126 t = re{str: line}
127 if t.Match(`\\$`) {
128 continue
129 }
130 t = re{str: line}
131
132 switch goos {
133 case "dragonfly":
134 if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
135 num, proto := t.sub[1], t.sub[2]
136 name := fmt.Sprintf("SYS_%s", t.sub[3])
137 text += format(name, num, proto)
138 }
139 case "freebsd":
140 if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD)\s+({ \S+\s+(\w+).*)$`) {
141 num, proto := t.sub[1], t.sub[2]
142 name := fmt.Sprintf("SYS_%s", t.sub[3])
143
144 proto = regexp.MustCompile(`\( `).ReplaceAllString(proto, "(")
145 proto = regexp.MustCompile(` \)`).ReplaceAllString(proto, ")")
146
147 proto = regexp.MustCompile(`_In[^ ]*[_)] `).ReplaceAllString(proto, "")
148 proto = regexp.MustCompile(`_Out[^ ]*[_)] `).ReplaceAllString(proto, "")
149
150 proto = regexp.MustCompile(`\s{2}`).ReplaceAllString(proto, " ")
151 text += format(name, num, proto)
152 }
153 case "openbsd":
154 if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
155 num, proto, name := t.sub[1], t.sub[3], t.sub[4]
156 text += format(name, num, proto)
157 }
158 case "netbsd":
159 if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
160 num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
161 name := t.sub[7] + "_" + t.sub[9]
162 if t.sub[11] != "" {
163 name = t.sub[7] + "_" + t.sub[11]
164 }
165 name = strings.ToUpper(name)
166 if compat == "" || compat == "13" || compat == "30" || compat == "50" {
167 text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
168 }
169 }
170 default:
171 fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
172 os.Exit(1)
173
174 }
175 }
176 err := s.Err()
177 checkErr(err)
178
179 fmt.Printf(template, cmdLine(), goBuildTags(), text)
180 }
181
182 const template = `// %s
183 // Code generated by the command above; see README.md. DO NOT EDIT.
184
185 //go:build %s
186
187 package unix
188
189 const(
190 %s)`
191
View as plain text