github.com/zhongdalu/gf@v1.0.0/third/golang.org/x/sys/unix/mksyscall_aix_ppc.go (about)

     1  // Copyright 2019 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  // +build ignore
     6  
     7  /*
     8  This program reads a file containing function prototypes
     9  (like syscall_aix.go) and generates system call bodies.
    10  The prototypes are marked by lines beginning with "//sys"
    11  and read like func declarations if //sys is replaced by func, but:
    12  	* The parameter lists must give a name for each argument.
    13  	  This includes return parameters.
    14  	* The parameter lists must give a type for each argument:
    15  	  the (x, y, z int) shorthand is not allowed.
    16  	* If the return parameter is an error number, it must be named err.
    17  	* If go func name needs to be different than its libc name,
    18  	* or the function is not in libc, name could be specified
    19  	* at the end, after "=" sign, like
    20  	  //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
    21  */
    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  // cmdLine returns this programs's commandline arguments
    41  func cmdLine() string {
    42  	return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
    43  }
    44  
    45  // buildTags returns build tags
    46  func buildTags() string {
    47  	return *tags
    48  }
    49  
    50  // Param is function parameter
    51  type Param struct {
    52  	Name string
    53  	Type string
    54  }
    55  
    56  // usage prints the program usage
    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  // parseParamList parses parameter list and returns a slice of parameters
    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  // parseParam splits a parameter into name and type
    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  			t = strings.TrimSpace(t)
   109  			t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
   110  			if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
   111  				pack = p[1]
   112  			}
   113  			nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
   114  			if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
   115  				continue
   116  			}
   117  
   118  			// Line must be of the form
   119  			//	func Open(path string, mode int, perm int) (fd int, err error)
   120  			// Split into name, in params, out params.
   121  			f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
   122  			if f == nil {
   123  				fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
   124  				os.Exit(1)
   125  			}
   126  			funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
   127  
   128  			// Split argument lists on comma.
   129  			in := parseParamList(inps)
   130  			out := parseParamList(outps)
   131  
   132  			inps = strings.Join(in, ", ")
   133  			outps = strings.Join(out, ", ")
   134  
   135  			// Try in vain to keep people from editing this file.
   136  			// The theory is that they jump into the middle of the file
   137  			// without reading the header.
   138  			text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
   139  
   140  			// Check if value return, err return available
   141  			errvar := ""
   142  			retvar := ""
   143  			rettype := ""
   144  			for _, param := range out {
   145  				p := parseParam(param)
   146  				if p.Type == "error" {
   147  					errvar = p.Name
   148  				} else {
   149  					retvar = p.Name
   150  					rettype = p.Type
   151  				}
   152  			}
   153  
   154  			// System call name.
   155  			if sysname == "" {
   156  				sysname = funct
   157  			}
   158  			sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
   159  			sysname = strings.ToLower(sysname) // All libc functions are lowercase.
   160  
   161  			cRettype := ""
   162  			if rettype == "unsafe.Pointer" {
   163  				cRettype = "uintptr_t"
   164  			} else if rettype == "uintptr" {
   165  				cRettype = "uintptr_t"
   166  			} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
   167  				cRettype = "uintptr_t"
   168  			} else if rettype == "int" {
   169  				cRettype = "int"
   170  			} else if rettype == "int32" {
   171  				cRettype = "int"
   172  			} else if rettype == "int64" {
   173  				cRettype = "long long"
   174  			} else if rettype == "uint32" {
   175  				cRettype = "unsigned int"
   176  			} else if rettype == "uint64" {
   177  				cRettype = "unsigned long long"
   178  			} else {
   179  				cRettype = "int"
   180  			}
   181  			if sysname == "exit" {
   182  				cRettype = "void"
   183  			}
   184  
   185  			// Change p.Types to c
   186  			var cIn []string
   187  			for _, param := range in {
   188  				p := parseParam(param)
   189  				if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
   190  					cIn = append(cIn, "uintptr_t")
   191  				} else if p.Type == "string" {
   192  					cIn = append(cIn, "uintptr_t")
   193  				} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
   194  					cIn = append(cIn, "uintptr_t", "size_t")
   195  				} else if p.Type == "unsafe.Pointer" {
   196  					cIn = append(cIn, "uintptr_t")
   197  				} else if p.Type == "uintptr" {
   198  					cIn = append(cIn, "uintptr_t")
   199  				} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
   200  					cIn = append(cIn, "uintptr_t")
   201  				} else if p.Type == "int" {
   202  					cIn = append(cIn, "int")
   203  				} else if p.Type == "int32" {
   204  					cIn = append(cIn, "int")
   205  				} else if p.Type == "int64" {
   206  					cIn = append(cIn, "long long")
   207  				} else if p.Type == "uint32" {
   208  					cIn = append(cIn, "unsigned int")
   209  				} else if p.Type == "uint64" {
   210  					cIn = append(cIn, "unsigned long long")
   211  				} else {
   212  					cIn = append(cIn, "int")
   213  				}
   214  			}
   215  
   216  			if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
   217  				// Imports of system calls from libc
   218  				cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
   219  				cIn := strings.Join(cIn, ", ")
   220  				cExtern += fmt.Sprintf("(%s);\n", cIn)
   221  			}
   222  
   223  			// So file name.
   224  			if *aix {
   225  				if modname == "" {
   226  					modname = "libc.a/shr_64.o"
   227  				} else {
   228  					fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
   229  					os.Exit(1)
   230  				}
   231  			}
   232  
   233  			strconvfunc := "C.CString"
   234  
   235  			// Go function header.
   236  			if outps != "" {
   237  				outps = fmt.Sprintf(" (%s)", outps)
   238  			}
   239  			if text != "" {
   240  				text += "\n"
   241  			}
   242  
   243  			text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
   244  
   245  			// Prepare arguments to Syscall.
   246  			var args []string
   247  			n := 0
   248  			argN := 0
   249  			for _, param := range in {
   250  				p := parseParam(param)
   251  				if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
   252  					args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
   253  				} else if p.Type == "string" && errvar != "" {
   254  					text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
   255  					args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
   256  					n++
   257  				} else if p.Type == "string" {
   258  					fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
   259  					text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
   260  					args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
   261  					n++
   262  				} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
   263  					// Convert slice into pointer, length.
   264  					// Have to be careful not to take address of &a[0] if len == 0:
   265  					// pass nil in that case.
   266  					text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
   267  					text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
   268  					args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
   269  					n++
   270  					text += fmt.Sprintf("\tvar _p%d int\n", n)
   271  					text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
   272  					args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
   273  					n++
   274  				} else if p.Type == "int64" && endianness != "" {
   275  					if endianness == "big-endian" {
   276  						args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
   277  					} else {
   278  						args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
   279  					}
   280  					n++
   281  				} else if p.Type == "bool" {
   282  					text += fmt.Sprintf("\tvar _p%d uint32\n", n)
   283  					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)
   284  					args = append(args, fmt.Sprintf("_p%d", n))
   285  				} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
   286  					args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
   287  				} else if p.Type == "unsafe.Pointer" {
   288  					args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
   289  				} else if p.Type == "int" {
   290  					if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
   291  						args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
   292  					} else if argN == 0 && funct == "fcntl" {
   293  						args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
   294  					} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
   295  						args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
   296  					} else {
   297  						args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
   298  					}
   299  				} else if p.Type == "int32" {
   300  					args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
   301  				} else if p.Type == "int64" {
   302  					args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
   303  				} else if p.Type == "uint32" {
   304  					args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
   305  				} else if p.Type == "uint64" {
   306  					args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
   307  				} else if p.Type == "uintptr" {
   308  					args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
   309  				} else {
   310  					args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
   311  				}
   312  				argN++
   313  			}
   314  
   315  			// Actual call.
   316  			arglist := strings.Join(args, ", ")
   317  			call := ""
   318  			if sysname == "exit" {
   319  				if errvar != "" {
   320  					call += "er :="
   321  				} else {
   322  					call += ""
   323  				}
   324  			} else if errvar != "" {
   325  				call += "r0,er :="
   326  			} else if retvar != "" {
   327  				call += "r0,_ :="
   328  			} else {
   329  				call += ""
   330  			}
   331  			call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
   332  
   333  			// Assign return values.
   334  			body := ""
   335  			for i := 0; i < len(out); i++ {
   336  				p := parseParam(out[i])
   337  				reg := ""
   338  				if p.Name == "err" {
   339  					reg = "e1"
   340  				} else {
   341  					reg = "r0"
   342  				}
   343  				if reg != "e1" {
   344  					body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
   345  				}
   346  			}
   347  
   348  			// verify return
   349  			if sysname != "exit" && errvar != "" {
   350  				if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
   351  					body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
   352  					body += fmt.Sprintf("\t\t%s = er\n", errvar)
   353  					body += "\t}\n"
   354  				} else {
   355  					body += "\tif (r0 ==-1 && er != nil) {\n"
   356  					body += fmt.Sprintf("\t\t%s = er\n", errvar)
   357  					body += "\t}\n"
   358  				}
   359  			} else if errvar != "" {
   360  				body += "\tif (er != nil) {\n"
   361  				body += fmt.Sprintf("\t\t%s = er\n", errvar)
   362  				body += "\t}\n"
   363  			}
   364  
   365  			text += fmt.Sprintf("\t%s\n", call)
   366  			text += body
   367  
   368  			text += "\treturn\n"
   369  			text += "}\n"
   370  		}
   371  		if err := s.Err(); err != nil {
   372  			fmt.Fprintf(os.Stderr, err.Error())
   373  			os.Exit(1)
   374  		}
   375  		file.Close()
   376  	}
   377  	imp := ""
   378  	if pack != "unix" {
   379  		imp = "import \"github.com/zhongdalu/gf/third/golang.org/x/sys/unix\"\n"
   380  
   381  	}
   382  	fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
   383  }
   384  
   385  const srcTemplate = `// %s
   386  // Code generated by the command above; see README.md. DO NOT EDIT.
   387  
   388  // +build %s
   389  
   390  package %s
   391  
   392  
   393  %s
   394  */
   395  import "C"
   396  import (
   397  	"unsafe"
   398  )
   399  
   400  
   401  %s
   402  
   403  %s
   404  `