1
2
3
4
5
6
7
22 package main
23
24 import (
25 "bufio"
26 "flag"
27 "fmt"
28 "os"
29 "regexp"
30 "strings"
31 )
32
33 var (
34 b32 = flag.Bool("b32", false, "32bit big-endian")
35 l32 = flag.Bool("l32", false, "32bit little-endian")
36 aix = flag.Bool("aix", false, "aix")
37 tags = flag.String("tags", "", "build tags")
38 )
39
40
41 func cmdLine() string {
42 return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
43 }
44
45
46 func goBuildTags() string {
47 return strings.ReplaceAll(*tags, ",", " && ")
48 }
49
50
51 type Param struct {
52 Name string
53 Type string
54 }
55
56
57 func usage() {
58 fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
59 os.Exit(1)
60 }
61
62
63 func parseParamList(list string) []string {
64 list = strings.TrimSpace(list)
65 if list == "" {
66 return []string{}
67 }
68 return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
69 }
70
71
72 func parseParam(p string) Param {
73 ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
74 if ps == nil {
75 fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
76 os.Exit(1)
77 }
78 return Param{ps[1], ps[2]}
79 }
80
81 func main() {
82 flag.Usage = usage
83 flag.Parse()
84 if len(flag.Args()) <= 0 {
85 fmt.Fprintf(os.Stderr, "no files to parse provided\n")
86 usage()
87 }
88
89 endianness := ""
90 if *b32 {
91 endianness = "big-endian"
92 } else if *l32 {
93 endianness = "little-endian"
94 }
95
96 pack := ""
97 text := ""
98 cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
99 for _, path := range flag.Args() {
100 file, err := os.Open(path)
101 if err != nil {
102 fmt.Fprintf(os.Stderr, err.Error())
103 os.Exit(1)
104 }
105 s := bufio.NewScanner(file)
106 for s.Scan() {
107 t := s.Text()
108 if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
109 pack = p[1]
110 }
111 nonblock := regexp.MustCompile(`^\/\/sysnb\t`).FindStringSubmatch(t)
112 if regexp.MustCompile(`^\/\/sys\t`).FindStringSubmatch(t) == nil && nonblock == nil {
113 continue
114 }
115
116
117
118
119 f := regexp.MustCompile(`^\/\/sys(nb)?\t(\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
120 if f == nil {
121 fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
122 os.Exit(1)
123 }
124 funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
125
126
127 in := parseParamList(inps)
128 out := parseParamList(outps)
129
130 inps = strings.Join(in, ", ")
131 outps = strings.Join(out, ", ")
132
133
134
135
136 text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
137
138
139 errvar := ""
140 retvar := ""
141 rettype := ""
142 for _, param := range out {
143 p := parseParam(param)
144 if p.Type == "error" {
145 errvar = p.Name
146 } else {
147 retvar = p.Name
148 rettype = p.Type
149 }
150 }
151
152
153 if sysname == "" {
154 sysname = funct
155 }
156 sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
157 sysname = strings.ToLower(sysname)
158
159 cRettype := ""
160 if rettype == "unsafe.Pointer" {
161 cRettype = "uintptr_t"
162 } else if rettype == "uintptr" {
163 cRettype = "uintptr_t"
164 } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
165 cRettype = "uintptr_t"
166 } else if rettype == "int" {
167 cRettype = "int"
168 } else if rettype == "int32" {
169 cRettype = "int"
170 } else if rettype == "int64" {
171 cRettype = "long long"
172 } else if rettype == "uint32" {
173 cRettype = "unsigned int"
174 } else if rettype == "uint64" {
175 cRettype = "unsigned long long"
176 } else {
177 cRettype = "int"
178 }
179 if sysname == "exit" {
180 cRettype = "void"
181 }
182
183
184 var cIn []string
185 for _, param := range in {
186 p := parseParam(param)
187 if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
188 cIn = append(cIn, "uintptr_t")
189 } else if p.Type == "string" {
190 cIn = append(cIn, "uintptr_t")
191 } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
192 cIn = append(cIn, "uintptr_t", "size_t")
193 } else if p.Type == "unsafe.Pointer" {
194 cIn = append(cIn, "uintptr_t")
195 } else if p.Type == "uintptr" {
196 cIn = append(cIn, "uintptr_t")
197 } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
198 cIn = append(cIn, "uintptr_t")
199 } else if p.Type == "int" {
200 cIn = append(cIn, "int")
201 } else if p.Type == "int32" {
202 cIn = append(cIn, "int")
203 } else if p.Type == "int64" {
204 cIn = append(cIn, "long long")
205 } else if p.Type == "uint32" {
206 cIn = append(cIn, "unsigned int")
207 } else if p.Type == "uint64" {
208 cIn = append(cIn, "unsigned long long")
209 } else {
210 cIn = append(cIn, "int")
211 }
212 }
213
214 if funct != "fcntl" && funct != "FcntlInt" && funct != "ioctlPtr" {
215 if sysname == "select" {
216
217
218 cExtern += "#define c_select select\n"
219 }
220
221 cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
222 cIn := strings.Join(cIn, ", ")
223 cExtern += fmt.Sprintf("(%s);\n", cIn)
224 }
225
226
227 if *aix {
228 if modname == "" {
229 modname = "libc.a/shr_64.o"
230 } else {
231 fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
232 os.Exit(1)
233 }
234 }
235
236 strconvfunc := "C.CString"
237
238
239 if outps != "" {
240 outps = fmt.Sprintf(" (%s)", outps)
241 }
242 if text != "" {
243 text += "\n"
244 }
245
246 text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
247
248
249 var args []string
250 n := 0
251 argN := 0
252 for _, param := range in {
253 p := parseParam(param)
254 if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
255 args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
256 } else if p.Type == "string" && errvar != "" {
257 text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
258 args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
259 n++
260 } else if p.Type == "string" {
261 fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
262 text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
263 args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
264 n++
265 } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
266
267
268
269 text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
270 text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
271 args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
272 n++
273 text += fmt.Sprintf("\tvar _p%d int\n", n)
274 text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
275 args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
276 n++
277 } else if p.Type == "int64" && endianness != "" {
278 if endianness == "big-endian" {
279 args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
280 } else {
281 args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
282 }
283 n++
284 } else if p.Type == "bool" {
285 text += fmt.Sprintf("\tvar _p%d uint32\n", n)
286 text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
287 args = append(args, fmt.Sprintf("_p%d", n))
288 } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
289 args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
290 } else if p.Type == "unsafe.Pointer" {
291 args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
292 } else if p.Type == "int" {
293 if argN == 0 && funct == "fcntl" {
294 args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
295 } else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
296 args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
297 } else {
298 args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
299 }
300 } else if p.Type == "int32" {
301 args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
302 } else if p.Type == "int64" {
303 args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
304 } else if p.Type == "uint32" {
305 args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
306 } else if p.Type == "uint64" {
307 args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
308 } else if p.Type == "uintptr" {
309 args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
310 } else {
311 args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
312 }
313 argN++
314 }
315
316
317 arglist := strings.Join(args, ", ")
318 call := ""
319 if sysname == "exit" {
320 if errvar != "" {
321 call += "er :="
322 } else {
323 call += ""
324 }
325 } else if errvar != "" {
326 call += "r0,er :="
327 } else if retvar != "" {
328 call += "r0,_ :="
329 } else {
330 call += ""
331 }
332 if sysname == "select" {
333
334
335 call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
336 } else {
337 call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
338 }
339
340
341 body := ""
342 for i := 0; i < len(out); i++ {
343 p := parseParam(out[i])
344 reg := ""
345 if p.Name == "err" {
346 reg = "e1"
347 } else {
348 reg = "r0"
349 }
350 if reg != "e1" {
351 body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
352 }
353 }
354
355
356 if sysname != "exit" && errvar != "" {
357 if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
358 body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
359 body += fmt.Sprintf("\t\t%s = er\n", errvar)
360 body += "\t}\n"
361 } else {
362 body += "\tif (r0 ==-1 && er != nil) {\n"
363 body += fmt.Sprintf("\t\t%s = er\n", errvar)
364 body += "\t}\n"
365 }
366 } else if errvar != "" {
367 body += "\tif (er != nil) {\n"
368 body += fmt.Sprintf("\t\t%s = er\n", errvar)
369 body += "\t}\n"
370 }
371
372 text += fmt.Sprintf("\t%s\n", call)
373 text += body
374
375 text += "\treturn\n"
376 text += "}\n"
377 }
378 if err := s.Err(); err != nil {
379 fmt.Fprintf(os.Stderr, err.Error())
380 os.Exit(1)
381 }
382 file.Close()
383 }
384 imp := ""
385 if pack != "unix" {
386 imp = "import \"golang.org/x/sys/unix\"\n"
387
388 }
389 fmt.Printf(srcTemplate, cmdLine(), goBuildTags(), pack, cExtern, imp, text)
390 }
391
392 const srcTemplate = `// %s
393 // Code generated by the command above; see README.md. DO NOT EDIT.
394
395 //go:build %s
396
397 package %s
398
399
400 %s
401 */
402 import "C"
403 import (
404 "unsafe"
405 )
406
407
408 %s
409
410 %s
411 `
412
View as plain text