1
2
3
4
5
6
7
61
62 package main
63
64 import (
65 "bufio"
66 "flag"
67 "fmt"
68 "os"
69 "regexp"
70 "strings"
71 )
72
73 var (
74 b32 = flag.Bool("b32", false, "32bit big-endian")
75 l32 = flag.Bool("l32", false, "32bit little-endian")
76 aix = flag.Bool("aix", false, "aix")
77 tags = flag.String("tags", "", "build tags")
78 )
79
80
81 func cmdLine() string {
82 return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
83 }
84
85
86 func goBuildTags() string {
87 return strings.ReplaceAll(*tags, ",", " && ")
88 }
89
90
91 type Param struct {
92 Name string
93 Type string
94 }
95
96
97 func usage() {
98 fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
99 os.Exit(1)
100 }
101
102
103 func parseParamList(list string) []string {
104 list = strings.TrimSpace(list)
105 if list == "" {
106 return []string{}
107 }
108 return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
109 }
110
111
112 func parseParam(p string) Param {
113 ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
114 if ps == nil {
115 fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
116 os.Exit(1)
117 }
118 return Param{ps[1], ps[2]}
119 }
120
121 func main() {
122 flag.Usage = usage
123 flag.Parse()
124 if len(flag.Args()) <= 0 {
125 fmt.Fprintf(os.Stderr, "no files to parse provided\n")
126 usage()
127 }
128
129 endianness := ""
130 if *b32 {
131 endianness = "big-endian"
132 } else if *l32 {
133 endianness = "little-endian"
134 }
135
136 pack := ""
137
138 textgccgo := ""
139 cExtern := "/*\n#include <stdint.h>\n"
140
141 textgc := ""
142 dynimports := ""
143 linknames := ""
144 var vars []string
145
146 textcommon := ""
147 for _, path := range flag.Args() {
148 file, err := os.Open(path)
149 if err != nil {
150 fmt.Fprintf(os.Stderr, err.Error())
151 os.Exit(1)
152 }
153 s := bufio.NewScanner(file)
154 for s.Scan() {
155 t := s.Text()
156 if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
157 pack = p[1]
158 }
159 nonblock := regexp.MustCompile(`^\/\/sysnb\t`).FindStringSubmatch(t)
160 if regexp.MustCompile(`^\/\/sys\t`).FindStringSubmatch(t) == nil && nonblock == nil {
161 continue
162 }
163
164
165
166
167 f := regexp.MustCompile(`^\/\/sys(nb)?\t(\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
168 if f == nil {
169 fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
170 os.Exit(1)
171 }
172 funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
173
174
175 in := parseParamList(inps)
176 out := parseParamList(outps)
177
178 inps = strings.Join(in, ", ")
179 outps = strings.Join(out, ", ")
180
181 if sysname == "" {
182 sysname = funct
183 }
184
185 onlyCommon := false
186 if funct == "FcntlInt" || funct == "FcntlFlock" || funct == "ioctlPtr" {
187
188
189 onlyCommon = true
190 }
191
192
193
194
195
196 textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
197 if !onlyCommon {
198 textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
199 textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
200 }
201
202
203 errvar := ""
204 rettype := ""
205 for _, param := range out {
206 p := parseParam(param)
207 if p.Type == "error" {
208 errvar = p.Name
209 } else {
210 rettype = p.Type
211 }
212 }
213
214 sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
215 sysname = strings.ToLower(sysname)
216
217
218 cRettype := ""
219 if rettype == "unsafe.Pointer" {
220 cRettype = "uintptr_t"
221 } else if rettype == "uintptr" {
222 cRettype = "uintptr_t"
223 } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
224 cRettype = "uintptr_t"
225 } else if rettype == "int" {
226 cRettype = "int"
227 } else if rettype == "int32" {
228 cRettype = "int"
229 } else if rettype == "int64" {
230 cRettype = "long long"
231 } else if rettype == "uint32" {
232 cRettype = "unsigned int"
233 } else if rettype == "uint64" {
234 cRettype = "unsigned long long"
235 } else {
236 cRettype = "int"
237 }
238 if sysname == "exit" {
239 cRettype = "void"
240 }
241
242
243 var cIn []string
244 for i, param := range in {
245 p := parseParam(param)
246 if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
247 cIn = append(cIn, "uintptr_t")
248 } else if p.Type == "string" {
249 cIn = append(cIn, "uintptr_t")
250 } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
251 cIn = append(cIn, "uintptr_t", "size_t")
252 } else if p.Type == "unsafe.Pointer" {
253 cIn = append(cIn, "uintptr_t")
254 } else if p.Type == "uintptr" {
255 cIn = append(cIn, "uintptr_t")
256 } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
257 cIn = append(cIn, "uintptr_t")
258 } else if p.Type == "int" {
259 if (i == 0 || i == 2) && funct == "fcntl" {
260
261 cIn = append(cIn, "uintptr_t")
262 } else {
263 cIn = append(cIn, "int")
264 }
265
266 } else if p.Type == "int32" {
267 cIn = append(cIn, "int")
268 } else if p.Type == "int64" {
269 cIn = append(cIn, "long long")
270 } else if p.Type == "uint32" {
271 cIn = append(cIn, "unsigned int")
272 } else if p.Type == "uint64" {
273 cIn = append(cIn, "unsigned long long")
274 } else {
275 cIn = append(cIn, "int")
276 }
277 }
278
279 if !onlyCommon {
280
281
282 if sysname == "select" {
283
284
285 cExtern += "#define c_select select\n"
286 }
287 cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
288 cIn := strings.Join(cIn, ", ")
289 cExtern += fmt.Sprintf("(%s);\n", cIn)
290 }
291
292 if modname == "" {
293 modname = "libc.a/shr_64.o"
294 } else {
295 fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
296 os.Exit(1)
297 }
298 sysvarname := fmt.Sprintf("libc_%s", sysname)
299
300 if !onlyCommon {
301
302 dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
303
304 linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
305
306 vars = append(vars, sysvarname)
307 }
308
309 strconvfunc := "BytePtrFromString"
310 strconvtype := "*byte"
311
312
313 if outps != "" {
314 outps = fmt.Sprintf(" (%s)", outps)
315 }
316 if textcommon != "" {
317 textcommon += "\n"
318 }
319
320 textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
321
322
323 var argscommon []string
324 var argscall []string
325 var argsgc []string
326 var argsgccgo []string
327 n := 0
328 argN := 0
329 for _, param := range in {
330 p := parseParam(param)
331 if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
332 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
333 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
334 argsgc = append(argsgc, p.Name)
335 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
336 } else if p.Type == "string" && errvar != "" {
337 textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
338 textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
339 textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
340
341 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
342 argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
343 argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
344 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
345 n++
346 } else if p.Type == "string" {
347 fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
348 textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
349 textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
350 textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
351
352 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
353 argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
354 argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
355 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
356 n++
357 } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
358
359
360
361 textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
362 textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
363 argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
364 argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
365 argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
366 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
367 n++
368 } else if p.Type == "int64" && endianness != "" {
369 fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
370 } else if p.Type == "bool" {
371 fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
372 } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
373 argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
374 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
375 argsgc = append(argsgc, p.Name)
376 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
377 } else if p.Type == "int" {
378 if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
379
380 argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
381 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
382 argsgc = append(argsgc, p.Name)
383 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
384
385 } else {
386 argscommon = append(argscommon, p.Name)
387 argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
388 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
389 argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
390 }
391 } else if p.Type == "int32" {
392 argscommon = append(argscommon, p.Name)
393 argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
394 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
395 argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
396 } else if p.Type == "int64" {
397 argscommon = append(argscommon, p.Name)
398 argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
399 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
400 argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
401 } else if p.Type == "uint32" {
402 argscommon = append(argscommon, p.Name)
403 argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
404 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
405 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
406 } else if p.Type == "uint64" {
407 argscommon = append(argscommon, p.Name)
408 argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
409 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
410 argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
411 } else if p.Type == "uintptr" {
412 argscommon = append(argscommon, p.Name)
413 argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
414 argsgc = append(argsgc, p.Name)
415 argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
416 } else {
417 argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
418 argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
419 argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
420 argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
421 }
422 argN++
423 }
424 nargs := len(argsgc)
425
426
427 argscommonlist := strings.Join(argscommon, ", ")
428 callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
429 ret := []string{"_", "_"}
430 body := ""
431 doErrno := false
432 for i := 0; i < len(out); i++ {
433 p := parseParam(out[i])
434 reg := ""
435 if p.Name == "err" {
436 reg = "e1"
437 ret[1] = reg
438 doErrno = true
439 } else {
440 reg = "r0"
441 ret[0] = reg
442 }
443 if p.Type == "bool" {
444 reg = fmt.Sprintf("%s != 0", reg)
445 }
446 if reg != "e1" {
447 body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
448 }
449 }
450 if ret[0] == "_" && ret[1] == "_" {
451 textcommon += fmt.Sprintf("\t%s\n", callcommon)
452 } else {
453 textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
454 }
455 textcommon += body
456
457 if doErrno {
458 textcommon += "\tif e1 != 0 {\n"
459 textcommon += "\t\terr = errnoErr(e1)\n"
460 textcommon += "\t}\n"
461 }
462 textcommon += "\treturn\n"
463 textcommon += "}\n"
464
465 if onlyCommon {
466 continue
467 }
468
469
470 callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
471
472
473 asm := "syscall6"
474 if nonblock != nil {
475 asm = "rawSyscall6"
476 }
477
478 if len(argsgc) <= 6 {
479 for len(argsgc) < 6 {
480 argsgc = append(argsgc, "0")
481 }
482 } else {
483 fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
484 os.Exit(1)
485 }
486 argsgclist := strings.Join(argsgc, ", ")
487 callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
488
489 textgc += callProto
490 textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
491 textgc += "\treturn\n}\n"
492
493
494 argsgccgolist := strings.Join(argsgccgo, ", ")
495 var callgccgo string
496 if sysname == "select" {
497
498
499 callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
500 } else {
501 callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
502 }
503 textgccgo += callProto
504 textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
505 textgccgo += "\te1 = syscall.GetErrno()\n"
506 textgccgo += "\treturn\n}\n"
507 }
508 if err := s.Err(); err != nil {
509 fmt.Fprintf(os.Stderr, err.Error())
510 os.Exit(1)
511 }
512 file.Close()
513 }
514 imp := ""
515 if pack != "unix" {
516 imp = "import \"golang.org/x/sys/unix\"\n"
517
518 }
519
520
521 err := os.WriteFile("zsyscall_aix_ppc64.go",
522 []byte(fmt.Sprintf(srcTemplate1, cmdLine(), goBuildTags(), pack, imp, textcommon)),
523 0644)
524 if err != nil {
525 fmt.Fprintf(os.Stderr, err.Error())
526 os.Exit(1)
527 }
528
529
530 vardecls := "\t" + strings.Join(vars, ",\n\t")
531 vardecls += " syscallFunc"
532 err = os.WriteFile("zsyscall_aix_ppc64_gc.go",
533 []byte(fmt.Sprintf(srcTemplate2, cmdLine(), goBuildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
534 0644)
535 if err != nil {
536 fmt.Fprintf(os.Stderr, err.Error())
537 os.Exit(1)
538 }
539
540
541 err = os.WriteFile("zsyscall_aix_ppc64_gccgo.go",
542 []byte(fmt.Sprintf(srcTemplate3, cmdLine(), goBuildTags(), pack, cExtern, imp, textgccgo)),
543 0644)
544 if err != nil {
545 fmt.Fprintf(os.Stderr, err.Error())
546 os.Exit(1)
547 }
548 }
549
550 const srcTemplate1 = `// %s
551 // Code generated by the command above; see README.md. DO NOT EDIT.
552
553 //go:build %s
554
555 package %s
556
557 import (
558 "unsafe"
559 )
560
561
562 %s
563
564 %s
565 `
566 const srcTemplate2 = `// %s
567 // Code generated by the command above; see README.md. DO NOT EDIT.
568
569 //go:build %s && gc
570
571 package %s
572
573 import (
574 "unsafe"
575 )
576 %s
577 %s
578 %s
579 type syscallFunc uintptr
580
581 var (
582 %s
583 )
584
585 // Implemented in runtime/syscall_aix.go.
586 func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
587 func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
588
589 %s
590 `
591 const srcTemplate3 = `// %s
592 // Code generated by the command above; see README.md. DO NOT EDIT.
593
594 //go:build %s && gccgo
595
596 package %s
597
598 %s
599 */
600 import "C"
601 import (
602 "syscall"
603 )
604
605
606 %s
607
608 %s
609 `
610
View as plain text