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