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