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