github.com/afumu/libc@v0.0.6/generate.go (about)

     1  //go:build ignore
     2  // +build ignore
     3  
     4  package main
     5  
     6  import (
     7  	"bufio"
     8  	"bytes"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"runtime"
    15  	"sort"
    16  	"strings"
    17  
    18  	ccgo "modernc.org/ccgo/v3/lib"
    19  )
    20  
    21  var (
    22  	goos   = runtime.GOOS
    23  	goarch = runtime.GOARCH
    24  )
    25  
    26  func origin(skip int) string {
    27  	pc, fn, fl, _ := runtime.Caller(skip)
    28  	f := runtime.FuncForPC(pc)
    29  	var fns string
    30  	if f != nil {
    31  		fns = f.Name()
    32  		if x := strings.LastIndex(fns, "."); x > 0 {
    33  			fns = fns[x+1:]
    34  		}
    35  	}
    36  	return fmt.Sprintf("%s:%d:%s", filepath.Base(fn), fl, fns)
    37  }
    38  
    39  func trc(s string, args ...interface{}) string { //TODO-
    40  	switch {
    41  	case s == "":
    42  		s = fmt.Sprintf(strings.Repeat("%v ", len(args)), args...)
    43  	default:
    44  		s = fmt.Sprintf(s, args...)
    45  	}
    46  	_, fn, fl, _ := runtime.Caller(1)
    47  	r := fmt.Sprintf("\n%s:%d: TRC %s", fn, fl, s)
    48  	fmt.Fprintf(os.Stdout, "%s\n", r)
    49  	os.Stdout.Sync()
    50  	return r
    51  }
    52  
    53  func main() {
    54  	fmt.Printf("Running on %s/%s.\n", runtime.GOOS, runtime.GOARCH)
    55  	if s := os.Getenv("TARGET_GOOS"); s != "" {
    56  		goos = s
    57  	}
    58  	if s := os.Getenv("TARGET_GOARCH"); s != "" {
    59  		goarch = s
    60  	}
    61  	g := []string{"libc.go", "mem.go"}
    62  	switch goos {
    63  	case "linux":
    64  		g = append(g, "libc_unix.go", "pthread.go", "pthread_all.go")
    65  		makeMuslLinux(goos, goarch)
    66  	case "freebsd":
    67  		g = append(g, "libc_unix.go", "pthread.go", "pthread_all.go")
    68  		makeMuslFreeBSD(goos, goarch)
    69  	case "netbsd":
    70  		g = append(g, "libc_unix.go", "pthread.go", "pthread_all.go")
    71  		makeMuslNetBSD(goos, goarch)
    72  	case "openbsd":
    73  		g = append(g, "libc_unix.go", "pthread.go", "pthread_all.go")
    74  		makeMuslOpenBSD(goos, goarch)
    75  	case "darwin":
    76  		g = append(g, "libc_unix.go", "pthread.go", "pthread_all.go")
    77  		makeMuslDarwin(goos, goarch)
    78  	case "windows":
    79  		g = append(g, "libc_windows.go")
    80  		makeMuslWin(goos, goarch)
    81  	}
    82  	_, _, hostSysIncludes, err := cc.HostConfig(os.Getenv("CCGO_CPP"))
    83  	if err != nil {
    84  		fail(err)
    85  	}
    86  
    87  	x, err := filepath.Glob(fmt.Sprintf("*_%s.go", goos))
    88  	if err != nil {
    89  		fail(err)
    90  	}
    91  
    92  	g = append(g, x...)
    93  	if x, err = filepath.Glob(fmt.Sprintf("*_%s_%s.go", goos, goarch)); err != nil {
    94  		fail(err)
    95  	}
    96  
    97  	g = append(g, x...)
    98  	m := map[string]struct{}{}
    99  	for _, v := range g {
   100  		f, err := os.Open(v)
   101  		if err != nil {
   102  			fail(err)
   103  		}
   104  
   105  		sc := bufio.NewScanner(f)
   106  		for sc.Scan() {
   107  			s := sc.Text()
   108  			s0 := s
   109  			switch {
   110  			case strings.HasPrefix(s, "func X"):
   111  				s = s[len("func X"):]
   112  				x := strings.IndexByte(s, '(')
   113  				s = s[:x]
   114  			case strings.HasPrefix(s, "var X"):
   115  				s = s[len("var X"):]
   116  				x := strings.IndexByte(s, ' ')
   117  				s = s[:x]
   118  			default:
   119  				continue
   120  			}
   121  
   122  			if s == "" {
   123  				panic(fmt.Sprintf("internal error %q", s0))
   124  			}
   125  			m[s] = struct{}{}
   126  		}
   127  		if err := sc.Err(); err != nil {
   128  			fail(err)
   129  		}
   130  
   131  		f.Close()
   132  	}
   133  	var a []string
   134  	for k := range m {
   135  		a = append(a, k)
   136  	}
   137  	sort.Strings(a)
   138  	b := bytes.NewBuffer(nil)
   139  	b.WriteString(`// Code generated by 'go generate' - DO NOT EDIT.
   140  
   141  package libc // import "github.com/afumu/libc"
   142  
   143  var CAPI = map[string]struct{}{`)
   144  
   145  	for _, v := range a {
   146  		fmt.Fprintf(b, "\n\t%q: {},", v)
   147  	}
   148  	b.WriteString("\n}")
   149  	if err := ioutil.WriteFile(fmt.Sprintf("capi_%s_%s.go", goos, goarch), b.Bytes(), 0660); err != nil {
   150  		fail(err)
   151  	}
   152  
   153  	ccgoHelpers()
   154  
   155  	if err := libcHeaders(hostSysIncludes); err != nil {
   156  		fail(err)
   157  	}
   158  }
   159  
   160  func makeMuslWin(goos, goarch string) {
   161  	if runtime.GOOS != "windows" {
   162  		switch goarch {
   163  		case "386":
   164  			makeMuslWin386(goos, goarch)
   165  			return
   166  		default:
   167  			fail(fmt.Errorf("must be runned on Windows"))
   168  		}
   169  	}
   170  
   171  	wd, err := os.Getwd()
   172  	if err != nil {
   173  		fail(err)
   174  	}
   175  
   176  	if err := os.Chdir("musl"); err != nil {
   177  		fail(err)
   178  	}
   179  
   180  	var arch string
   181  	switch goarch {
   182  	case "amd64":
   183  		arch = "x86_64"
   184  	case "386":
   185  		arch = "i386"
   186  	case "arm":
   187  		arch = "arm"
   188  	case "arm64":
   189  		arch = "aarch64"
   190  	default:
   191  		fail(fmt.Errorf("unknown/unsupported GOARCH: %q", goarch))
   192  	}
   193  	defer func() {
   194  		if err := os.Chdir(wd); err != nil {
   195  			fail(err)
   196  		}
   197  	}()
   198  
   199  	//TODO- run("mkdir", "-p", "obj/include/bits")
   200  	//TODO- run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   201  	//TODO- run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   202  	//TODO- run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   203  	if err := os.MkdirAll("obj\\include\\bits", 0770); err != nil {
   204  		fail(err)
   205  	}
   206  
   207  	run("cmd", "/c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   208  	run("cmd", "/c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   209  	run("cmd", "/c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   210  
   211  	if out, err := runcc(
   212  		"-D__environ=environ",
   213  		"-export-externs", "X",
   214  		"-export-fields", "F",
   215  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6",
   216  		"-nostdinc",
   217  		"-nostdlib",
   218  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   219  		"-pkgname", "libc",
   220  		"-static-locals-prefix", "_s",
   221  
   222  		// Keep the order below, don't sort!
   223  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   224  		fmt.Sprintf("-I%s", "arch/generic"),
   225  		fmt.Sprintf("-I%s", "obj/src/internal"),
   226  		fmt.Sprintf("-I%s", "src/include"),
   227  		fmt.Sprintf("-I%s", "src/internal"),
   228  		fmt.Sprintf("-I%s", "obj/include"),
   229  		fmt.Sprintf("-I%s", "include"),
   230  		// Keep the order above, don't sort!
   231  
   232  		"copyright.c", // Inject legalese first
   233  
   234  		// Keep the below lines sorted.
   235  		"src/ctype/isalnum.c",
   236  		"src/ctype/isalpha.c",
   237  		"src/ctype/isdigit.c",
   238  		"src/ctype/islower.c",
   239  		"src/ctype/isprint.c",
   240  		"src/ctype/isspace.c",
   241  		"src/ctype/isxdigit.c",
   242  		"src/env/putenv.c",
   243  		"src/env/setenv.c",
   244  		"src/env/unsetenv.c",
   245  		"src/multibyte/wcrtomb.c",
   246  		"src/multibyte/wcsrtombs.c",
   247  		"src/multibyte/wcstombs.c",
   248  		"src/stdlib/bsearch.c",
   249  		"src/string/strchrnul.c",
   250  		"src/string/strdup.c",
   251  	); err != nil {
   252  		fail(fmt.Errorf("%s\nFAIL: %v", out, err))
   253  	}
   254  }
   255  
   256  func makeMuslWin386(goos, goarch string) {
   257  	if runtime.GOOS != "linux" {
   258  		fail(fmt.Errorf("must be runned on Linux"))
   259  	}
   260  
   261  	wd, err := os.Getwd()
   262  	if err != nil {
   263  		fail(err)
   264  	}
   265  
   266  	if err := os.Chdir("musl"); err != nil {
   267  		fail(err)
   268  	}
   269  
   270  	arch := "i386"
   271  	defer func() {
   272  		if err := os.Chdir(wd); err != nil {
   273  			fail(err)
   274  		}
   275  	}()
   276  
   277  	run("mkdir", "-p", "obj/include/bits")
   278  	run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   279  	run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   280  	run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   281  
   282  	if _, err := runcc(
   283  		"-D__environ=environ",
   284  		"-export-externs", "X",
   285  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6",
   286  		"-nostdinc",
   287  		"-nostdlib",
   288  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   289  		"-pkgname", "libc",
   290  		"-static-locals-prefix", "_s",
   291  
   292  		// Keep the order below, don't sort!
   293  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   294  		fmt.Sprintf("-I%s", "arch/generic"),
   295  		fmt.Sprintf("-I%s", "obj/src/internal"),
   296  		fmt.Sprintf("-I%s", "src/include"),
   297  		fmt.Sprintf("-I%s", "src/internal"),
   298  		fmt.Sprintf("-I%s", "obj/include"),
   299  		fmt.Sprintf("-I%s", "include"),
   300  		// Keep the order above, don't sort!
   301  
   302  		"copyright.c", // Inject legalese first
   303  
   304  		// Keep the below lines sorted.
   305  		"src/ctype/isalnum.c",
   306  		"src/ctype/isalpha.c",
   307  		"src/ctype/isdigit.c",
   308  		"src/ctype/islower.c",
   309  		"src/ctype/isprint.c",
   310  		"src/ctype/isspace.c",
   311  		"src/ctype/isxdigit.c",
   312  		"src/env/putenv.c",
   313  		"src/env/setenv.c",
   314  		"src/env/unsetenv.c",
   315  		"src/multibyte/wcrtomb.c",
   316  		"src/multibyte/wcsrtombs.c",
   317  		"src/multibyte/wcstombs.c",
   318  		"src/string/strchrnul.c",
   319  		"src/string/strdup.c",
   320  	); err != nil {
   321  		fail(err)
   322  	}
   323  }
   324  
   325  func makeMuslDarwin(goos, goarch string) {
   326  	wd, err := os.Getwd()
   327  	if err != nil {
   328  		fail(err)
   329  	}
   330  
   331  	if err := os.Chdir("musl"); err != nil {
   332  		fail(err)
   333  	}
   334  
   335  	var arch string
   336  	switch goarch {
   337  	case "amd64":
   338  		arch = "x86_64"
   339  	case "arm64":
   340  		arch = "aarch64"
   341  	default:
   342  		fail(fmt.Errorf("unknown/unsupported GOARCH: %q", goarch))
   343  	}
   344  	defer func() {
   345  		if err := os.Chdir(wd); err != nil {
   346  			fail(err)
   347  		}
   348  	}()
   349  
   350  	run("mkdir", "-p", "obj/include/bits")
   351  	run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   352  	run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   353  	run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   354  	if _, err := runcc(
   355  		"-D__environ=environ",
   356  		"-export-externs", "X",
   357  		"-export-fields", "F",
   358  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6",
   359  		"-hide", "isascii,isspace,tolower,toupper",
   360  		"-nostdinc",
   361  		"-nostdlib",
   362  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   363  		"-pkgname", "libc",
   364  		"-static-locals-prefix", "_s",
   365  
   366  		// Keep the order below, don't sort!
   367  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   368  		fmt.Sprintf("-I%s", "arch/generic"),
   369  		fmt.Sprintf("-I%s", "obj/src/internal"),
   370  		fmt.Sprintf("-I%s", "src/include"),
   371  		fmt.Sprintf("-I%s", "src/internal"),
   372  		fmt.Sprintf("-I%s", "obj/include"),
   373  		fmt.Sprintf("-I%s", "include"),
   374  		// Keep the order above, don't sort!
   375  
   376  		"copyright.c", // Inject legalese first
   377  
   378  		"../darwin/table.c",
   379  
   380  		// Keep the below lines sorted.
   381  		"src/env/putenv.c",
   382  		"src/env/setenv.c",
   383  		"src/env/unsetenv.c",
   384  		"src/internal/floatscan.c",
   385  		"src/internal/intscan.c",
   386  		"src/internal/shgetc.c",
   387  		"src/locale/localeconv.c",
   388  		"src/math/__fpclassify.c",
   389  		"src/math/__fpclassifyf.c",
   390  		"src/math/__fpclassifyl.c",
   391  		"src/math/copysignl.c",
   392  		"src/math/fabsl.c",
   393  		"src/math/fmodl.c",
   394  		"src/math/nanf.c",
   395  		"src/math/rint.c",
   396  		"src/math/scalbn.c",
   397  		"src/math/scalbnl.c",
   398  		"src/network/freeaddrinfo.c",
   399  		"src/network/getaddrinfo.c",
   400  		"src/network/gethostbyaddr.c",
   401  		"src/network/gethostbyaddr_r.c",
   402  		"src/network/gethostbyname.c",
   403  		"src/network/gethostbyname2.c",
   404  		"src/network/gethostbyname2_r.c",
   405  		"src/network/getnameinfo.c",
   406  		"src/network/h_errno.c",
   407  		"src/network/inet_aton.c",
   408  		"src/network/inet_ntop.c",
   409  		"src/network/inet_pton.c",
   410  		"src/network/lookup_ipliteral.c",
   411  		"src/network/lookup_name.c",
   412  		"src/network/lookup_serv.c",
   413  		"src/prng/rand_r.c",
   414  		"src/stdio/__toread.c",
   415  		"src/stdio/__uflow.c",
   416  		"src/stdlib/bsearch.c",
   417  		"src/stdlib/strtod.c",
   418  		"src/stdlib/strtol.c",
   419  		"src/string/strchrnul.c",
   420  		"src/string/strdup.c",
   421  		"src/string/strlcat.c",
   422  		"src/string/strlcpy.c",
   423  		"src/string/strncasecmp.c",
   424  		"src/string/strncat.c",
   425  		"src/string/strnlen.c",
   426  		"src/string/strspn.c",
   427  		"src/string/strtok.c",
   428  	); err != nil {
   429  		fail(err)
   430  	}
   431  }
   432  
   433  func makeMuslLinux(goos, goarch string) {
   434  	wd, err := os.Getwd()
   435  	if err != nil {
   436  		fail(err)
   437  	}
   438  
   439  	if err := os.Chdir("musl"); err != nil {
   440  		fail(err)
   441  	}
   442  
   443  	var arch string
   444  	switch goarch {
   445  	case "amd64":
   446  		arch = "x86_64"
   447  	case "386":
   448  		arch = "i386"
   449  	case "arm":
   450  		arch = "arm"
   451  	case "arm64":
   452  		arch = "aarch64"
   453  	case "s390x":
   454  		arch = "s390x"
   455  	case "ppc64le":
   456  		arch = "powerpc64"
   457  	case "riscv64":
   458  		arch = "riscv64"
   459  	default:
   460  		fail(fmt.Errorf("unknown/unsupported GOARCH: %q", goarch))
   461  	}
   462  	defer func() {
   463  		if err := os.Chdir(wd); err != nil {
   464  			fail(err)
   465  		}
   466  	}()
   467  
   468  	run("mkdir", "-p", "obj/include/bits")
   469  	run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   470  	run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   471  	run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   472  	if _, err := runcc(
   473  		"-export-externs", "X",
   474  		"-export-fields", "F",
   475  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6",
   476  		"-nostdinc",
   477  		"-nostdlib",
   478  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   479  		"-pkgname", "libc",
   480  		"-static-locals-prefix", "_s",
   481  
   482  		// Keep the order below, don't sort!
   483  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   484  		fmt.Sprintf("-I%s", "arch/generic"),
   485  		fmt.Sprintf("-I%s", "obj/src/internal"),
   486  		fmt.Sprintf("-I%s", "src/include"),
   487  		fmt.Sprintf("-I%s", "src/internal"),
   488  		fmt.Sprintf("-I%s", "obj/include"),
   489  		fmt.Sprintf("-I%s", "include"),
   490  		// Keep the order above, don't sort!
   491  
   492  		"copyright.c", // Inject legalese first
   493  
   494  		// Keep the below lines sorted.
   495  		"src/ctype/__ctype_b_loc.c",
   496  		"src/ctype/isalnum.c",
   497  		"src/ctype/isalpha.c",
   498  		"src/ctype/isdigit.c",
   499  		"src/ctype/islower.c",
   500  		"src/ctype/isprint.c",
   501  		"src/ctype/isupper.c",
   502  		"src/ctype/isxdigit.c",
   503  		"src/dirent/closedir.c",
   504  		"src/dirent/opendir.c",
   505  		"src/dirent/readdir.c",
   506  		"src/internal/floatscan.c",
   507  		"src/internal/intscan.c",
   508  		"src/internal/shgetc.c",
   509  		"src/locale/localeconv.c",
   510  		"src/math/__fpclassify.c",
   511  		"src/math/__fpclassifyf.c",
   512  		"src/math/__fpclassifyl.c",
   513  		"src/math/copysignl.c",
   514  		"src/math/fabsl.c",
   515  		"src/math/fmodl.c",
   516  		"src/math/nanf.c",
   517  		"src/math/rint.c",
   518  		"src/math/scalbn.c",
   519  		"src/math/scalbnl.c",
   520  		"src/multibyte/internal.c",
   521  		"src/multibyte/mbrtowc.c",
   522  		"src/multibyte/mbsinit.c",
   523  		"src/network/freeaddrinfo.c",
   524  		"src/network/getaddrinfo.c",
   525  		"src/network/gethostbyaddr.c",
   526  		"src/network/gethostbyaddr_r.c",
   527  		"src/network/gethostbyname.c",
   528  		"src/network/gethostbyname2.c",
   529  		"src/network/gethostbyname2_r.c",
   530  		"src/network/gethostbyname_r.c",
   531  		"src/network/getnameinfo.c",
   532  		"src/network/h_errno.c",
   533  		"src/network/inet_aton.c",
   534  		"src/network/inet_ntop.c",
   535  		"src/network/inet_pton.c",
   536  		"src/network/lookup_ipliteral.c",
   537  		"src/network/lookup_name.c",
   538  		"src/network/lookup_serv.c",
   539  		"src/prng/rand_r.c",
   540  		"src/stdio/__lockfile.c",
   541  		"src/stdio/__toread.c",
   542  		"src/stdio/__uflow.c",
   543  		"src/stdio/sscanf.c",
   544  		"src/stdio/vfscanf.c",
   545  		"src/stdio/vsscanf.c",
   546  		"src/stdlib/bsearch.c",
   547  		"src/stdlib/strtod.c",
   548  		"src/stdlib/strtol.c",
   549  		"src/string/strdup.c",
   550  		"src/string/strlcat.c",
   551  		"src/string/strlcpy.c",
   552  		"src/string/strncasecmp.c",
   553  		"src/string/strncat.c",
   554  		"src/string/strnlen.c",
   555  		"src/string/strspn.c",
   556  		"src/string/strtok.c",
   557  		"src/thread/pthread_attr_get.c",
   558  		"src/thread/pthread_attr_setdetachstate.c",
   559  		"src/thread/pthread_mutex_lock.c",
   560  		"src/thread/pthread_mutexattr_destroy.c",
   561  		"src/thread/pthread_mutexattr_init.c",
   562  		"src/thread/pthread_mutexattr_settype.c",
   563  	); err != nil {
   564  		fail(err)
   565  	}
   566  }
   567  
   568  func makeMuslNetBSD(goos, goarch string) {
   569  	wd, err := os.Getwd()
   570  	if err != nil {
   571  		fail(err)
   572  	}
   573  
   574  	if err := os.Chdir("musl"); err != nil {
   575  		fail(err)
   576  	}
   577  
   578  	var arch string
   579  	switch goarch {
   580  	case "amd64":
   581  		arch = "x86_64"
   582  	case "arm":
   583  		arch = "arm"
   584  	default:
   585  		fail(fmt.Errorf("unknown/unsupported GOARCH: %q", goarch))
   586  	}
   587  	defer func() {
   588  		if err := os.Chdir(wd); err != nil {
   589  			fail(err)
   590  		}
   591  	}()
   592  
   593  	run("mkdir", "-p", "obj/include/bits")
   594  	run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   595  	run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   596  	run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   597  	if _, err := runcc(
   598  		"-export-externs", "X",
   599  		"-export-fields", "F",
   600  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6,getnameinfo,gethostbyaddr_r,",
   601  		"-nostdinc",
   602  		"-nostdlib",
   603  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   604  		"-pkgname", "libc",
   605  		"-static-locals-prefix", "_s",
   606  
   607  		// Keep the order below, don't sort!
   608  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   609  		fmt.Sprintf("-I%s", "arch/generic"),
   610  		fmt.Sprintf("-I%s", "obj/src/internal"),
   611  		fmt.Sprintf("-I%s", "src/include"),
   612  		fmt.Sprintf("-I%s", "src/internal"),
   613  		fmt.Sprintf("-I%s", "obj/include"),
   614  		fmt.Sprintf("-I%s", "include"),
   615  		// Keep the order above, don't sort!
   616  
   617  		"copyright.c", // Inject legalese first
   618  
   619  		"../netbsd/ctype_.cpp.c",
   620  
   621  		// Keep the below lines sorted.
   622  		"src/ctype/isalnum.c",
   623  		"src/ctype/isalpha.c",
   624  		"src/ctype/isdigit.c",
   625  		"src/ctype/isprint.c",
   626  		"src/internal/floatscan.c",
   627  		"src/internal/intscan.c",
   628  		"src/internal/shgetc.c",
   629  		"src/math/copysignl.c",
   630  		"src/math/fabsl.c",
   631  		"src/math/fmodl.c",
   632  		"src/math/rint.c",
   633  		"src/math/scalbn.c",
   634  		"src/math/scalbnl.c",
   635  		"src/network/freeaddrinfo.c",
   636  		"src/network/getaddrinfo.c",
   637  		"src/network/gethostbyaddr.c",
   638  		"src/network/gethostbyaddr_r.c",
   639  		"src/network/gethostbyname.c",
   640  		"src/network/gethostbyname2.c",
   641  		"src/network/gethostbyname2_r.c",
   642  		"src/network/getnameinfo.c",
   643  		"src/network/h_errno.c",
   644  		"src/network/inet_aton.c",
   645  		"src/network/inet_ntop.c",
   646  		"src/network/inet_pton.c",
   647  		"src/network/lookup_ipliteral.c",
   648  		"src/network/lookup_name.c",
   649  		"src/network/lookup_serv.c",
   650  		"src/stdio/__toread.c",
   651  		"src/stdio/__uflow.c",
   652  		"src/stdlib/bsearch.c",
   653  		"src/stdlib/strtod.c",
   654  		"src/stdlib/strtol.c",
   655  		"src/string/strdup.c",
   656  		"src/string/strnlen.c",
   657  		"src/string/strspn.c",
   658  	); err != nil {
   659  		fail(err)
   660  	}
   661  }
   662  
   663  func makeMuslOpenBSD(goos, goarch string) {
   664  	wd, err := os.Getwd()
   665  	if err != nil {
   666  		fail(err)
   667  	}
   668  
   669  	if err := os.Chdir("musl"); err != nil {
   670  		fail(err)
   671  	}
   672  
   673  	var arch string
   674  	switch goarch {
   675  	case "amd64":
   676  		arch = "x86_64"
   677  	case "386":
   678  		arch = "i386"
   679  	case "arm":
   680  		arch = "arm"
   681  	case "arm64":
   682  		arch = "aarch64"
   683  	default:
   684  		fail(fmt.Errorf("unknown/unsupported GOARCH: %q", goarch))
   685  	}
   686  	defer func() {
   687  		if err := os.Chdir(wd); err != nil {
   688  			fail(err)
   689  		}
   690  	}()
   691  
   692  	run("mkdir", "-p", "obj/include/bits")
   693  	run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   694  	run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   695  	run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   696  	if _, err := runcc(
   697  		"-export-externs", "X",
   698  		"-export-fields", "F",
   699  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6,getnameinfo,gethostbyaddr_r,",
   700  		"-nostdinc",
   701  		"-nostdlib",
   702  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   703  		"-pkgname", "libc",
   704  		"-static-locals-prefix", "_s",
   705  
   706  		// Keep the order below, don't sort!
   707  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   708  		fmt.Sprintf("-I%s", "arch/generic"),
   709  		fmt.Sprintf("-I%s", "obj/src/internal"),
   710  		fmt.Sprintf("-I%s", "src/include"),
   711  		fmt.Sprintf("-I%s", "src/internal"),
   712  		fmt.Sprintf("-I%s", "obj/include"),
   713  		fmt.Sprintf("-I%s", "include"),
   714  		// Keep the order above, don't sort!
   715  
   716  		"copyright.c", // Inject legalese first
   717  
   718  		"../openbsd/ctype_.c",
   719  
   720  		// Keep the below lines sorted.
   721  		"src/ctype/isalnum.c",
   722  		"src/ctype/isalpha.c",
   723  		"src/ctype/isdigit.c",
   724  		"src/ctype/islower.c",
   725  		"src/ctype/isprint.c",
   726  		"src/ctype/isspace.c",
   727  		"src/ctype/isupper.c",
   728  		"src/ctype/isxdigit.c",
   729  		"src/internal/floatscan.c",
   730  		"src/internal/intscan.c",
   731  		"src/internal/shgetc.c",
   732  		"src/math/copysignl.c",
   733  		"src/math/fabsl.c",
   734  		"src/math/fmodl.c",
   735  		"src/math/rint.c",
   736  		"src/math/scalbn.c",
   737  		"src/math/scalbnl.c",
   738  		"src/network/freeaddrinfo.c",
   739  		"src/network/getaddrinfo.c",
   740  		"src/network/gethostbyaddr.c",
   741  		"src/network/gethostbyaddr_r.c",
   742  		"src/network/gethostbyname.c",
   743  		"src/network/gethostbyname2.c",
   744  		"src/network/gethostbyname2_r.c",
   745  		"src/network/getnameinfo.c",
   746  		"src/network/h_errno.c",
   747  		"src/network/inet_aton.c",
   748  		"src/network/inet_ntop.c",
   749  		"src/network/inet_pton.c",
   750  		"src/network/lookup_ipliteral.c",
   751  		"src/network/lookup_name.c",
   752  		"src/network/lookup_serv.c",
   753  		"src/stdio/__toread.c",
   754  		"src/stdio/__uflow.c",
   755  		"src/stdlib/bsearch.c",
   756  		"src/stdlib/strtod.c",
   757  		"src/stdlib/strtol.c",
   758  		"src/string/strdup.c",
   759  		"src/string/strnlen.c",
   760  		"src/string/strspn.c",
   761  	); err != nil {
   762  		fail(err)
   763  	}
   764  }
   765  
   766  func makeMuslFreeBSD(goos, goarch string) {
   767  	wd, err := os.Getwd()
   768  	if err != nil {
   769  		fail(err)
   770  	}
   771  
   772  	if err := os.Chdir("musl"); err != nil {
   773  		fail(err)
   774  	}
   775  
   776  	var arch string
   777  	switch goarch {
   778  	case "amd64":
   779  		arch = "x86_64"
   780  	case "386":
   781  		arch = "i386"
   782  	case "arm":
   783  		arch = "arm"
   784  	default:
   785  		fail(fmt.Errorf("unknown/unsupported GOARCH: %q", goarch))
   786  	}
   787  	defer func() {
   788  		if err := os.Chdir(wd); err != nil {
   789  			fail(err)
   790  		}
   791  	}()
   792  
   793  	run("mkdir", "-p", "obj/include/bits")
   794  	run("sh", "-c", fmt.Sprintf("sed -f ./tools/mkalltypes.sed ./arch/%s/bits/alltypes.h.in ./include/alltypes.h.in > obj/include/bits/alltypes.h", arch))
   795  	run("sh", "-c", fmt.Sprintf("cp arch/%s/bits/syscall.h.in obj/include/bits/syscall.h", arch))
   796  	run("sh", "-c", fmt.Sprintf("sed -n -e s/__NR_/SYS_/p < arch/%s/bits/syscall.h.in >> obj/include/bits/syscall.h", arch))
   797  	if _, err := runcc(
   798  		"-export-externs", "X",
   799  		"-export-fields", "F",
   800  		"-hide", "__syscall0,__syscall1,__syscall2,__syscall3,__syscall4,__syscall5,__syscall6,getnameinfo,gethostbyaddr_r,",
   801  		"-nostdinc",
   802  		"-nostdlib",
   803  		"-o", fmt.Sprintf("../musl_%s_%s.go", goos, goarch),
   804  		"-pkgname", "libc",
   805  		"-static-locals-prefix", "_s",
   806  
   807  		// Keep the order below, don't sort!
   808  		fmt.Sprintf("-I%s", filepath.Join("arch", arch)),
   809  		fmt.Sprintf("-I%s", "arch/generic"),
   810  		fmt.Sprintf("-I%s", "obj/src/internal"),
   811  		fmt.Sprintf("-I%s", "src/include"),
   812  		fmt.Sprintf("-I%s", "src/internal"),
   813  		fmt.Sprintf("-I%s", "obj/include"),
   814  		fmt.Sprintf("-I%s", "include"),
   815  		// Keep the order above, don't sort!
   816  
   817  		"copyright.c", // Inject legalese first
   818  
   819  		"../freebsd/table.cpp.c",
   820  
   821  		// Keep the below lines sorted.
   822  		"src/ctype/isalnum.c",
   823  		"src/ctype/isalpha.c",
   824  		"src/ctype/isdigit.c",
   825  		"src/ctype/islower.c",
   826  		"src/ctype/isprint.c",
   827  		"src/ctype/isspace.c",
   828  		"src/ctype/isupper.c",
   829  		"src/ctype/isxdigit.c",
   830  		"src/internal/floatscan.c",
   831  		"src/internal/intscan.c",
   832  		"src/internal/shgetc.c",
   833  		"src/math/copysignl.c",
   834  		"src/math/fabsl.c",
   835  		"src/math/fmodl.c",
   836  		"src/math/rint.c",
   837  		"src/math/scalbn.c",
   838  		"src/math/scalbnl.c",
   839  		"src/network/freeaddrinfo.c",
   840  		"src/network/getaddrinfo.c",
   841  		"src/network/gethostbyaddr.c",
   842  		"src/network/gethostbyaddr_r.c",
   843  		"src/network/gethostbyname.c",
   844  		"src/network/gethostbyname2.c",
   845  		"src/network/gethostbyname2_r.c",
   846  		"src/network/getnameinfo.c",
   847  		"src/network/h_errno.c",
   848  		"src/network/inet_aton.c",
   849  		"src/network/inet_ntop.c",
   850  		"src/network/inet_pton.c",
   851  		"src/network/lookup_ipliteral.c",
   852  		"src/network/lookup_name.c",
   853  		"src/network/lookup_serv.c",
   854  		"src/stdio/__toread.c",
   855  		"src/stdio/__uflow.c",
   856  		"src/stdlib/bsearch.c",
   857  		"src/stdlib/strtod.c",
   858  		"src/stdlib/strtol.c",
   859  		"src/string/strdup.c",
   860  		"src/string/strnlen.c",
   861  		"src/string/strspn.c",
   862  	); err != nil {
   863  		fail(err)
   864  	}
   865  }
   866  
   867  func run(arg0 string, args ...string) []byte {
   868  	fmt.Printf("%s %q\n", arg0, args)
   869  	cmd := exec.Command(arg0, args...)
   870  	out, err := cmd.CombinedOutput()
   871  	if err != nil {
   872  		sout := strings.TrimSpace(string(out))
   873  		fmt.Fprintf(os.Stderr, "==== FAIL\n%s\n%s\n", sout, err)
   874  		fail(err)
   875  	}
   876  	return out
   877  }
   878  
   879  type echoWriter struct {
   880  	w bytes.Buffer
   881  }
   882  
   883  func (w *echoWriter) Write(b []byte) (int, error) {
   884  	os.Stdout.Write(b)
   885  	return w.w.Write(b)
   886  }
   887  
   888  func runcc(args ...string) ([]byte, error) {
   889  	args = append([]string{"ccgo"}, args...)
   890  	// fmt.Printf("%q\n", args)
   891  	var out echoWriter
   892  	err := ccgo.NewTask(args, &out, &out).Main()
   893  	return out.w.Bytes(), err
   894  }
   895  
   896  func libcHeaders(paths []string) error {
   897  	const cfile = "gen.c"
   898  	return filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
   899  		if err != nil {
   900  			return err
   901  		}
   902  
   903  		if !info.IsDir() {
   904  			return nil
   905  		}
   906  
   907  		path = filepath.Clean(path)
   908  		if strings.HasPrefix(path, ".") {
   909  			return nil
   910  		}
   911  
   912  		dir := path
   913  		ok := false
   914  		for _, v := range paths {
   915  			full := filepath.Join(v, dir+".h")
   916  			if fi, err := os.Stat(full); err == nil && !fi.IsDir() {
   917  				ok = true
   918  				break
   919  			}
   920  		}
   921  		if !ok {
   922  			return nil
   923  		}
   924  
   925  		var src string
   926  		switch filepath.ToSlash(path) {
   927  		case "fts":
   928  			src = `
   929  #include <sys/types.h>
   930  #include <sys/stat.h>
   931  #include <fts.h>
   932  `
   933  		default:
   934  			src = fmt.Sprintf("#include <%s.h>\n", dir)
   935  		}
   936  		src += "static char _;\n"
   937  		fn := filepath.Join(dir, cfile)
   938  		if err := ioutil.WriteFile(fn, []byte(src), 0660); err != nil {
   939  			return err
   940  		}
   941  
   942  		defer os.Remove(fn)
   943  
   944  		dest := filepath.Join(path, fmt.Sprintf("%s_%s_%s.go", filepath.Base(path), goos, goarch))
   945  		base := filepath.Base(dir)
   946  		argv := []string{
   947  			fn,
   948  
   949  			"-crt-import-path", "",
   950  			"-export-defines", "",
   951  			"-export-enums", "",
   952  			"-export-externs", "X",
   953  			"-export-fields", "F",
   954  			"-export-structs", "",
   955  			"-export-typedefs", "",
   956  			"-header",
   957  			"-hide", "_OSSwapInt16,_OSSwapInt32,_OSSwapInt64",
   958  			"-ignore-unsupported-alignment",
   959  			"-o", dest,
   960  			"-pkgname", base,
   961  		}
   962  		out, err := runcc(argv...)
   963  		if err != nil {
   964  			fmt.Fprintf(os.Stderr, "%s: %s%s\n", path, out, err)
   965  		} else {
   966  			fmt.Fprintf(os.Stdout, "%s\n%s", path, out)
   967  		}
   968  		return nil
   969  	})
   970  }
   971  
   972  func fail(err error) {
   973  	fmt.Fprintf(os.Stderr, "%v (%v: %v:)\n", err, origin(3), origin(2))
   974  	os.Exit(1)
   975  }
   976  
   977  func ccgoHelpers() {
   978  	var (
   979  		signed = []string{
   980  			"int8",
   981  			"int16",
   982  			"int32",
   983  			"int64",
   984  		}
   985  		unsigned = []string{
   986  			"uint8",
   987  			"uint16",
   988  			"uint32",
   989  			"uint64",
   990  		}
   991  		ints   = append(signed[:len(signed):len(signed)], unsigned...)
   992  		intptr = append(ints[:len(ints):len(ints)], "uintptr")
   993  		arith  = append(ints[:len(ints):len(ints)], "float32", "float64", "complex64", "complex128")
   994  		scalar = append(arith[:len(arith):len(arith)], []string{"uintptr"}...)
   995  		sizes  = []string{"8", "16", "32", "64"}
   996  		atomic = []string{
   997  			"int32",
   998  			"int64",
   999  			"uint32",
  1000  			"uint64",
  1001  			"uintptr",
  1002  		}
  1003  	)
  1004  
  1005  	b := bytes.NewBuffer(nil)
  1006  	b.WriteString(`// Code generated by 'go generate' - DO NOT EDIT.
  1007  
  1008  package libc // import "github.com/afumu/libc"
  1009  
  1010  import (
  1011  	"sync/atomic"
  1012  	"unsafe"
  1013  )
  1014  
  1015  `)
  1016  	for _, v := range atomic {
  1017  		fmt.Fprintln(b)
  1018  		fmt.Fprintf(b, "func AtomicStoreN%s(ptr uintptr, val %s, memorder int32) { atomic.Store%[1]s((*%[2]s)(unsafe.Pointer(ptr)), val) }\n", capitalize(v), v)
  1019  	}
  1020  
  1021  	fmt.Fprintln(b)
  1022  	for _, v := range atomic {
  1023  		fmt.Fprintln(b)
  1024  		fmt.Fprintf(b, "func AtomicLoadN%s(ptr uintptr, memorder int32) %s { return atomic.Load%[1]s((*%[2]s)(unsafe.Pointer(ptr))) }\n", capitalize(v), v)
  1025  	}
  1026  
  1027  	for _, v := range scalar {
  1028  		fmt.Fprintf(b, "func Assign%s(p *%s, v %[2]s) %[2]s { *p = v; return v }\n", capitalize(v), v)
  1029  	}
  1030  
  1031  	fmt.Fprintln(b)
  1032  	for _, v := range scalar {
  1033  		fmt.Fprintf(b, "func AssignPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) = v; return v }\n", capitalize(v), v)
  1034  	}
  1035  
  1036  	fmt.Fprintln(b)
  1037  	for _, v := range scalar {
  1038  		fmt.Fprintf(b, "func AssignMul%s(p *%s, v %[2]s) %[2]s { *p *= v; return *p }\n", capitalize(v), v)
  1039  	}
  1040  
  1041  	fmt.Fprintln(b)
  1042  	for _, v := range scalar {
  1043  		fmt.Fprintf(b, "func AssignDiv%s(p *%s, v %[2]s) %[2]s { *p /= v; return *p }\n", capitalize(v), v)
  1044  	}
  1045  
  1046  	fmt.Fprintln(b)
  1047  	for _, v := range intptr {
  1048  		fmt.Fprintf(b, "func AssignRem%s(p *%s, v %[2]s) %[2]s { *p %%= v; return *p }\n", capitalize(v), v)
  1049  	}
  1050  
  1051  	fmt.Fprintln(b)
  1052  	for _, v := range scalar {
  1053  		fmt.Fprintf(b, "func AssignAdd%s(p *%s, v %[2]s) %[2]s { *p += v; return *p }\n", capitalize(v), v)
  1054  	}
  1055  
  1056  	fmt.Fprintln(b)
  1057  	for _, v := range scalar {
  1058  		fmt.Fprintf(b, "func AssignSub%s(p *%s, v %[2]s) %[2]s { *p -= v; return *p }\n", capitalize(v), v)
  1059  	}
  1060  
  1061  	fmt.Fprintln(b)
  1062  	for _, v := range intptr {
  1063  		fmt.Fprintf(b, "func AssignAnd%s(p *%s, v %[2]s) %[2]s { *p &= v; return *p }\n", capitalize(v), v)
  1064  	}
  1065  
  1066  	fmt.Fprintln(b)
  1067  	for _, v := range intptr {
  1068  		fmt.Fprintf(b, "func AssignXor%s(p *%s, v %[2]s) %[2]s { *p ^= v; return *p }\n", capitalize(v), v)
  1069  	}
  1070  
  1071  	fmt.Fprintln(b)
  1072  	for _, v := range intptr {
  1073  		fmt.Fprintf(b, "func AssignOr%s(p *%s, v %[2]s) %[2]s { *p |= v; return *p }\n", capitalize(v), v)
  1074  	}
  1075  
  1076  	fmt.Fprintln(b)
  1077  	for _, v := range scalar {
  1078  		fmt.Fprintf(b, "func AssignMulPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) *= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1079  	}
  1080  
  1081  	fmt.Fprintln(b)
  1082  	for _, v := range scalar {
  1083  		fmt.Fprintf(b, "func AssignDivPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) /= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1084  	}
  1085  
  1086  	fmt.Fprintln(b)
  1087  	for _, v := range intptr {
  1088  		fmt.Fprintf(b, "func AssignRemPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) %%= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1089  	}
  1090  
  1091  	fmt.Fprintln(b)
  1092  	for _, v := range scalar {
  1093  		fmt.Fprintf(b, "func AssignAddPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) += v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1094  	}
  1095  
  1096  	fmt.Fprintln(b)
  1097  	for _, v := range scalar {
  1098  		fmt.Fprintf(b, "func AssignSubPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) -= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1099  	}
  1100  
  1101  	fmt.Fprintln(b)
  1102  	for _, v := range intptr {
  1103  		fmt.Fprintf(b, "func AssignAndPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) &= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1104  	}
  1105  
  1106  	fmt.Fprintln(b)
  1107  	for _, v := range intptr {
  1108  		fmt.Fprintf(b, "func AssignXorPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) ^= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1109  	}
  1110  
  1111  	fmt.Fprintln(b)
  1112  	for _, v := range intptr {
  1113  		fmt.Fprintf(b, "func AssignOrPtr%s(p uintptr, v %s) %[2]s { *(*%[2]s)(unsafe.Pointer(p)) |= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1114  	}
  1115  
  1116  	fmt.Fprintln(b)
  1117  	for _, v := range intptr {
  1118  		fmt.Fprintf(b, "func AssignShlPtr%s(p uintptr, v int) %s { *(*%[2]s)(unsafe.Pointer(p)) <<= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1119  	}
  1120  
  1121  	fmt.Fprintln(b)
  1122  	for _, v := range intptr {
  1123  		fmt.Fprintf(b, "func AssignShrPtr%s(p uintptr, v int) %s { *(*%[2]s)(unsafe.Pointer(p)) >>= v; return *(*%[2]s)(unsafe.Pointer(p)) }\n\n", capitalize(v), v)
  1124  	}
  1125  
  1126  	fmt.Fprintln(b)
  1127  	for _, v := range intptr {
  1128  		fmt.Fprintf(b, "func AssignShl%s(p *%s, v int) %[2]s { *p <<= v; return *p }\n\n", capitalize(v), v)
  1129  	}
  1130  
  1131  	fmt.Fprintln(b)
  1132  	for _, v := range intptr {
  1133  		fmt.Fprintf(b, "func AssignShr%s(p *%s, v int) %[2]s { *p >>= v; return *p }\n\n", capitalize(v), v)
  1134  	}
  1135  
  1136  	fmt.Fprintln(b)
  1137  	for _, v := range scalar {
  1138  		fmt.Fprintf(b, "func PreInc%s(p *%s, d %[2]s) %[2]s { *p += d; return *p }\n", capitalize(v), v)
  1139  	}
  1140  
  1141  	fmt.Fprintln(b)
  1142  	for _, v := range atomic {
  1143  		fmt.Fprintf(b, "func PreIncAtomic%s(p *%s, d %[2]s) %[2]s { return atomic.Add%[1]s(p, d) }\n", capitalize(v), v)
  1144  	}
  1145  
  1146  	fmt.Fprintln(b)
  1147  	for _, v := range scalar {
  1148  		fmt.Fprintf(b, "func PreDec%s(p *%s, d %[2]s) %[2]s { *p -= d; return *p }\n", capitalize(v), v)
  1149  	}
  1150  
  1151  	fmt.Fprintln(b)
  1152  	for _, v := range atomic {
  1153  		fmt.Fprintf(b, "func PreDecAtomic%s(p *%s, d %[2]s) %[2]s { return atomic.Add%[1]s(p, -d) }\n", capitalize(v), v)
  1154  	}
  1155  
  1156  	fmt.Fprintln(b)
  1157  	for _, v := range scalar {
  1158  		fmt.Fprintf(b, "func PostInc%s(p *%s, d %[2]s) %[2]s { r := *p; *p += d; return r }\n", capitalize(v), v)
  1159  	}
  1160  
  1161  	fmt.Fprintln(b)
  1162  	for _, v := range atomic {
  1163  		fmt.Fprintf(b, "func PostIncAtomic%s(p *%s, d %[2]s) %[2]s { return atomic.Add%[1]s(p, d) - d }\n", capitalize(v), v)
  1164  	}
  1165  
  1166  	fmt.Fprintln(b)
  1167  	for _, v := range scalar {
  1168  		fmt.Fprintf(b, "func PostDec%s(p *%s, d %[2]s) %[2]s { r := *p; *p -= d; return r }\n", capitalize(v), v)
  1169  	}
  1170  
  1171  	fmt.Fprintln(b)
  1172  	for _, v := range atomic {
  1173  		fmt.Fprintf(b, "func PostDecAtomic%s(p *%s, d %[2]s) %[2]s { return atomic.Add%[1]s(p, -d) + d }\n", capitalize(v), v)
  1174  	}
  1175  
  1176  	fmt.Fprintln(b)
  1177  	for _, v := range scalar {
  1178  		for _, w := range scalar {
  1179  			switch {
  1180  			case strings.HasPrefix(v, "complex64"):
  1181  				switch {
  1182  				case strings.HasPrefix(w, "complex"):
  1183  					fmt.Fprintf(b, "func %sFrom%s(n %s) %s { return %[4]s(n) }\n", capitalize(v), capitalize(w), w, v)
  1184  				default:
  1185  					fmt.Fprintf(b, "func %sFrom%s(n %s) %s { return %[4]s(complex(float32(n), 0)) }\n", capitalize(v), capitalize(w), w, v)
  1186  				}
  1187  			case strings.HasPrefix(v, "complex128"):
  1188  				switch {
  1189  				case strings.HasPrefix(w, "complex"):
  1190  					fmt.Fprintf(b, "func %sFrom%s(n %s) %s { return %[4]s(n) }\n", capitalize(v), capitalize(w), w, v)
  1191  				default:
  1192  					fmt.Fprintf(b, "func %sFrom%s(n %s) %s { return %[4]s(complex(float64(n), 0)) }\n", capitalize(v), capitalize(w), w, v)
  1193  				}
  1194  			default:
  1195  				switch {
  1196  				case strings.HasPrefix(w, "complex"):
  1197  					fmt.Fprintf(b, "func %sFrom%s(n %s) %s { return %[4]s(real(n)) }\n", capitalize(v), capitalize(w), w, v)
  1198  				default:
  1199  					fmt.Fprintf(b, "func %sFrom%s(n %s) %s { return %[4]s(n) }\n", capitalize(v), capitalize(w), w, v)
  1200  				}
  1201  			}
  1202  		}
  1203  	}
  1204  
  1205  	fmt.Fprintln(b)
  1206  	for _, v := range scalar {
  1207  		fmt.Fprintf(b, "func %s(n %s) %[2]s { return n }\n", capitalize(v), v)
  1208  	}
  1209  
  1210  	fmt.Fprintln(b)
  1211  	for _, v := range intptr {
  1212  		fmt.Fprintf(b, "func Neg%s(n %s) %[2]s { return -n }\n", capitalize(v), v)
  1213  	}
  1214  
  1215  	fmt.Fprintln(b)
  1216  	for _, v := range intptr {
  1217  		fmt.Fprintf(b, "func Cpl%s(n %s) %[2]s { return ^n }\n", capitalize(v), v)
  1218  	}
  1219  
  1220  	fmt.Fprintln(b)
  1221  	for _, v := range intptr {
  1222  		fmt.Fprintf(b, `
  1223  func Bool%s(b bool) %s {
  1224  	if b {
  1225  		return 1
  1226  	}
  1227  	return 0
  1228  }
  1229  `, capitalize(v), v)
  1230  	}
  1231  
  1232  	fmt.Fprintln(b)
  1233  	for _, sz := range sizes {
  1234  		for _, v := range ints {
  1235  			fmt.Fprintf(b, `
  1236  func SetBitFieldPtr%s%s(p uintptr, v %s, off int, mask uint%[1]s) {
  1237  	*(*uint%[1]s)(unsafe.Pointer(p)) = *(*uint%[1]s)(unsafe.Pointer(p))&^uint%[1]s(mask) | uint%[1]s(v)<<off&mask
  1238  }
  1239  
  1240  `, sz, capitalize(v), v)
  1241  		}
  1242  	}
  1243  
  1244  	fmt.Fprintln(b)
  1245  	for _, sz := range []int{8, 16, 32, 64} {
  1246  		for _, v := range []int{8, 16, 32, 64} {
  1247  			fmt.Fprintf(b, `
  1248  func AssignBitFieldPtr%dInt%d(p uintptr, v int%[2]d, w, off int, mask uint%[1]d) int%[2]d {
  1249  	*(*uint%[1]d)(unsafe.Pointer(p)) = *(*uint%[1]d)(unsafe.Pointer(p))&^uint%[1]d(mask) | uint%[1]d(v)<<off&mask
  1250  	s := %[2]d - w
  1251  	return v << s >> s
  1252  }
  1253  
  1254  `, sz, v)
  1255  		}
  1256  	}
  1257  
  1258  	fmt.Fprintln(b)
  1259  	for _, sz := range []int{8, 16, 32, 64} {
  1260  		for _, v := range []int{8, 16, 32, 64} {
  1261  			fmt.Fprintf(b, `
  1262  func AssignBitFieldPtr%dUint%d(p uintptr, v uint%[2]d, w, off int, mask uint%[1]d) uint%[2]d {
  1263  	*(*uint%[1]d)(unsafe.Pointer(p)) = *(*uint%[1]d)(unsafe.Pointer(p))&^uint%[1]d(mask) | uint%[1]d(v)<<off&mask
  1264  	return v & uint%[2]d(mask >> off)
  1265  }
  1266  
  1267  `, sz, v)
  1268  		}
  1269  	}
  1270  
  1271  	fmt.Fprintln(b)
  1272  	for _, sz := range []int{8, 16, 32, 64} {
  1273  		for _, v := range []int{8, 16, 32, 64} {
  1274  			fmt.Fprintf(b, `
  1275  func PostDecBitFieldPtr%dInt%d(p uintptr, d int%[2]d, w, off int, mask uint%[1]d) (r int%[2]d) {
  1276  	x0 := *(*uint%[1]d)(unsafe.Pointer(p))
  1277  	s := %[2]d - w - off
  1278  	r = int%[2]d(x0) & int%[2]d(mask) << s >> (s+off)
  1279  	*(*uint%[1]d)(unsafe.Pointer(p)) = x0&^uint%[1]d(mask) | uint%[1]d(r-d)<<off&mask
  1280  	return r
  1281  }
  1282  
  1283  `, sz, v)
  1284  		}
  1285  	}
  1286  
  1287  	fmt.Fprintln(b)
  1288  	for _, sz := range []int{8, 16, 32, 64} {
  1289  		for _, v := range []int{8, 16, 32, 64} {
  1290  			fmt.Fprintf(b, `
  1291  func PostDecBitFieldPtr%dUint%d(p uintptr, d uint%[2]d, w, off int, mask uint%[1]d) (r uint%[2]d) {
  1292  	x0 := *(*uint%[1]d)(unsafe.Pointer(p))
  1293  	r = uint%[2]d(x0) & uint%[2]d(mask) >> off
  1294  	*(*uint%[1]d)(unsafe.Pointer(p)) = x0&^uint%[1]d(mask) | uint%[1]d(r-d)<<off&mask
  1295  	return r
  1296  }
  1297  
  1298  `, sz, v)
  1299  		}
  1300  	}
  1301  
  1302  	fmt.Fprintln(b)
  1303  	for _, sz := range []int{8, 16, 32, 64} {
  1304  		for _, v := range []int{8, 16, 32, 64} {
  1305  			fmt.Fprintf(b, `
  1306  func PostIncBitFieldPtr%dInt%d(p uintptr, d int%[2]d, w, off int, mask uint%[1]d) (r int%[2]d) {
  1307  	x0 := *(*uint%[1]d)(unsafe.Pointer(p))
  1308  	s := %[2]d - w - off
  1309  	r = int%[2]d(x0) & int%[2]d(mask) << s >> (s+off)
  1310  	*(*uint%[1]d)(unsafe.Pointer(p)) = x0&^uint%[1]d(mask) | uint%[1]d(r+d)<<off&mask
  1311  	return r
  1312  }
  1313  
  1314  `, sz, v)
  1315  		}
  1316  	}
  1317  
  1318  	fmt.Fprintln(b)
  1319  	for _, sz := range []int{8, 16, 32, 64} {
  1320  		for _, v := range []int{8, 16, 32, 64} {
  1321  			fmt.Fprintf(b, `
  1322  func PostIncBitFieldPtr%dUint%d(p uintptr, d uint%[2]d, w, off int, mask uint%[1]d) (r uint%[2]d) {
  1323  	x0 := *(*uint%[1]d)(unsafe.Pointer(p))
  1324  	r = uint%[2]d(x0) & uint%[2]d(mask) >> off
  1325  	*(*uint%[1]d)(unsafe.Pointer(p)) = x0&^uint%[1]d(mask) | uint%[1]d(r+d)<<off&mask
  1326  	return r
  1327  }
  1328  
  1329  `, sz, v)
  1330  		}
  1331  	}
  1332  
  1333  	b.WriteString("\n")
  1334  	if err := ioutil.WriteFile(fmt.Sprintf("ccgo.go"), b.Bytes(), 0660); err != nil {
  1335  		fail(err)
  1336  	}
  1337  }
  1338  
  1339  func capitalize(s string) string { return strings.ToUpper(s[:1]) + s[1:] }