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