github.com/kortschak/ccgo@v0.0.0-20180729174341-14b549ba2a43/v2/all_test.go (about)

     1  // Copyright 2017 The CCGO 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  // linux_386
     6  //
     7  //	TCC0	cc 51 ccgo 51 build 51 run 51 ok 51
     8  //	Other0	cc 18 ccgo 18 build 18 run 18 ok 18
     9  //	GCC0	cc 1112 ccgo 1093 build 1089 run 1089 ok 1089
    10  //	Shell0	cc 1 ccgo 1 build 1 run 1 ok 1
    11  //	TCL0	tclsqlite build ok
    12  //	--- FAIL: TestTCL0 (36.48s)
    13  //		all_test.go:1586:
    14  //			Test cases:        0
    15  //			Pass:              0 (NaN%)
    16  //			Fail:              0 (NaN%)
    17  //		all_test.go:1594:
    18  //			Test binary exit error: exit status 2
    19  //			Last completed test file: ""
    20  //			Last passed test: ""
    21  //			Last line written to stdout: ""
    22  //			Blacklisted test files: 107
    23  //			btreefault.test
    24  //			cffault.test
    25  //			collate1.test
    26  //			collate2.test
    27  //			collate3.test
    28  //			collate4.test
    29  //			collate5.test
    30  //			collate6.test
    31  //			collate9.test
    32  //			corruptC.test
    33  //			crash.test
    34  //			crash2.test
    35  //			crash3.test
    36  //			crash4.test
    37  //			crash6.test
    38  //			crash7.test
    39  //			date.test
    40  //			e_createtable.test
    41  //			e_delete.test
    42  //			e_insert.test
    43  //			e_reindex.test
    44  //			e_select.test
    45  //			e_update.test
    46  //			e_walauto.test
    47  //			exists.test
    48  //			func4.test
    49  //			fuzz.test
    50  //			fuzzerfault.test
    51  //			ieee754.test
    52  //			incrcorrupt.test
    53  //			incrvacuum_ioerr.test
    54  //			ioerr3.test
    55  //			journal3.test
    56  //			lock.test
    57  //			lock4.test
    58  //			lock5.test
    59  //			malloc.test
    60  //			minmax.test
    61  //			misc1.test
    62  //			misc3.test
    63  //			misc7.test
    64  //			mjournal.test
    65  //			mmap1.test
    66  //			mmap4.test
    67  //			multiplex2.test
    68  //			nan.test
    69  //			pager1.test
    70  //			pager4.test
    71  //			pagerfault.test
    72  //			pagerfault2.test
    73  //			pagerfault3.test
    74  //			pragma.test
    75  //			printf.test
    76  //			quota2.test
    77  //			rbu.test
    78  //			reindex.test
    79  //			rollbackfault.test
    80  //			rowallock.test
    81  //			savepoint.test
    82  //			savepoint4.test
    83  //			savepointfault.test
    84  //			schema3.test
    85  //			select9.test
    86  //			shared2.test
    87  //			shared9.test
    88  //			sharedA.test
    89  //			sort2.test
    90  //			sort3.test
    91  //			sort4.test
    92  //			sortfault.test
    93  //			speed4.test
    94  //			speed4p.test
    95  //			statfault.test
    96  //			superlock.test
    97  //			symlink.test
    98  //			syscall.test
    99  //			tempfault.test
   100  //			thread001.test
   101  //			thread002.test
   102  //			thread003.test
   103  //			thread004.test
   104  //			thread005.test
   105  //			thread1.test
   106  //			thread2.test
   107  //			tkt-5d863f876e.test
   108  //			tkt-fc62af4523.test
   109  //			tkt3838.test
   110  //			tkt3997.test
   111  //			trans.test
   112  //			unionvtabfault.test
   113  //			unixexcl.test
   114  //			vacuum2.test
   115  //			vtabH.test
   116  //			wal.test
   117  //			wal2.test
   118  //			wal3.test
   119  //			wal4.test
   120  //			wal5.test
   121  //			walcrash.test
   122  //			walcrash2.test
   123  //			walcrash4.test
   124  //			walro.test
   125  //			walslow.test
   126  //			walthread.test
   127  //			where.test
   128  //			whereD.test
   129  //			writecrash.test
   130  //	FAIL
   131  //	exit status 1
   132  //	FAIL	github.com/cznic/ccgo/v2	481.539s
   133  
   134  //	go version go1.10.3 linux/amd64
   135  //	crt @6292872c0c06693d8be8aacf703ce3171550c0df
   136  //	cc  @b5e2186b9dda8102bd3a831a89d4550de37fa079
   137  //
   138  //	TCC0	cc 51 ccgo 51 build 51 run 51 ok 51
   139  //	TCC	cc 51 ccgo 51 build 51 run 51 ok 51 n 51
   140  //	Other0	cc 20 ccgo 20 build 20 run 20 ok 20
   141  //	Other	cc 20 ccgo 20 build 20 run 20 ok 20 n 20
   142  //	GCC0	cc 1121 ccgo 1099 build 1095 run 1095 ok 1095
   143  //	GCC	cc 1077 ccgo 1077 build 1074 run 1074 ok 1074 n 1408
   144  //	--- FAIL: TestGCC (251.54s)
   145  //			...
   146  //			exit status 1
   147  //	Shell0	cc 1 ccgo 1 build 1 run 1 ok 1
   148  //	Shell	cc 1 ccgo 1 build 1 run 1 ok 1 n 1
   149  //	TCL0	tclsqlite build ok
   150  //	--- FAIL: TestTCL0 (2257.86s)
   151  //		all_test.go:2037:
   152  //			Test cases:   261840
   153  //			Pass:         261067 (99.70%)
   154  //			Fail:            773 (0.30%)
   155  //			! alter-7.1 expected: [text 1 integer -2 text 5.4e-8 real 5.4e-8]
   156  //			! alter-7.1 got:      [text 1 integer -2 text 5.4e-8 real {}]
   157  //			! auth3-2.2 expected: [1]
   158  //			! auth3-2.2 got:      [0]
   159  //			! autovacuum-1.1.3 expected: [4]
   160  //			! autovacuum-1.1.3 got:      [16]
   161  //			! autovacuum-1.2.3 expected: [4]
   162  //			! autovacuum-1.2.3 got:      [16]
   163  //			! autovacuum-1.3.3 expected: [4]
   164  //			! autovacuum-1.3.3 got:      [16]
   165  //			... too many fails
   166  //		all_test.go:2045:
   167  //			Test binary exit error: exit status 1
   168  //			Last completed test file: "Time: selectC.test 282 ms"
   169  //			Last passed test: "no_optimization.selectC-5.3... Ok"
   170  //			Last line written to stdout: "Page-cache overflow:  now 0  max 21057216"
   171  //			Blacklisted test files: 107
   172  //			btreefault.test
   173  //			cffault.test
   174  //			collate1.test
   175  //			collate2.test
   176  //			collate3.test
   177  //			collate4.test
   178  //			collate5.test
   179  //			collate6.test
   180  //			collate9.test
   181  //			corruptC.test
   182  //			crash.test
   183  //			crash2.test
   184  //			crash3.test
   185  //			crash4.test
   186  //			crash6.test
   187  //			crash7.test
   188  //			date.test
   189  //			e_createtable.test
   190  //			e_delete.test
   191  //			e_insert.test
   192  //			e_reindex.test
   193  //			e_select.test
   194  //			e_update.test
   195  //			e_walauto.test
   196  //			exists.test
   197  //			func4.test
   198  //			fuzz.test
   199  //			fuzzerfault.test
   200  //			ieee754.test
   201  //			incrcorrupt.test
   202  //			incrvacuum_ioerr.test
   203  //			ioerr3.test
   204  //			journal3.test
   205  //			lock.test
   206  //			lock4.test
   207  //			lock5.test
   208  //			malloc.test
   209  //			minmax.test
   210  //			misc1.test
   211  //			misc3.test
   212  //			misc7.test
   213  //			mjournal.test
   214  //			mmap1.test
   215  //			mmap4.test
   216  //			multiplex2.test
   217  //			nan.test
   218  //			pager1.test
   219  //			pager4.test
   220  //			pagerfault.test
   221  //			pagerfault2.test
   222  //			pagerfault3.test
   223  //			pragma.test
   224  //			printf.test
   225  //			quota2.test
   226  //			rbu.test
   227  //			reindex.test
   228  //			rollbackfault.test
   229  //			rowallock.test
   230  //			savepoint.test
   231  //			savepoint4.test
   232  //			savepointfault.test
   233  //			schema3.test
   234  //			select9.test
   235  //			shared2.test
   236  //			shared9.test
   237  //			sharedA.test
   238  //			sort2.test
   239  //			sort3.test
   240  //			sort4.test
   241  //			sortfault.test
   242  //			speed4.test
   243  //			speed4p.test
   244  //			statfault.test
   245  //			superlock.test
   246  //			symlink.test
   247  //			syscall.test
   248  //			tempfault.test
   249  //			thread001.test
   250  //			thread002.test
   251  //			thread003.test
   252  //			thread004.test
   253  //			thread005.test
   254  //			thread1.test
   255  //			thread2.test
   256  //			tkt-5d863f876e.test
   257  //			tkt-fc62af4523.test
   258  //			tkt3838.test
   259  //			tkt3997.test
   260  //			trans.test
   261  //			unionvtabfault.test
   262  //			unixexcl.test
   263  //			vacuum2.test
   264  //			vtabH.test
   265  //			wal.test
   266  //			wal2.test
   267  //			wal3.test
   268  //			wal4.test
   269  //			wal5.test
   270  //			walcrash.test
   271  //			walcrash2.test
   272  //			walcrash4.test
   273  //			walro.test
   274  //			walslow.test
   275  //			walthread.test
   276  //			where.test
   277  //			whereD.test
   278  //			writecrash.test
   279  //	cc 1 ccgo 1 build 1 run 1 ok 1 (100.00%) csmith 1 (878.918489ms)
   280  //	cc 2 ccgo 2 build 2 run 2 ok 2 (100.00%) csmith 2 (1.860282035s)
   281  //	cc 3 ccgo 3 build 3 run 3 ok 3 (100.00%) csmith 3 (2.934628356s)
   282  //	cc 4 ccgo 4 build 4 run 4 ok 4 (100.00%) csmith 4 (3.703504113s)
   283  //	cc 5 ccgo 5 build 5 run 5 ok 5 (100.00%) csmith 5 (4.018860365s)
   284  //	cc 6 ccgo 6 build 6 run 6 ok 6 (100.00%) csmith 6 (4.33961958s)
   285  //	cc 7 ccgo 7 build 7 run 7 ok 7 (100.00%) csmith 7 (5.124800795s)
   286  //	cc 8 ccgo 8 build 8 run 8 ok 8 (100.00%) csmith 8 (5.432854884s)
   287  //	cc 9 ccgo 9 build 9 run 9 ok 9 (100.00%) csmith 9 (6.104557806s)
   288  //	cc 10 ccgo 10 build 10 run 10 ok 10 (100.00%) csmith 10 (6.822640488s)
   289  //	cc 11 ccgo 11 build 11 run 11 ok 11 (100.00%) csmith 11 (7.901912577s)
   290  //	cc 12 ccgo 12 build 12 run 12 ok 12 (100.00%) csmith 12 (8.896937935s)
   291  //	cc 13 ccgo 13 build 13 run 13 ok 13 (100.00%) csmith 13 (9.802575728s)
   292  //	cc 14 ccgo 14 build 14 run 14 ok 14 (100.00%) csmith 14 (23.153177457s)
   293  //	cc 15 ccgo 15 build 15 run 15 ok 15 (100.00%) csmith 15 (23.472549767s)
   294  //	cc 16 ccgo 16 build 16 run 16 ok 16 (100.00%) csmith 16 (36.879479487s)
   295  //	cc 17 ccgo 17 build 17 run 17 ok 17 (100.00%) csmith 17 (38.218026037s)
   296  //	cc 18 ccgo 18 build 18 run 18 ok 18 (100.00%) csmith 18 (38.528793375s)
   297  //	cc 19 ccgo 19 build 19 run 19 ok 19 (100.00%) csmith 19 (38.845052669s)
   298  //	cc 20 ccgo 20 build 20 run 20 ok 20 (100.00%) csmith 20 (39.590318453s)
   299  //	cc 21 ccgo 21 build 21 run 21 ok 21 (100.00%) csmith 21 (40.321804628s)
   300  //	cc 22 ccgo 22 build 22 run 22 ok 22 (100.00%) csmith 22 (48.256544591s)
   301  //	cc 23 ccgo 23 build 23 run 23 ok 23 (100.00%) csmith 23 (49.55323892s)
   302  //	cc 24 ccgo 24 build 24 run 24 ok 24 (100.00%) csmith 24 (50.710280104s)
   303  //	cc 25 ccgo 25 build 25 run 25 ok 25 (100.00%) csmith 25 (51.318273446s)
   304  //	cc 26 ccgo 26 build 26 run 26 ok 26 (100.00%) csmith 26 (58.73633808s)
   305  //	cc 27 ccgo 27 build 27 run 27 ok 27 (100.00%) csmith 27 (59.301626111s)
   306  //	cc 28 ccgo 28 build 28 run 28 ok 28 (100.00%) csmith 28 (1m0.48276345s)
   307  //	CSmith0	cc 28 ccgo 28 build 28 run 28 ok 28 (100.00%) csmith 28 (1m0.482786141s)
   308  //	FAIL
   309  //	exit status 1
   310  //	FAIL	github.com/cznic/ccgo/v2	2860.443s
   311  
   312  package ccgo
   313  
   314  import (
   315  	"bufio"
   316  	"bytes"
   317  	"context"
   318  	"encoding/hex"
   319  	"flag"
   320  	"fmt"
   321  	"io"
   322  	"io/ioutil"
   323  	"os"
   324  	"os/exec"
   325  	"path"
   326  	"path/filepath"
   327  	"regexp"
   328  	"runtime"
   329  	"sort"
   330  	"strings"
   331  	"testing"
   332  	"time"
   333  
   334  	"github.com/cznic/cc/v2"
   335  	"github.com/cznic/strutil"
   336  )
   337  
   338  func caller(s string, va ...interface{}) {
   339  	if s == "" {
   340  		s = strings.Repeat("%v ", len(va))
   341  	}
   342  	_, fn, fl, _ := runtime.Caller(2)
   343  	fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl)
   344  	fmt.Fprintf(os.Stderr, s, va...)
   345  	fmt.Fprintln(os.Stderr)
   346  	_, fn, fl, _ = runtime.Caller(1)
   347  	fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl)
   348  	fmt.Fprintln(os.Stderr)
   349  	os.Stderr.Sync()
   350  }
   351  
   352  func dbg(s string, va ...interface{}) {
   353  	if s == "" {
   354  		s = strings.Repeat("%v ", len(va))
   355  	}
   356  	_, fn, fl, _ := runtime.Caller(1)
   357  	fmt.Fprintf(os.Stderr, "# dbg %s:%d: ", path.Base(fn), fl)
   358  	fmt.Fprintf(os.Stderr, s, va...)
   359  	fmt.Fprintln(os.Stderr)
   360  	os.Stderr.Sync()
   361  }
   362  
   363  func TODO(...interface{}) string { //TODOOK
   364  	_, fn, fl, _ := runtime.Caller(1)
   365  	return fmt.Sprintf("# TODO: %s:%d:\n", path.Base(fn), fl) //TODOOK
   366  }
   367  
   368  func use(...interface{}) {}
   369  
   370  func init() {
   371  	use(caller, dbg, TODO) //TODOOK
   372  	flag.BoolVar(&traceLConsts, "lconst", false, "")
   373  	flag.BoolVar(&traceOpt, "to", false, "")
   374  	flag.BoolVar(&traceTODO, "todo", false, "")
   375  	flag.BoolVar(&traceWrites, "tw", false, "")
   376  	isTesting = true
   377  }
   378  
   379  // ============================================================================
   380  
   381  const (
   382  	testTimeout = 60 * time.Second
   383  )
   384  
   385  var (
   386  	oBuild   = flag.Bool("build", false, "full build errors")
   387  	oCC      = flag.Bool("cc", false, "full cc errors")
   388  	oCCGO    = flag.Bool("ccgo", false, "full ccgo errors")
   389  	oCSmith  = flag.Duration("csmith", time.Minute, "") // Use something like -timeout 25h -csmith 24h for real testing.
   390  	oEdit    = flag.Bool("edit", false, "")
   391  	oI       = flag.String("I", "", "")
   392  	oNoCmp   = flag.Bool("nocmp", false, "")
   393  	oRE      = flag.String("re", "", "")
   394  	oTCLRace = flag.Bool("tclrace", false, "")
   395  	oTmp     = flag.String("tmp", "", "")
   396  	oTrace   = flag.Bool("trc", false, "")
   397  
   398  	re          *regexp.Regexp
   399  	searchPaths []string
   400  	crt0o       []byte
   401  	defCCGO     = cc.NewStringSource("<defines>", "#define __ccgo__ 1\n#define __FUNCTION__ __func__\n")
   402  )
   403  
   404  func init() {
   405  	var err error
   406  	if searchPaths, err = cc.Paths(true); err != nil {
   407  		panic(err)
   408  	}
   409  
   410  	crt := cc.MustCrt0()
   411  	crt0, err := cc.Translate(&cc.Tweaks{}, []string{"@"}, searchPaths, defCCGO, cc.MustBuiltin(), crt)
   412  	if err != nil {
   413  		panic(err)
   414  	}
   415  
   416  	// o := traceOpt
   417  	// defer func() { traceOpt = o }()
   418  	// w := traceWrites
   419  	// defer func() { traceWrites = w }()
   420  	// traceWrites = true //TODO-
   421  	// traceOpt = true //TODO-
   422  
   423  	var b bytes.Buffer
   424  	if err = NewObject(&b, runtime.GOOS, runtime.GOARCH, crt.Name(), crt0, &NewObjectTweaks{}); err != nil {
   425  		panic(err)
   426  	}
   427  
   428  	crt0o = b.Bytes()
   429  }
   430  
   431  // Command outputs a Go program generated from in to w.
   432  //
   433  // No package or import clause is generated.
   434  func Command(w io.Writer, in []*cc.TranslationUnit) (err error) {
   435  	returned := false
   436  
   437  	defer func() {
   438  		if e := recover(); !returned && err == nil {
   439  			err = fmt.Errorf("PANIC: %v\n%s", e, compact(string(debugStack()), compactStack))
   440  		}
   441  	}()
   442  
   443  	err = newGen(w, in).gen(true)
   444  	returned = true
   445  	return err
   446  }
   447  
   448  func TestOpt(t *testing.T) {
   449  	for _, v := range []struct{ in, out string }{
   450  		{"var _ = (a(b))", "var _ = a(b)"},
   451  		{"var _ = ((a)(b))", "var _ = a(b)"},
   452  		{"var _ = *((*a)(b))", "var _ = *(*a)(b)"},
   453  	} {
   454  		in := bytes.NewBufferString(v.in)
   455  		var out bytes.Buffer
   456  		if err := newOpt().do(&out, in, "TestOp", 0); err != nil {
   457  			t.Fatal(err)
   458  		}
   459  
   460  		if g, e := bytes.TrimSpace(out.Bytes()), []byte(v.out); !bytes.Equal(g, e) {
   461  			t.Fatalf("got\n%s\nexp\n%s", g, e)
   462  		}
   463  	}
   464  }
   465  
   466  func trim(b []byte) []byte {
   467  	a := bytes.Split(b, []byte{'\n'})
   468  	for i, v := range a {
   469  		a[i] = bytes.TrimRight(v, " ")
   470  	}
   471  	return bytes.Join(a, []byte{'\n'})
   472  }
   473  
   474  func translate(tweaks *cc.Tweaks, includePaths, sysIncludePaths []string, def string, sources ...cc.Source) (*cc.TranslationUnit, error) {
   475  	in := []cc.Source{defCCGO, cc.MustBuiltin()}
   476  	if def != "" {
   477  		in = append(in, cc.NewStringSource("<defines>", def))
   478  	}
   479  	in = append(in, sources...)
   480  	if *oTrace {
   481  		fmt.Fprintln(os.Stderr, in)
   482  	}
   483  	return cc.Translate(tweaks, includePaths, sysIncludePaths, in...)
   484  }
   485  
   486  func test(t *testing.T, clean bool, c, ccgo, build, run *int, def, imp string, inc2 []string, dir string, pth []string, args ...string) ([]byte, error) {
   487  	testFn = pth[len(pth)-1]
   488  	if clean {
   489  		m, err := filepath.Glob(filepath.Join(dir, "*.*"))
   490  		if err != nil {
   491  			t.Fatal(err)
   492  		}
   493  
   494  		for _, v := range m {
   495  			if err := os.Remove(v); err != nil {
   496  				t.Fatal(err)
   497  			}
   498  		}
   499  	}
   500  
   501  	tweaks := &cc.Tweaks{
   502  		// TrackExpand:                 func(s string) { fmt.Print(s) }, //TODO-
   503  		EnableAnonymousStructFields: true,
   504  		EnableEmptyStructs:          true,
   505  		EnableImplicitBuiltins:      true,
   506  		EnableImplicitDeclarations:  true,
   507  		EnableOmitFuncDeclSpec:      true,
   508  		EnablePointerCompatibility:  true, // CSmith transparent_crc_bytes
   509  		EnableReturnExprInVoidFunc:  true,
   510  		IgnorePragmas:               true,
   511  		InjectFinalNL:               true,
   512  	}
   513  	inc := append([]string{"@"}, inc2...)
   514  
   515  	crt0, err := cc.Translate(tweaks, inc, searchPaths, defCCGO, cc.MustBuiltin(), cc.MustCrt0())
   516  	if err != nil {
   517  		return nil, err
   518  	}
   519  
   520  	tus := []*cc.TranslationUnit{crt0}
   521  	for _, v := range pth {
   522  		tu, err := translate(tweaks, inc, searchPaths, def, cc.MustFileSource2(v, false))
   523  		if err != nil {
   524  			//dbg("cc: %v", errString(err)) //TODO-
   525  			if !*oCC {
   526  				err = nil
   527  			}
   528  			return nil, err
   529  		}
   530  
   531  		tus = append(tus, tu)
   532  	}
   533  
   534  	*c++
   535  	f, err := os.Create(filepath.Join(dir, "main.go"))
   536  	if err != nil {
   537  		t.Fatal(err)
   538  	}
   539  
   540  	w := bufio.NewWriter(f)
   541  	w.WriteString(`package main
   542  	
   543  import (
   544  	"math"
   545  	"os"
   546  	"unsafe"
   547  
   548  	"github.com/cznic/crt"
   549  )
   550  
   551  var _ = math.Inf
   552  `)
   553  	w.WriteString(imp)
   554  	if err := Command(w, tus); err != nil {
   555  		//dbg("ccgo: %v", errString(err)) //TODO-
   556  		if !*oCCGO {
   557  			err = nil
   558  		}
   559  		return nil, err
   560  	}
   561  
   562  	if err := w.Flush(); err != nil {
   563  		t.Fatal(err)
   564  	}
   565  
   566  	if err := f.Close(); err != nil {
   567  		t.Fatal(err)
   568  	}
   569  
   570  	*ccgo++
   571  
   572  	if out, err := exec.Command("go", "build", "-o", filepath.Join(dir, "main"), f.Name()).CombinedOutput(); err != nil {
   573  		//dbg("build: %v", errString(err)) //TODO-
   574  		if !*oBuild {
   575  			return nil, nil
   576  		}
   577  
   578  		return nil, fmt.Errorf("%v: %s", err, out)
   579  	}
   580  
   581  	*build++
   582  
   583  	cwd, err := os.Getwd()
   584  	if err != nil {
   585  		t.Fatal(err)
   586  	}
   587  
   588  	defer func() {
   589  		if err := os.Chdir(cwd); err != nil {
   590  			t.Fatal(err)
   591  		}
   592  	}()
   593  
   594  	if err := os.Chdir(dir); err != nil {
   595  		t.Fatal(err)
   596  	}
   597  
   598  	ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
   599  
   600  	defer cancel()
   601  
   602  	out, err := exec.CommandContext(ctx, filepath.Join(dir, "main"), args...).CombinedOutput()
   603  	switch {
   604  	case err != nil:
   605  		//dbg("run: %v", errString(err)) //TODO-
   606  	default:
   607  		*run++
   608  	}
   609  	return out, err
   610  }
   611  
   612  func TestTCC0(t *testing.T) { //TODO-
   613  	cc.FlushCache()
   614  	blacklist := map[string]struct{}{
   615  		"13_integer_literals.c": {}, // 9:12: ExprInt strconv.ParseUint: parsing "0b010101010101": invalid syntax
   616  		"31_args.c":             {},
   617  		"34_array_assignment.c": {}, // gcc: main.c:16:6: error: incompatible types when assigning to type ‘int[4]’ from type ‘int *’
   618  		"46_grep.c":             {}, // incompatible forward declaration type
   619  	}
   620  
   621  	if s := *oRE; s != "" {
   622  		re = regexp.MustCompile(s)
   623  	}
   624  
   625  	dir := *oTmp
   626  	if dir == "" {
   627  		var err error
   628  		if dir, err = ioutil.TempDir("", "test-ccgo-tcc-"); err != nil {
   629  			t.Fatal(err)
   630  		}
   631  
   632  		defer func() {
   633  			if err := os.RemoveAll(dir); err != nil {
   634  				t.Fatal(err)
   635  			}
   636  		}()
   637  	}
   638  
   639  	m, err := filepath.Glob(filepath.FromSlash("testdata/tcc-0.9.26/tests/tests2/*.c"))
   640  	if err != nil {
   641  		t.Fatal(err)
   642  	}
   643  
   644  	var cc, ccgo, build, run, ok, n int
   645  	for _, pth := range m {
   646  		if re != nil && !re.MatchString(filepath.Base(pth)) {
   647  			continue
   648  		}
   649  
   650  		if _, ok := blacklist[filepath.Base(pth)]; ok {
   651  			continue
   652  		}
   653  
   654  		run0 := run
   655  		n++
   656  		out, err := test(t, false, &cc, &ccgo, &build, &run, "", "", nil, dir, []string{pth})
   657  		if err != nil {
   658  			t.Errorf("%v: %v", pth, err)
   659  			continue
   660  		}
   661  
   662  		if run == run0 {
   663  			continue
   664  		}
   665  
   666  		fn := pth[:len(pth)-len(filepath.Ext(pth))] + ".expect"
   667  		s, err := ioutil.ReadFile(fn)
   668  		if err != nil {
   669  			if os.IsNotExist(err) {
   670  				ok++
   671  				continue
   672  			}
   673  		}
   674  
   675  		out = trim(out)
   676  		s = trim(s)
   677  		if !bytes.Equal(out, s) {
   678  			t.Errorf("%s\ngot\n%s\nexp\n%s----\ngot\n%s\nexp\n%s", pth, hex.Dump(out), hex.Dump(s), out, s)
   679  			continue
   680  		}
   681  
   682  		ok++
   683  	}
   684  	if cc != n || ccgo != n || build != n || run != n || ok != n {
   685  		t.Fatalf("cc %v ccgo %v build %v run %v ok %v", cc, ccgo, build, run, ok)
   686  	}
   687  
   688  	if *oEdit {
   689  		fmt.Printf("TCC0\tcc %v ccgo %v build %v run %v ok %v\n", cc, ccgo, build, run, ok)
   690  	}
   691  }
   692  
   693  func TestTCC(t *testing.T) {
   694  	blacklist := map[string]struct{}{
   695  		"13_integer_literals.c": {}, // 9:12: ExprInt strconv.ParseUint: parsing "0b010101010101": invalid syntax
   696  		"31_args.c":             {},
   697  		"34_array_assignment.c": {}, // gcc: main.c:16:6: error: incompatible types when assigning to type ‘int[4]’ from type ‘int *’
   698  		"46_grep.c":             {}, // incompatible forward declaration type
   699  	}
   700  
   701  	var re *regexp.Regexp
   702  	if s := *oRE; s != "" {
   703  		re = regexp.MustCompile(s)
   704  	}
   705  
   706  	dir := *oTmp
   707  	if dir == "" {
   708  		var err error
   709  		if dir, err = ioutil.TempDir("", "test-ccgo-tcc-"); err != nil {
   710  			t.Fatal(err)
   711  		}
   712  
   713  		defer func() {
   714  			if err := os.RemoveAll(dir); err != nil {
   715  				t.Fatal(err)
   716  			}
   717  		}()
   718  	}
   719  
   720  	compiler, err := compileCCGO(dir)
   721  	if err != nil {
   722  		t.Fatal(err)
   723  	}
   724  
   725  	root, err := filepath.Abs(filepath.FromSlash("testdata/tcc-0.9.26/tests/tests2/*.c"))
   726  	if err != nil {
   727  		t.Fatal(err)
   728  	}
   729  
   730  	m, err := filepath.Glob(root)
   731  	if err != nil {
   732  		t.Fatal(err)
   733  	}
   734  
   735  	cwd, err := os.Getwd()
   736  	if err != nil {
   737  		t.Fatal(err)
   738  	}
   739  
   740  	if err := os.Chdir(dir); err != nil {
   741  		t.Fatal(err)
   742  	}
   743  
   744  	defer func() {
   745  		if err := os.Chdir(cwd); err != nil {
   746  			t.Fatal(err)
   747  		}
   748  	}()
   749  
   750  	testGo := filepath.Join(dir, "main.go")
   751  	testBin := filepath.Join(dir, "main")
   752  	var c, ccgo, build, run, ok, n int
   753  	for _, pth := range m {
   754  		if re != nil && !re.MatchString(filepath.Base(pth)) {
   755  			continue
   756  		}
   757  
   758  		if _, ok := blacklist[filepath.Base(pth)]; ok {
   759  			continue
   760  		}
   761  
   762  		if *oTrace {
   763  			fmt.Fprintln(os.Stderr, pth)
   764  		}
   765  		n++
   766  		out, err := exec.Command(compiler, "-o", testGo, pth).CombinedOutput()
   767  		if err != nil {
   768  			t.Logf("%s: %s\n%v", pth, out, err)
   769  			continue
   770  		}
   771  
   772  		c++
   773  		ccgo++
   774  		if out, err := exec.Command("go", "build", "-o", testBin, testGo).CombinedOutput(); err != nil {
   775  			t.Logf("%s: %s\n%v", pth, out, err)
   776  			continue
   777  		}
   778  
   779  		build++
   780  		if out, err = exec.Command(testBin).CombinedOutput(); err != nil {
   781  			t.Logf("%s\n%v", out, err)
   782  			continue
   783  		}
   784  
   785  		run++
   786  		expect, err := ioutil.ReadFile(pth[:len(pth)-len(filepath.Ext(pth))] + ".expect")
   787  		if err != nil {
   788  			if os.IsNotExist(err) {
   789  				ok++
   790  				continue
   791  			}
   792  		}
   793  
   794  		out = trim(out)
   795  		expect = trim(expect)
   796  		if !bytes.Equal(out, expect) {
   797  			t.Logf("%s\ngot\n%s\nexp\n%s----\ngot\n%s\nexp\n%s", pth, hex.Dump(out), hex.Dump(expect), out, expect)
   798  			continue
   799  		}
   800  
   801  		ok++
   802  	}
   803  	if c != n || ccgo != n || build != n || run != n || ok != n {
   804  		t.Fatalf("TCC cc %v ccgo %v build %v run %v ok %v n %v", c, ccgo, build, run, ok, n)
   805  	}
   806  
   807  	if *oEdit {
   808  		fmt.Printf("TCC\tcc %v ccgo %v build %v run %v ok %v n %v\n", c, ccgo, build, run, ok, n)
   809  	}
   810  }
   811  
   812  func compileCCGO(dir string) (string, error) {
   813  	ip, err := strutil.ImportPath()
   814  	if err != nil {
   815  		return "", err
   816  	}
   817  
   818  	ip = filepath.Join(ip, "ccgo")
   819  	compiler := filepath.Join(dir, "ccgo")
   820  	out, err := exec.Command("go", "build", "-o", compiler, ip).CombinedOutput()
   821  	if err != nil {
   822  		return "", fmt.Errorf("%s\n%v", out, err)
   823  	}
   824  
   825  	return compiler, nil
   826  }
   827  
   828  func TestOther0(t *testing.T) { //TODO-
   829  	cc.FlushCache()
   830  	if s := *oRE; s != "" {
   831  		re = regexp.MustCompile(s)
   832  	}
   833  
   834  	dir, err := ioutil.TempDir("", "test-ccgo-other-")
   835  	if err != nil {
   836  		t.Fatal(err)
   837  	}
   838  
   839  	defer func() {
   840  		if err := os.RemoveAll(dir); err != nil {
   841  			t.Fatal(err)
   842  		}
   843  	}()
   844  
   845  	m, err := filepath.Glob(filepath.FromSlash("testdata/bug/*.c"))
   846  	if err != nil {
   847  		t.Fatal(err)
   848  	}
   849  
   850  	var cc, ccgo, build, run, ok, n int
   851  	for _, pth := range m {
   852  		if b := filepath.Base(pth); b == "log.c" && *oRE != "log.c" || re != nil && !re.MatchString(b) {
   853  			continue
   854  		}
   855  
   856  		run0 := run
   857  		n++
   858  		out, err := test(t, false, &cc, &ccgo, &build, &run, "", "", strings.Split(*oI, ","), dir, []string{pth})
   859  		if err != nil {
   860  			t.Errorf("%v: %v", pth, err)
   861  			continue
   862  		}
   863  
   864  		if run == run0 {
   865  			continue
   866  		}
   867  
   868  		fn := pth[:len(pth)-len(filepath.Ext(pth))] + ".expect"
   869  		s, err := ioutil.ReadFile(fn)
   870  		if err != nil {
   871  			if os.IsNotExist(err) {
   872  				ok++
   873  				continue
   874  			}
   875  		}
   876  
   877  		out = trim(out)
   878  		s = trim(s)
   879  		if !bytes.Equal(out, s) {
   880  			t.Errorf("%s\ngot\n%s\nexp\n%s----\ngot\n%s\nexp\n%s", pth, hex.Dump(out), hex.Dump(s), out, s)
   881  			continue
   882  		}
   883  
   884  		ok++
   885  	}
   886  	if cc != n || ccgo != n || build != n || run != n || ok != n {
   887  		t.Fatalf("cc %v ccgo %v build %v run %v ok %v", cc, ccgo, build, run, ok)
   888  	}
   889  
   890  	if *oEdit {
   891  		fmt.Printf("Other0\tcc %v ccgo %v build %v run %v ok %v\n", cc, ccgo, build, run, ok)
   892  	}
   893  }
   894  
   895  func TestOther(t *testing.T) {
   896  	var re *regexp.Regexp
   897  	if s := *oRE; s != "" {
   898  		re = regexp.MustCompile(s)
   899  	}
   900  
   901  	dir := *oTmp
   902  	if dir == "" {
   903  		var err error
   904  		if dir, err = ioutil.TempDir("", "test-ccgo-other-"); err != nil {
   905  			t.Fatal(err)
   906  		}
   907  
   908  		defer func() {
   909  			if err := os.RemoveAll(dir); err != nil {
   910  				t.Fatal(err)
   911  			}
   912  		}()
   913  	}
   914  
   915  	compiler, err := compileCCGO(dir)
   916  	if err != nil {
   917  		t.Fatal(err)
   918  	}
   919  
   920  	root, err := filepath.Abs(filepath.FromSlash("testdata/bug/*.c"))
   921  	if err != nil {
   922  		t.Fatal(err)
   923  	}
   924  
   925  	m, err := filepath.Glob(root)
   926  	if err != nil {
   927  		t.Fatal(err)
   928  	}
   929  
   930  	cwd, err := os.Getwd()
   931  	if err != nil {
   932  		t.Fatal(err)
   933  	}
   934  
   935  	if err := os.Chdir(dir); err != nil {
   936  		t.Fatal(err)
   937  	}
   938  
   939  	defer func() {
   940  		if err := os.Chdir(cwd); err != nil {
   941  			t.Fatal(err)
   942  		}
   943  	}()
   944  
   945  	testGo := filepath.Join(dir, "main.go")
   946  	testBin := filepath.Join(dir, "main")
   947  	var c, ccgo, build, run, ok, n int
   948  	for _, pth := range m {
   949  		if re != nil && !re.MatchString(filepath.Base(pth)) {
   950  			continue
   951  		}
   952  
   953  		if *oTrace {
   954  			fmt.Fprintln(os.Stderr, pth)
   955  		}
   956  		n++
   957  		out, err := exec.Command(compiler, "-o", testGo, pth).CombinedOutput()
   958  		if err != nil {
   959  			t.Logf("%s: %s\n%v", pth, out, err)
   960  			continue
   961  		}
   962  
   963  		c++
   964  		ccgo++
   965  		if out, err := exec.Command("go", "build", "-o", testBin, testGo).CombinedOutput(); err != nil {
   966  			t.Logf("%s: %s\n%v", pth, out, err)
   967  			continue
   968  		}
   969  
   970  		build++
   971  		if out, err = exec.Command(testBin).CombinedOutput(); err != nil {
   972  			t.Logf("%s\n%v", out, err)
   973  			continue
   974  		}
   975  
   976  		run++
   977  		expect, err := ioutil.ReadFile(pth[:len(pth)-len(filepath.Ext(pth))] + ".expect")
   978  		if err != nil {
   979  			if os.IsNotExist(err) {
   980  				ok++
   981  				continue
   982  			}
   983  		}
   984  
   985  		out = trim(out)
   986  		expect = trim(expect)
   987  		if !bytes.Equal(out, expect) {
   988  			t.Logf("%s\ngot\n%s\nexp\n%s----\ngot\n%s\nexp\n%s", pth, hex.Dump(out), hex.Dump(expect), out, expect)
   989  			continue
   990  		}
   991  
   992  		ok++
   993  	}
   994  	if c != n || ccgo != n || build != n || run != n || ok != n {
   995  		t.Fatalf("Other\tcc %v ccgo %v build %v run %v ok %v n %v", c, ccgo, build, run, ok, n)
   996  	}
   997  
   998  	if *oEdit {
   999  		fmt.Printf("Other\tcc %v ccgo %v build %v run %v ok %v n %v\n", c, ccgo, build, run, ok, n)
  1000  	}
  1001  }
  1002  
  1003  func TestGCC0(t *testing.T) { //TODO-
  1004  	cc.FlushCache()
  1005  	const def = `
  1006  #define SIGNAL_SUPPRESS // gcc.c-torture/execute/20101011-1.c
  1007  `
  1008  	blacklist := map[string]struct{}{
  1009  		"20010904-1.c":    {}, // __attribute__((aligned(32)))
  1010  		"20010904-2.c":    {}, // __attribute__((aligned(32)))
  1011  		"20021127-1.c":    {}, // non standard GCC behavior
  1012  		"eeprof-1.c":      {}, // Need profiler code instrumentation
  1013  		"pr23467.c":       {}, // __attribute__ ((aligned (8)))
  1014  		"pr67037.c":       {}, // void f(); f(); f(42)
  1015  		"pushpop_macro.c": {}, // #pragma push_macro("_")
  1016  		"zerolen-2.c":     {}, // The Go translation makes the last zero items array to have size 1.
  1017  
  1018  		"20000703-1.c":                 {}, //TODO statement expression
  1019  		"20040411-1.c":                 {}, //TODO VLA
  1020  		"20040423-1.c":                 {}, //TODO VLA
  1021  		"20040629-1.c":                 {}, //TODO bits, arithmetic precision
  1022  		"20040705-1.c":                 {}, //TODO bits, arithmetic precision
  1023  		"20040705-2.c":                 {}, //TODO bits, arithmetic precision
  1024  		"20041218-2.c":                 {}, //TODO VLA
  1025  		"20101011-1.c":                 {}, //TODO Needs sigfpe on int division by zero
  1026  		"921016-1.c":                   {}, //TODO bits, arithmetic precision
  1027  		"970217-1.c":                   {}, //TODO VLA
  1028  		"bitfld-1.c":                   {}, //TODO bits, arithmetic precision
  1029  		"bitfld-3.c":                   {}, //TODO bits, arithmetic precision
  1030  		"builtin-types-compatible-p.c": {}, //TODO must track type qualifiers
  1031  		"pr32244-1.c":                  {}, //TODO bits, arithmetic precision
  1032  		"pr34971.c":                    {}, //TODO bits, arithmetic precision
  1033  		"pr77767.c":                    {}, //TODO VLA
  1034  
  1035  		//TODO bit field arithmetic
  1036  		// 20040709-1.c
  1037  		// 20040709-2.c
  1038  
  1039  	}
  1040  
  1041  	if s := *oRE; s != "" {
  1042  		re = regexp.MustCompile(s)
  1043  	}
  1044  
  1045  	dir := *oTmp
  1046  	if dir == "" {
  1047  		var err error
  1048  		if dir, err = ioutil.TempDir("", "test-ccgo-gcc-"); err != nil {
  1049  			t.Fatal(err)
  1050  		}
  1051  
  1052  		defer func() {
  1053  			if err := os.RemoveAll(dir); err != nil {
  1054  				t.Fatal(err)
  1055  			}
  1056  		}()
  1057  	}
  1058  
  1059  	m, err := filepath.Glob(filepath.FromSlash("testdata/github.com/gcc-mirror/gcc/gcc/testsuite/gcc.c-torture/execute/*.c"))
  1060  	if err != nil {
  1061  		t.Fatal(err)
  1062  	}
  1063  
  1064  	var cc, ccgo, build, run, ok int
  1065  	for _, pth := range m {
  1066  		if re != nil && !re.MatchString(filepath.Base(pth)) {
  1067  			continue
  1068  		}
  1069  
  1070  		if _, ok := blacklist[filepath.Base(pth)]; ok {
  1071  			continue
  1072  		}
  1073  
  1074  		run0 := run
  1075  		out, err := test(t, false, &cc, &ccgo, &build, &run, def, "", nil, dir, []string{pth})
  1076  		if err != nil {
  1077  			t.Errorf("%v: %v", pth, err)
  1078  			continue
  1079  		}
  1080  
  1081  		if run == run0 {
  1082  			continue
  1083  		}
  1084  
  1085  		fn := pth[:len(pth)-len(filepath.Ext(pth))] + ".expect"
  1086  		s, err := ioutil.ReadFile(fn)
  1087  		if err != nil {
  1088  			if os.IsNotExist(err) {
  1089  				ok++
  1090  				continue
  1091  			}
  1092  		}
  1093  
  1094  		out = trim(out)
  1095  		s = trim(s)
  1096  		if !bytes.Equal(out, s) {
  1097  			t.Errorf("%s\ngot\n%s\nexp\n%s----\ngot\n%s\nexp\n%s", pth, hex.Dump(out), hex.Dump(s), out, s)
  1098  			continue
  1099  		}
  1100  
  1101  		ok++
  1102  	}
  1103  	if run == 0 || run != build || ok != build {
  1104  		t.Fatalf("cc %v ccgo %v build %v run %v ok %v", cc, ccgo, build, run, ok)
  1105  	}
  1106  
  1107  	if *oEdit {
  1108  		fmt.Printf("GCC0\tcc %v ccgo %v build %v run %v ok %v\n", cc, ccgo, build, run, ok)
  1109  	}
  1110  }
  1111  
  1112  func TestGCC(t *testing.T) {
  1113  	blacklist := map[string]struct{}{
  1114  		"20010904-1.c":    {}, // __attribute__((aligned(32)))
  1115  		"20010904-2.c":    {}, // __attribute__((aligned(32)))
  1116  		"20021127-1.c":    {}, // non standard GCC behavior
  1117  		"pr23467.c":       {}, // __attribute__ ((aligned (8)))
  1118  		"pr67037.c":       {}, // void f(); f(); f(42)
  1119  		"pushpop_macro.c": {}, // #pragma push_macro("_")
  1120  		"eeprof-1.c":      {}, // requires profiler instrumentation
  1121  
  1122  		"20000703-1.c":                 {}, //TODO statement expression
  1123  		"20040411-1.c":                 {}, //TODO VLA
  1124  		"20040423-1.c":                 {}, //TODO VLA
  1125  		"20040629-1.c":                 {}, //TODO bits, arithmetic precision
  1126  		"20040705-1.c":                 {}, //TODO bits, arithmetic precision
  1127  		"20040705-2.c":                 {}, //TODO bits, arithmetic precision
  1128  		"20041218-2.c":                 {}, //TODO VLA
  1129  		"20101011-1.c":                 {}, //TODO Needs sigfpe on int division by zero
  1130  		"921016-1.c":                   {}, //TODO bits, arithmetic precision
  1131  		"970217-1.c":                   {}, //TODO VLA
  1132  		"bitfld-1.c":                   {}, //TODO bits, arithmetic precision
  1133  		"bitfld-3.c":                   {}, //TODO bits, arithmetic precision
  1134  		"builtin-types-compatible-p.c": {}, //TODO must track type qualifiers
  1135  		"pr32244-1.c":                  {}, //TODO bits, arithmetic precision
  1136  		"pr34971.c":                    {}, //TODO bits, arithmetic precision
  1137  		"pr77767.c":                    {}, //TODO VLA
  1138  		"zerolen-2.c":                  {}, //TODO The Go translation makes the last zero items array to have size 1.
  1139  
  1140  		//TODO bit field arithmetic
  1141  		// 20040709-1.c
  1142  		// 20040709-2.c
  1143  
  1144  	}
  1145  	var re *regexp.Regexp
  1146  	if s := *oRE; s != "" {
  1147  		re = regexp.MustCompile(s)
  1148  	}
  1149  
  1150  	dir := *oTmp
  1151  	if dir == "" {
  1152  		var err error
  1153  		if dir, err = ioutil.TempDir("", "test-ccgo-gcc-"); err != nil {
  1154  			t.Fatal(err)
  1155  		}
  1156  
  1157  		defer func() {
  1158  			if err := os.RemoveAll(dir); err != nil {
  1159  				t.Fatal(err)
  1160  			}
  1161  		}()
  1162  	}
  1163  
  1164  	compiler, err := compileCCGO(dir)
  1165  	if err != nil {
  1166  		t.Fatal(err)
  1167  	}
  1168  
  1169  	root, err := filepath.Abs(filepath.FromSlash("testdata/github.com/gcc-mirror/gcc/gcc/testsuite/gcc.c-torture/execute/*.c"))
  1170  	if err != nil {
  1171  		t.Fatal(err)
  1172  	}
  1173  
  1174  	m, err := filepath.Glob(root)
  1175  	if err != nil {
  1176  		t.Fatal(err)
  1177  	}
  1178  
  1179  	cwd, err := os.Getwd()
  1180  	if err != nil {
  1181  		t.Fatal(err)
  1182  	}
  1183  
  1184  	if err := os.Chdir(dir); err != nil {
  1185  		t.Fatal(err)
  1186  	}
  1187  
  1188  	defer func() {
  1189  		if err := os.Chdir(cwd); err != nil {
  1190  			t.Fatal(err)
  1191  		}
  1192  	}()
  1193  
  1194  	testGo := filepath.Join(dir, "main.go")
  1195  	testBin := filepath.Join(dir, "main")
  1196  	var c, ccgo, build, run, ok, n int
  1197  	for _, pth := range m {
  1198  		if re != nil && !re.MatchString(filepath.Base(pth)) {
  1199  			continue
  1200  		}
  1201  
  1202  		if _, ok := blacklist[filepath.Base(pth)]; ok {
  1203  			continue
  1204  		}
  1205  
  1206  		if *oTrace {
  1207  			fmt.Fprintln(os.Stderr, pth)
  1208  		}
  1209  		n++
  1210  		out, err := exec.Command(compiler, "-o", testGo, pth).CombinedOutput()
  1211  		if err != nil {
  1212  			t.Logf("%s: %s\n%v", pth, out, err)
  1213  			continue
  1214  		}
  1215  
  1216  		c++
  1217  		ccgo++
  1218  		if out, err := exec.Command("go", "build", "-o", testBin, testGo).CombinedOutput(); err != nil {
  1219  			t.Errorf("%s: %s\n%v", pth, out, err)
  1220  			continue
  1221  		}
  1222  
  1223  		build++
  1224  		if out, err = exec.Command(testBin).CombinedOutput(); err != nil {
  1225  			t.Errorf("%s\n%v", out, err)
  1226  			continue
  1227  		}
  1228  
  1229  		run++
  1230  		expect, err := ioutil.ReadFile(pth[:len(pth)-len(filepath.Ext(pth))] + ".expect")
  1231  		if err != nil {
  1232  			if os.IsNotExist(err) {
  1233  				ok++
  1234  				continue
  1235  			}
  1236  		}
  1237  
  1238  		out = trim(out)
  1239  		expect = trim(expect)
  1240  		if !bytes.Equal(out, expect) {
  1241  			t.Errorf("%s\ngot\n%s\nexp\n%s----\ngot\n%s\nexp\n%s", pth, hex.Dump(out), hex.Dump(expect), out, expect)
  1242  			continue
  1243  		}
  1244  
  1245  		ok++
  1246  	}
  1247  
  1248  	if run == 0 || run != build || ok != build {
  1249  		t.Fatalf("cc %v ccgo %v build %v run %v ok %v n %v", c, ccgo, build, run, ok, n)
  1250  	}
  1251  
  1252  	if *oEdit {
  1253  		fmt.Printf("GCC\tcc %v ccgo %v build %v run %v ok %v n %v\n", c, ccgo, build, run, ok, n)
  1254  	}
  1255  }
  1256  
  1257  func TestSQLiteShell0(t *testing.T) { //TODO-
  1258  	cc.FlushCache()
  1259  	dir := *oTmp
  1260  	if dir == "" {
  1261  		var err error
  1262  		if dir, err = ioutil.TempDir("", "test-ccgo-shell-"); err != nil {
  1263  			t.Fatal(err)
  1264  		}
  1265  
  1266  		defer func() {
  1267  			if err := os.RemoveAll(dir); err != nil {
  1268  				t.Fatal(err)
  1269  			}
  1270  		}()
  1271  	}
  1272  
  1273  	var cc, ccgo, build, run, ok int
  1274  	root := filepath.FromSlash("testdata/_sqlite/sqlite-amalgamation-3210000")
  1275  	if out, err := test(t, false, &cc, &ccgo, &build, &run, `
  1276  		#define HAVE_FDATASYNC 1
  1277  		#define HAVE_ISNAN 1
  1278  		#define HAVE_LOCALTIME_R 1
  1279  		#define HAVE_USLEEP 1
  1280  		#define SQLITE_DEBUG 1
  1281  		#define SQLITE_MEMDEBUG 1
  1282  		/* #define HAVE_MALLOC_USABLE_SIZE 1 */
  1283  `,
  1284  		"",
  1285  		nil,
  1286  		dir,
  1287  		[]string{
  1288  			filepath.Join(root, "shell.c"),
  1289  			filepath.Join(root, "sqlite3.c"),
  1290  		},
  1291  		"foo", "create table t(i)",
  1292  	); err != nil {
  1293  		t.Fatalf("%s: %v", out, errString(err))
  1294  	}
  1295  
  1296  	if run == 1 {
  1297  		ok++
  1298  	}
  1299  	if ok != 1 {
  1300  		t.Fatalf("cc %v ccgo %v build %v run %v ok %v", cc, ccgo, build, run, ok)
  1301  	}
  1302  
  1303  	if *oEdit {
  1304  		fmt.Printf("Shell0\tcc %v ccgo %v build %v run %v ok %v\n", cc, ccgo, build, run, ok)
  1305  	}
  1306  }
  1307  
  1308  func TestSQLiteShell(t *testing.T) {
  1309  	dir := *oTmp
  1310  	if dir == "" {
  1311  		var err error
  1312  		if dir, err = ioutil.TempDir("", "test-ccgo-sqlite-shell-"); err != nil {
  1313  			t.Fatal(err)
  1314  		}
  1315  
  1316  		defer func() {
  1317  			if err := os.RemoveAll(dir); err != nil {
  1318  				t.Fatal(err)
  1319  			}
  1320  		}()
  1321  	}
  1322  
  1323  	compiler, err := compileCCGO(dir)
  1324  	if err != nil {
  1325  		t.Fatal(err)
  1326  	}
  1327  
  1328  	root, err := filepath.Abs(filepath.FromSlash("testdata/_sqlite/sqlite-amalgamation-3210000"))
  1329  	if err != nil {
  1330  		t.Fatal(err)
  1331  	}
  1332  
  1333  	cwd, err := os.Getwd()
  1334  	if err != nil {
  1335  		t.Fatal(err)
  1336  	}
  1337  
  1338  	if err := os.Chdir(dir); err != nil {
  1339  		t.Fatal(err)
  1340  	}
  1341  
  1342  	defer func() {
  1343  		if err := os.Chdir(cwd); err != nil {
  1344  			t.Fatal(err)
  1345  		}
  1346  	}()
  1347  
  1348  	var c, ccgo, build, run, ok, n int
  1349  	for {
  1350  		n++
  1351  		out, err := exec.Command(compiler, filepath.Join(root, "shell.c"), filepath.Join(root, "sqlite3.c")).CombinedOutput()
  1352  		if err != nil {
  1353  			t.Logf("%s: %s\n%v", dir, out, err)
  1354  			break
  1355  		}
  1356  
  1357  		os.Remove(compiler)
  1358  		c++
  1359  		ccgo++
  1360  		build++
  1361  		m, err := filepath.Glob(filepath.Join(dir, "*"))
  1362  		if err != nil {
  1363  			t.Log(err)
  1364  			break
  1365  
  1366  		}
  1367  
  1368  		if len(m) != 1 {
  1369  			t.Fatal(len(m))
  1370  		}
  1371  
  1372  		if out, err = exec.Command(m[0], "foo", "create table t(i)").CombinedOutput(); err != nil {
  1373  			t.Logf("%s\n%v", out, err)
  1374  			break
  1375  		}
  1376  
  1377  		run++
  1378  		ok++
  1379  		break
  1380  	}
  1381  	if c != n || ccgo != n || build != n || run != n || ok != n {
  1382  		t.Fatalf("Shell cc %v ccgo %v build %v run %v ok %v n %v", c, ccgo, build, run, ok, n)
  1383  	}
  1384  
  1385  	if *oEdit {
  1386  		fmt.Printf("Shell\tcc %v ccgo %v build %v run %v ok %v n %v\n", c, ccgo, build, run, ok, n)
  1387  	}
  1388  }
  1389  
  1390  func TestTCL0(t *testing.T) { //TODO-
  1391  	cc.FlushCache()
  1392  	const (
  1393  		allDefs = `// Output of gcc features.c && ./a.out in github.com/cznic/sqlite2go/internal/c99/headers on linux_amd64.
  1394  			#define _POSIX_SOURCE 1
  1395  			#define _POSIX_C_SOURCE 200809
  1396  			#define _DEFAULT_SOURCE 1
  1397  `
  1398  		sqlite     = "_sqlite"
  1399  		sqliteDefs = `
  1400  			#define HAVE_FDATASYNC 1
  1401  			#define HAVE_ISNAN 1
  1402  			#define HAVE_LOCALTIME_R 1
  1403  			#define HAVE_USLEEP 1
  1404  			#define SQLITE_CORE 1 // Must be defined for TCL extensions to work.
  1405  			#define SQLITE_DEBUG 1
  1406  			#define SQLITE_ENABLE_RBU 1
  1407  			#define SQLITE_PRIVATE
  1408  			#define SQLITE_TEST 1
  1409  			#define TCLSH_INIT_PROC sqlite3TestInit
  1410  			/* #define HAVE_MALLOC_USABLE_SIZE 1 */
  1411  			// #define SQLITE_MEMDEBUG 1 //TODO wants execinfo.backtrace*
  1412  `
  1413  		tcl      = "_tcl8.6.8"
  1414  		tclDefs0 = `
  1415  			#define BUILD_tcl
  1416  			#define CFG_INSTALL_BINDIR "/usr/local/bin"
  1417  			#define CFG_INSTALL_DOCDIR "/usr/local/man"
  1418  			#define CFG_INSTALL_INCDIR "/usr/local/include"
  1419  			#define CFG_INSTALL_LIBDIR "/usr/local/lib64"
  1420  			#define CFG_INSTALL_SCRDIR "/usr/local/lib/tcl8.6"
  1421  			#define CFG_RUNTIME_BINDIR "/usr/local/bin"
  1422  			#define CFG_RUNTIME_DOCDIR "/usr/local/man"
  1423  			#define CFG_RUNTIME_INCDIR "/usr/local/include"
  1424  			#define CFG_RUNTIME_LIBDIR "/usr/local/lib64"
  1425  			#define CFG_RUNTIME_SCRDIR "/usr/local/lib/tcl8.6"
  1426  			#define HAVE_BLKCNT_T 1
  1427  			#define HAVE_CAST_TO_UNION 1
  1428  			#define HAVE_FREEADDRINFO 1
  1429  			#define HAVE_FTS 1
  1430  			#define HAVE_GAI_STRERROR 1
  1431  			#define HAVE_GETADDRINFO 1
  1432  			#define HAVE_GETCWD 1
  1433  			#define HAVE_GETGRGID_R 1
  1434  			#define HAVE_GETGRGID_R_5 1
  1435  			#define HAVE_GETGRNAM_R 1
  1436  			#define HAVE_GETGRNAM_R_5 1
  1437  			#define HAVE_GETHOSTBYADDR_R 1
  1438  			#define HAVE_GETNAMEINFO 1
  1439  			#define HAVE_GETPWNAM_R 1
  1440  			#define HAVE_GETPWNAM_R_5 1
  1441  			#define HAVE_GETPWUID_R 1
  1442  			#define HAVE_GETPWUID_R_5 1
  1443  			#define HAVE_GMTIME_R 1
  1444  			#define HAVE_HIDDEN 1
  1445  			#define HAVE_INTPTR_T 1
  1446  			#define HAVE_INTTYPES_H 1
  1447  			#define HAVE_LOCALTIME_R 1
  1448  			#define HAVE_MEMORY_H 1
  1449  			#define HAVE_MKSTEMP 1
  1450  			#define HAVE_MKSTEMPS 1
  1451  			#define HAVE_MKTIME 1
  1452  			#define HAVE_OPENDIR 1
  1453  			#define HAVE_SIGNED_CHAR 1
  1454  			#define HAVE_STDINT_H 1
  1455  			#define HAVE_STDLIB_H 1
  1456  			#define HAVE_STRINGS_H 1
  1457  			#define HAVE_STRING_H 1
  1458  			#define HAVE_STRTOL 1
  1459  			#define HAVE_STRUCT_ADDRINFO 1
  1460  			#define HAVE_STRUCT_IN6_ADDR 1
  1461  			#define HAVE_STRUCT_SOCKADDR_IN6 1
  1462  			#define HAVE_STRUCT_SOCKADDR_STORAGE 1
  1463  			#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
  1464  			#define HAVE_STRUCT_STAT_ST_BLOCKS 1
  1465  			#define HAVE_SYS_IOCTL_H 1
  1466  			#define HAVE_SYS_IOCTL_H 1
  1467  			#define HAVE_SYS_PARAM_H 1
  1468  			#define HAVE_SYS_STAT_H 1
  1469  			#define HAVE_SYS_TIME_H 1
  1470  			#define HAVE_SYS_TYPES_H 1
  1471  			#define HAVE_TERMIOS_H 1
  1472  			#define HAVE_TIMEZONE_VAR 1
  1473  			#define HAVE_TM_GMTOFF 1
  1474  			#define HAVE_UINTPTR_T 1
  1475  			#define HAVE_UNISTD_H 1
  1476  			#define HAVE_WAITPID 1
  1477  			#define MODULE_SCOPE extern
  1478  			#define MP_PREC 4
  1479  			#define PACKAGE_BUGREPORT ""
  1480  			#define PACKAGE_NAME "tcl"
  1481  			#define PACKAGE_STRING "tcl 8.6"
  1482  			#define PACKAGE_TARNAME "tcl"
  1483  			#define PACKAGE_VERSION "8.6"
  1484  			#define STDC_HEADERS 1
  1485  			#define TCL_CFGVAL_ENCODING "iso8859-1"
  1486  			#define TCL_CFG_OPTIMIZED 1
  1487  			#define TCL_COMPILE_DEBUG 1 //TODO-
  1488  			#define TCL_LIBRARY "/usr/local/lib/tcl8.6"
  1489  			#define TCL_PACKAGE_PATH "/usr/local/lib64 /usr/local/lib "
  1490  			#define TCL_SHLIB_EXT ".so"
  1491  			#define TCL_THREADS 1
  1492  			#define TCL_TOMMATH 1
  1493  			#define TCL_UNLOAD_DLLS 1
  1494  			#define TCL_WIDE_INT_TYPE long long //TODO ?386?
  1495  			#define TIME_WITH_SYS_TIME 1
  1496  			#define _REENTRANT 1
  1497  			#define _THREAD_SAFE 1
  1498  			// #define HAVE_CPUID 1
  1499  			// #define HAVE_GETHOSTBYADDR_R_8 1 // uses identifier h_errno -> UB
  1500  			// #define HAVE_GETHOSTBYNAME_R 1   // ../../_tcl8.6.8/unix/tclUnixCompat.c:580:20: undefined "compatLock"
  1501  			// #define HAVE_GETHOSTBYNAME_R_6 1  // uses identifier h_errno -> UB
  1502  			// #define HAVE_PTHREAD_ATFORK 1
  1503  			// #define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
  1504  			// #define HAVE_ZLIB 1
  1505  			// #define NDEBUG 1
  1506  			// #define USE_THREAD_ALLOC 1
  1507  
  1508  			/* Rename the global symbols in libtommath to avoid linkage conflicts */
  1509  
  1510  			#define KARATSUBA_MUL_CUTOFF TclBNKaratsubaMulCutoff
  1511  			#define KARATSUBA_SQR_CUTOFF TclBNKaratsubaSqrCutoff
  1512  			#define TOOM_MUL_CUTOFF TclBNToomMulCutoff
  1513  			#define TOOM_SQR_CUTOFF TclBNToomSqrCutoff
  1514  
  1515  			#define bn_reverse TclBN_reverse
  1516  			#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
  1517  			#define fast_s_mp_sqr TclBN_fast_s_mp_sqr
  1518  			#define mp_add TclBN_mp_add
  1519  			#define mp_add_d TclBN_mp_add_d
  1520  			#define mp_and TclBN_mp_and
  1521  			#define mp_clamp TclBN_mp_clamp
  1522  			#define mp_clear TclBN_mp_clear
  1523  			#define mp_clear_multi TclBN_mp_clear_multi
  1524  			#define mp_cmp TclBN_mp_cmp
  1525  			#define mp_cmp_d TclBN_mp_cmp_d
  1526  			#define mp_cmp_mag TclBN_mp_cmp_mag
  1527  			#define mp_cnt_lsb TclBN_mp_cnt_lsb
  1528  			#define mp_copy TclBN_mp_copy
  1529  			#define mp_count_bits TclBN_mp_count_bits
  1530  			#define mp_div TclBN_mp_div
  1531  			#define mp_div_2 TclBN_mp_div_2
  1532  			#define mp_div_2d TclBN_mp_div_2d
  1533  			#define mp_div_3 TclBN_mp_div_3
  1534  			#define mp_div_d TclBN_mp_div_d
  1535  			#define mp_exch TclBN_mp_exch
  1536  			#define mp_expt_d TclBN_mp_expt_d
  1537  			#define mp_grow TclBN_mp_grow
  1538  			#define mp_init TclBN_mp_init
  1539  			#define mp_init_copy TclBN_mp_init_copy
  1540  			#define mp_init_multi TclBN_mp_init_multi
  1541  			#define mp_init_set TclBN_mp_init_set
  1542  			#define mp_init_set_int TclBN_mp_init_set_int
  1543  			#define mp_init_size TclBN_mp_init_size
  1544  			#define mp_karatsuba_mul TclBN_mp_karatsuba_mul
  1545  			#define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
  1546  			#define mp_lshd TclBN_mp_lshd
  1547  			#define mp_mod TclBN_mp_mod
  1548  			#define mp_mod_2d TclBN_mp_mod_2d
  1549  			#define mp_mul TclBN_mp_mul
  1550  			#define mp_mul_2 TclBN_mp_mul_2
  1551  			#define mp_mul_2d TclBN_mp_mul_2d
  1552  			#define mp_mul_d TclBN_mp_mul_d
  1553  			#define mp_neg TclBN_mp_neg
  1554  			#define mp_or TclBN_mp_or
  1555  			#define mp_radix_size TclBN_mp_radix_size
  1556  			#define mp_read_radix TclBN_mp_read_radix
  1557  			#define mp_rshd TclBN_mp_rshd
  1558  			#define mp_s_rmap TclBNMpSRmap
  1559  			#define mp_set TclBN_mp_set
  1560  			#define mp_set_int TclBN_mp_set_int
  1561  			#define mp_shrink TclBN_mp_shrink
  1562  			#define mp_sqr TclBN_mp_sqr
  1563  			#define mp_sqrt TclBN_mp_sqrt
  1564  			#define mp_sub TclBN_mp_sub
  1565  			#define mp_sub_d TclBN_mp_sub_d
  1566  			#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
  1567  			#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
  1568  			#define mp_toom_mul TclBN_mp_toom_mul
  1569  			#define mp_toom_sqr TclBN_mp_toom_sqr
  1570  			#define mp_toradix_n TclBN_mp_toradix_n
  1571  			#define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size
  1572  			#define mp_xor TclBN_mp_xor
  1573  			#define mp_zero TclBN_mp_zero
  1574  			#define s_mp_add TclBN_s_mp_add
  1575  			#define s_mp_mul_digs TclBN_s_mp_mul_digs
  1576  			#define s_mp_sqr TclBN_s_mp_sqr
  1577  			#define s_mp_sub TclBN_s_mp_sub
  1578  `
  1579  		tclDefs32 = `
  1580  			#define mp_digit unsigned long
  1581  `
  1582  		tclDefs64 = "\n#define mp_digit unsigned long long\n"
  1583  	)
  1584  
  1585  	var tclDefs string
  1586  	switch arch := env("GOARCH", runtime.GOARCH); arch {
  1587  	case "386":
  1588  		tclDefs = allDefs + tclDefs0 + tclDefs32
  1589  	case "amd64":
  1590  		tclDefs = allDefs + tclDefs0 + tclDefs64
  1591  	default:
  1592  		panic(arch)
  1593  	}
  1594  
  1595  	dir := *oTmp
  1596  	if dir == "" {
  1597  		var err error
  1598  		if dir, err = ioutil.TempDir("", "test-ccgo-tcl-"); err != nil {
  1599  			t.Fatal(err)
  1600  		}
  1601  
  1602  		defer func() {
  1603  			if err := os.RemoveAll(dir); err != nil {
  1604  				t.Fatal(err)
  1605  			}
  1606  		}()
  1607  	}
  1608  	testdir := filepath.Join(dir, "test")
  1609  	if err := mkdir(testdir); err != nil {
  1610  		t.Fatal(err)
  1611  	}
  1612  
  1613  	g := newGen(nil, nil)
  1614  	g.escAllTLDs = true
  1615  	root := "testdata"
  1616  
  1617  	sqliteTweaks := &cc.Tweaks{
  1618  		// TrackExpand:                 func(s string) { fmt.Print(s) }, //TODO-
  1619  		// TrackIncludes:               func(s string) { fmt.Printf("#include %s\n", s) }, //TODO-
  1620  		EnableAnonymousStructFields: true,
  1621  		EnableEmptyStructs:          true,
  1622  		InjectFinalNL:               true,
  1623  	}
  1624  	inc := append([]string{
  1625  		"@",
  1626  		filepath.FromSlash(filepath.Join(root, sqlite, "sqlite-amalgamation-3210000")),
  1627  		filepath.FromSlash(filepath.Join(root, tcl, "generic")),
  1628  	}, searchPaths...)
  1629  	sysInc := append(searchPaths, filepath.FromSlash(filepath.Join(root, sqlite, "sqlite-amalgamation-3210000")))
  1630  
  1631  	for _, v := range []string{
  1632  		"sqlite-amalgamation-3210000/sqlite3.c", // Keep this first
  1633  
  1634  		"ext/rbu/test_rbu.c",
  1635  		"ext/fts5/fts5_tcl.c",
  1636  		"ext/misc/amatch.c",
  1637  		"ext/misc/carray.c",
  1638  		"ext/misc/closure.c",
  1639  		"ext/misc/csv.c",
  1640  		"ext/misc/eval.c",
  1641  		"ext/misc/fileio.c",
  1642  		"ext/misc/fuzzer.c",
  1643  		"ext/misc/ieee754.c",
  1644  		"ext/misc/mmapwarm.c",
  1645  		"ext/misc/nextchar.c",
  1646  		"ext/misc/percentile.c",
  1647  		"ext/misc/regexp.c",
  1648  		"ext/misc/remember.c",
  1649  		"ext/misc/series.c",
  1650  		"ext/misc/spellfix.c",
  1651  		"ext/misc/totype.c",
  1652  		"ext/misc/unionvtab.c",
  1653  		"ext/misc/wholenumber.c",
  1654  	} {
  1655  		in := []cc.Source{cc.MustFileSource2(filepath.FromSlash(filepath.Join(root, sqlite, v)), false)}
  1656  		tu, err := translate(sqliteTweaks, inc, sysInc, sqliteDefs+tclDefs, in...)
  1657  		if err != nil {
  1658  			t.Fatal(err)
  1659  		}
  1660  
  1661  		if err := g.file(testdir, v, tu); err != nil {
  1662  			t.Fatal(err)
  1663  		}
  1664  	}
  1665  
  1666  	tclTweaks := &cc.Tweaks{
  1667  		// TrackExpand:                 func(s string) { fmt.Print(s) },                   //TODO-
  1668  		// TrackIncludes:               func(s string) { fmt.Printf("#include %s\n", s) }, //TODO-
  1669  		EnableAnonymousStructFields: true,
  1670  		EnableEmptyStructs:          true,
  1671  		EnableImplicitBuiltins:      true,
  1672  		InjectFinalNL:               true,
  1673  	}
  1674  	inc = []string{
  1675  		"@",
  1676  		filepath.FromSlash(filepath.Join(root, tcl, "unix")), //TODO Windows
  1677  		filepath.FromSlash(filepath.Join(root, tcl, "generic")),
  1678  		filepath.FromSlash(filepath.Join(root, tcl, "libtommath")),
  1679  	}
  1680  	sysInc = append(searchPaths, inc...)
  1681  	for _, v := range []string{
  1682  		"generic/regcomp.c",
  1683  		"generic/regerror.c",
  1684  		"generic/regexec.c",
  1685  		"generic/regfree.c",
  1686  		"generic/tclAlloc.c",
  1687  		"generic/tclAssembly.c",
  1688  		"generic/tclAsync.c",
  1689  		"generic/tclBasic.c",
  1690  		"generic/tclBinary.c",
  1691  		"generic/tclCkalloc.c",
  1692  		"generic/tclClock.c",
  1693  		"generic/tclCmdAH.c",
  1694  		"generic/tclCmdIL.c",
  1695  		"generic/tclCmdMZ.c",
  1696  		"generic/tclCompCmds.c",
  1697  		"generic/tclCompCmdsGR.c",
  1698  		"generic/tclCompCmdsSZ.c",
  1699  		"generic/tclCompExpr.c",
  1700  		"generic/tclCompile.c",
  1701  		"generic/tclConfig.c",
  1702  		"generic/tclDate.c",
  1703  		"generic/tclDictObj.c",
  1704  		"generic/tclDisassemble.c",
  1705  		"generic/tclEncoding.c",
  1706  		"generic/tclEnsemble.c",
  1707  		"generic/tclEnv.c",
  1708  		"generic/tclEvent.c",
  1709  		"generic/tclExecute.c",
  1710  		"generic/tclFCmd.c",
  1711  		"generic/tclFileName.c",
  1712  		"generic/tclGet.c",
  1713  		"generic/tclHash.c",
  1714  		"generic/tclHistory.c",
  1715  		"generic/tclIO.c",
  1716  		"generic/tclIOCmd.c",
  1717  		"generic/tclIORChan.c",
  1718  		"generic/tclIORTrans.c",
  1719  		"generic/tclIOSock.c",
  1720  		"generic/tclIOUtil.c",
  1721  		"generic/tclIndexObj.c",
  1722  		"generic/tclInterp.c",
  1723  		"generic/tclLink.c",
  1724  		"generic/tclListObj.c",
  1725  		"generic/tclLiteral.c",
  1726  		"generic/tclLoad.c",
  1727  		"generic/tclLoadNone.c", // TclGuessPackageName
  1728  		"generic/tclMain.c",
  1729  		"generic/tclNamesp.c",
  1730  		"generic/tclNotify.c",
  1731  		"generic/tclOO.c",
  1732  		"generic/tclOOBasic.c",
  1733  		"generic/tclOOCall.c",
  1734  		"generic/tclOODefineCmds.c",
  1735  		"generic/tclOOInfo.c",
  1736  		"generic/tclOOMethod.c",
  1737  		"generic/tclObj.c",
  1738  		"generic/tclOptimize.c",
  1739  		"generic/tclPanic.c",
  1740  		"generic/tclParse.c",
  1741  		"generic/tclPathObj.c",
  1742  		"generic/tclPipe.c",
  1743  		"generic/tclPkg.c",
  1744  		"generic/tclPkgConfig.c",
  1745  		"generic/tclPosixStr.c",
  1746  		"generic/tclPreserve.c",
  1747  		"generic/tclProc.c",
  1748  		"generic/tclRegexp.c",
  1749  		"generic/tclResolve.c",
  1750  		"generic/tclResult.c",
  1751  		"generic/tclScan.c",
  1752  		"generic/tclStrToD.c",
  1753  		"generic/tclStringObj.c",
  1754  		"generic/tclThread.c",
  1755  		"generic/tclThreadStorage.c",
  1756  		"generic/tclTimer.c",
  1757  		"generic/tclTomMathInterface.c",
  1758  		"generic/tclTrace.c",
  1759  		"generic/tclUtf.c",
  1760  		"generic/tclUtil.c",
  1761  		"generic/tclVar.c",
  1762  		"unix/tclUnixChan.c",
  1763  		"unix/tclUnixCompat.c",
  1764  		"unix/tclUnixEvent.c",
  1765  		"unix/tclUnixFCmd.c",
  1766  		"unix/tclUnixFile.c",
  1767  		"unix/tclUnixInit.c",
  1768  		"unix/tclUnixNotfy.c",
  1769  		"unix/tclUnixPipe.c",
  1770  		"unix/tclUnixSock.c",
  1771  		"unix/tclUnixThrd.c",
  1772  		"unix/tclUnixTime.c",
  1773  	} {
  1774  		tu, err := translate(tclTweaks, inc, sysInc, tclDefs, cc.MustFileSource2(filepath.FromSlash(filepath.Join(root, tcl, v)), false))
  1775  		if err != nil {
  1776  			t.Fatal(err)
  1777  		}
  1778  
  1779  		if err := g.file(testdir, v, tu); err != nil {
  1780  			t.Fatal(err)
  1781  		}
  1782  	}
  1783  
  1784  	m, err := filepath.Glob(filepath.FromSlash(filepath.Join(root, tcl, "libtommath/*.c")))
  1785  	if err != nil {
  1786  		t.Fatal(err)
  1787  	}
  1788  
  1789  	for _, v := range m {
  1790  		tu, err := translate(tclTweaks, inc, sysInc, tclDefs, cc.MustFileSource2(v, false))
  1791  		if err != nil {
  1792  			t.Fatal(err)
  1793  		}
  1794  
  1795  		if err := g.file(testdir, v, tu); err != nil {
  1796  			t.Fatal(err)
  1797  		}
  1798  	}
  1799  
  1800  	inc = append([]string{
  1801  		"@",
  1802  		filepath.FromSlash(filepath.Join(root, sqlite, "sqlite-amalgamation-3210000")),
  1803  		filepath.FromSlash(filepath.Join(root, tcl, "generic")),
  1804  	}, searchPaths...)
  1805  
  1806  	if m, err = filepath.Glob(filepath.FromSlash(filepath.Join(root, sqlite, "src/test*.c"))); err != nil {
  1807  		t.Fatal(err)
  1808  	}
  1809  
  1810  	for _, v := range m {
  1811  		tu, err := translate(sqliteTweaks, inc, sysInc, allDefs+sqliteDefs, cc.MustFileSource2(v, false))
  1812  		if err != nil {
  1813  			t.Fatal(err)
  1814  		}
  1815  
  1816  		if err := g.file(testdir, v, tu); err != nil {
  1817  			t.Fatal(err)
  1818  		}
  1819  	}
  1820  
  1821  	inc = append([]string{
  1822  		"@",
  1823  		filepath.FromSlash(filepath.Join(root, sqlite, "sqlite-amalgamation-3210000")),
  1824  		filepath.FromSlash(filepath.Join(root, tcl, "generic")),
  1825  	}, searchPaths...)
  1826  
  1827  	// file with main must be last
  1828  	v := "src/tclsqlite.c"
  1829  	in := []cc.Source{cc.MustFileSource2(filepath.FromSlash(filepath.Join(root, sqlite, v)), false), cc.MustCrt0()}
  1830  	tu, err := translate(sqliteTweaks, inc, searchPaths, allDefs+sqliteDefs, in...)
  1831  	if err != nil {
  1832  		t.Fatal(err)
  1833  	}
  1834  
  1835  	if err := g.file(testdir, v, tu); err != nil {
  1836  		t.Fatal(err)
  1837  	}
  1838  
  1839  	cwd, err := os.Getwd()
  1840  	if err != nil {
  1841  		t.Fatal(err)
  1842  	}
  1843  
  1844  	defer func() {
  1845  		if err := os.Chdir(cwd); err != nil {
  1846  			t.Error(err)
  1847  		}
  1848  	}()
  1849  
  1850  	src, err := filepath.Abs(filepath.Join(cwd, "testdata"))
  1851  	if err != nil {
  1852  		t.Fatal(err)
  1853  	}
  1854  
  1855  	if err := os.Chdir(testdir); err != nil {
  1856  		t.Fatal(err)
  1857  	}
  1858  
  1859  	cc.FlushCache()
  1860  	build := "build -o test"
  1861  	if *oTCLRace {
  1862  		build += " -race"
  1863  	}
  1864  	out, err := exec.Command("go", strings.Split(build, " ")...).CombinedOutput()
  1865  	if err != nil {
  1866  		t.Fatalf("%v\n%s", err, out)
  1867  	}
  1868  
  1869  	if *oEdit {
  1870  		fmt.Printf("TCL0\ttclsqlite build ok\n")
  1871  	}
  1872  
  1873  	if err := cpDir(filepath.Join(dir, "ext"), filepath.Join(src, filepath.FromSlash("_sqlite/ext")), nil); err != nil {
  1874  		t.Fatal(err)
  1875  	}
  1876  
  1877  	if err := cpDir(filepath.Join(dir, "library"), filepath.Join(src, filepath.FromSlash("_tcl8.6.8/library")), nil); err != nil {
  1878  		t.Fatal(err)
  1879  	}
  1880  
  1881  	if err := cpDir(filepath.Join(dir, "test"), filepath.Join(src, filepath.FromSlash("_sqlite/test")), nil); err != nil {
  1882  		t.Fatal(err)
  1883  	}
  1884  
  1885  	blacklist := []string{
  1886  		"btreefault.test",
  1887  		"cffault.test",
  1888  		"collate1.test",
  1889  		"collate2.test",
  1890  		"collate3.test",
  1891  		"collate4.test",
  1892  		"collate5.test",
  1893  		"collate6.test",
  1894  		"collate9.test",
  1895  		"corruptC.test",
  1896  		"crash.test",
  1897  		"crash2.test",
  1898  		"crash3.test",
  1899  		"crash4.test",
  1900  		"crash6.test",
  1901  		"crash7.test",
  1902  		"date.test", // crt.Xselect
  1903  		"e_createtable.test",
  1904  		"e_delete.test",
  1905  		"e_insert.test",
  1906  		"e_reindex.test",
  1907  		"e_select.test",
  1908  		"e_update.test",
  1909  		"e_walauto.test",
  1910  		"exists.test",
  1911  		"func4.test",
  1912  		"fuzz.test",
  1913  		"fuzzerfault.test",
  1914  		"ieee754.test",
  1915  		"incrcorrupt.test", // crt.Xftruncate
  1916  		"incrvacuum_ioerr.test",
  1917  		"ioerr3.test",
  1918  		"journal3.test", // crt.Xfchmod
  1919  		"lock.test",
  1920  		"lock4.test", // crt.Xselect
  1921  		"lock5.test", // crt.Xutimes
  1922  		"malloc.test",
  1923  		"minmax.test",
  1924  		"misc1.test",
  1925  		"misc3.test",
  1926  		"misc7.test",    // crt.Xatof
  1927  		"mjournal.test", // crt.Xfopen
  1928  		"mmap1.test",
  1929  		"mmap4.test",
  1930  		"multiplex2.test",
  1931  		"nan.test",
  1932  		"pager1.test",
  1933  		"pager4.test", // crt.Xrename
  1934  		"pagerfault.test",
  1935  		"pagerfault2.test",
  1936  		"pagerfault3.test",
  1937  		"pragma.test", // crt.X__assert_fail
  1938  		"printf.test",
  1939  		"quota2.test", // crt.Xfopen
  1940  		"rbu.test",    // crt.Xrename
  1941  		"reindex.test",
  1942  		"rollbackfault.test",
  1943  		"rowallock.test",
  1944  		"savepoint.test",
  1945  		"savepoint4.test",
  1946  		"savepointfault.test",
  1947  		"schema3.test",
  1948  		"select9.test",
  1949  		"shared2.test",
  1950  		"shared9.test",
  1951  		"sharedA.test", // crt.Xpthread_attr_init
  1952  		"sort2.test",
  1953  		"sort3.test",
  1954  		"sort4.test", // crt.Xpthread_create
  1955  		"sortfault.test",
  1956  		"speed4.test",
  1957  		"speed4p.test",
  1958  		"statfault.test",
  1959  		"superlock.test",
  1960  		"symlink.test", // crt.Xsymlink
  1961  		"syscall.test",
  1962  		"tempfault.test",
  1963  		"thread001.test", // crt.Xpthread_attr_init
  1964  		"thread002.test", // crt.Xpthread_attr_init
  1965  		"thread003.test", // crt.Xpthread_attr_init
  1966  		"thread004.test", // crt.Xpthread_attr_init
  1967  		"thread005.test", // crt.Xpthread_attr_init
  1968  		"thread1.test",   // crt.Xpthread_create
  1969  		"thread2.test",   // crt.Xpthread_create
  1970  		"tkt-5d863f876e.test",
  1971  		"tkt-fc62af4523.test",
  1972  		"tkt3838.test",
  1973  		"tkt3997.test",
  1974  		"trans.test",
  1975  		"unionvtabfault.test",
  1976  		"unixexcl.test",
  1977  		"vacuum2.test",
  1978  		"vtabH.test", // crt.Xreaddir64_r
  1979  		"wal.test",
  1980  		"wal2.test",
  1981  		"wal3.test",
  1982  		"wal4.test",
  1983  		"wal5.test",
  1984  		"walcrash.test",
  1985  		"walcrash2.test",
  1986  		"walcrash4.test",
  1987  		"walro.test",
  1988  		"walslow.test",
  1989  		"walthread.test", // crt.Xpthread_attr_init
  1990  		"where.test",
  1991  		"whereD.test",
  1992  		"writecrash.test",
  1993  	}
  1994  
  1995  	for _, v := range blacklist {
  1996  		if err := os.Remove(filepath.Join(testdir, v)); err != nil {
  1997  			t.Fatal(err)
  1998  		}
  1999  	}
  2000  
  2001  	cmd := exec.Command("./test", "all.test")
  2002  	pipe, err := cmd.StdoutPipe()
  2003  	if err != nil {
  2004  		t.Fatal(err)
  2005  	}
  2006  
  2007  	if err := cmd.Start(); err != nil {
  2008  		t.Fatal(err)
  2009  	}
  2010  
  2011  	const maxFails = 10
  2012  	var green, red int
  2013  	var fail []string
  2014  	sc := bufio.NewScanner(pipe)
  2015  	var lastStdout, lastOk, lastFinished string
  2016  	for sc.Scan() {
  2017  		lastStdout = sc.Text()
  2018  		if *oTrace {
  2019  			fmt.Fprintln(os.Stderr, lastStdout)
  2020  		}
  2021  		switch {
  2022  		case strings.HasPrefix(lastStdout, "!") && strings.Contains(lastStdout, "expected"):
  2023  			if len(fail) < maxFails {
  2024  				fail = append(fail, lastStdout)
  2025  			}
  2026  		case
  2027  			strings.HasPrefix(lastStdout, "Error:"),
  2028  			strings.HasPrefix(lastStdout, "!") && strings.Contains(lastStdout, "got"):
  2029  
  2030  			red++
  2031  			if len(fail) < maxFails {
  2032  				fail = append(fail, lastStdout)
  2033  			}
  2034  		case strings.HasPrefix(lastStdout, "Time: "):
  2035  			lastFinished = lastStdout
  2036  		case strings.HasSuffix(lastStdout, "... Ok") && !strings.Contains(lastStdout, "-closeallfiles") && !strings.Contains(lastStdout, "-sharedcachesetting"):
  2037  			green++
  2038  			lastOk = lastStdout
  2039  		}
  2040  	}
  2041  	total := green + red
  2042  	if red > len(fail) {
  2043  		fail = append(fail, "... too many fails")
  2044  	}
  2045  	t.Logf(`
  2046  Test cases: %8d
  2047  Pass:       %8d (%3.2f%%)
  2048  Fail:       %8d (%3.2f%%)
  2049  %s`,
  2050  		total, green, 100*float64(green)/float64(total), red, 100*float64(red)/float64(total), strings.Join(fail, "\n"),
  2051  	)
  2052  	if err := cmd.Wait(); err != nil || len(blacklist) != 0 {
  2053  		t.Fatalf(`
  2054  Test binary exit error: %v
  2055  Last completed test file: %q
  2056  Last passed test: %q
  2057  Last line written to stdout: %q
  2058  Blacklisted test files: %d
  2059  %s`, err, lastFinished, lastOk, lastStdout, len(blacklist), strings.Join(blacklist, "\n"))
  2060  	}
  2061  }
  2062  
  2063  func (g *gen) define2(n *cc.Declarator) {
  2064  more:
  2065  	n = g.normalizeDeclarator(n)
  2066  	nm := n.Name()
  2067  	done := false
  2068  	if n.Linkage == cc.LinkageExternal {
  2069  		_, produced := g.producedExterns[nm]
  2070  		_, initialized := g.initializedExterns[nm]
  2071  		hasInitializer := n.Initializer != nil
  2072  		switch {
  2073  		case !produced && !initialized && !hasInitializer:
  2074  			switch x := underlyingType(n.Type, true).(type) {
  2075  			case *cc.ArrayType:
  2076  				if x.Size.Value == nil {
  2077  					g.incompleteExternArrays[nm] = n
  2078  					done = true // Must resolve later
  2079  				}
  2080  			}
  2081  		case !produced && !initialized && hasInitializer:
  2082  
  2083  			// nop here
  2084  		case
  2085  			produced && !initialized && !hasInitializer,
  2086  			produced && initialized && hasInitializer,
  2087  			produced && initialized && !hasInitializer:
  2088  
  2089  			done = true
  2090  		case produced && !initialized && hasInitializer:
  2091  			g.escapedTLD2(n)
  2092  			done = true
  2093  		default:
  2094  			panic(fmt.Errorf("%v: %q produced %v, initialized %v, hasInitializer %v", g.position(n), dict.S(nm), produced, initialized, hasInitializer))
  2095  		}
  2096  	}
  2097  
  2098  	if !done {
  2099  		_, done = g.producedDeclarators[n]
  2100  	}
  2101  	if !done {
  2102  		if n.Linkage == cc.LinkageExternal {
  2103  			_, done = g.producedExterns[nm]
  2104  			//dbg("%v: %q, %v", g.position(n), dict.S(nm), done)
  2105  		}
  2106  
  2107  		if n.Type.Kind() == cc.Function && n.FunctionDefinition == nil {
  2108  			done = true
  2109  		}
  2110  		if !done {
  2111  			switch underlyingType(n.Type, true).(type) {
  2112  			case
  2113  				*cc.ArrayType,
  2114  				*cc.EnumType,
  2115  				*cc.FunctionType,
  2116  				*cc.PointerType,
  2117  				*cc.StructType,
  2118  				*cc.UnionType,
  2119  				cc.TypeKind:
  2120  
  2121  				if n.Linkage == cc.LinkageExternal {
  2122  					g.producedExterns[nm] = struct{}{}
  2123  				}
  2124  				g.producedDeclarators[n] = struct{}{}
  2125  				g.tld(n)
  2126  			default:
  2127  				//dbg("%v: %q %v (%v)", g.position(n), dict.S(nm), n.Type, underlyingType(n.Type, true))
  2128  				todo("")
  2129  			}
  2130  		}
  2131  	}
  2132  
  2133  	for g.queue.Front() != nil {
  2134  		m := g.queue.Front()
  2135  		g.queue.Remove(m)
  2136  		switch x := m.Value.(type) {
  2137  		case *cc.Declarator:
  2138  			n = x
  2139  			goto more
  2140  		case *cc.EnumType:
  2141  			g.defineEnumType(x)
  2142  		case *cc.FunctionType:
  2143  			// nop
  2144  		case *cc.NamedType:
  2145  			g.enqueue(x.Type)
  2146  		case *cc.PointerType:
  2147  			if !x.IsVoidPointerType() {
  2148  				g.enqueue(x.Item)
  2149  			}
  2150  		case *cc.StructType:
  2151  			// nop
  2152  		case *cc.TaggedEnumType:
  2153  			g.defineTaggedEnumType(x)
  2154  		case *cc.TaggedStructType:
  2155  			switch {
  2156  			case x.Type == nil || x.Type == x:
  2157  				g.opaqueStructTags[x.Tag] = struct{}{}
  2158  			default:
  2159  				g.defineTaggedStructType(x)
  2160  			}
  2161  		case *cc.TaggedUnionType:
  2162  			switch {
  2163  			case x.Type == nil || x.Type == x:
  2164  				g.opaqueStructTags[x.Tag] = struct{}{}
  2165  			default:
  2166  				g.defineTaggedUnionType(x)
  2167  			}
  2168  		case cc.TypeKind:
  2169  			// nop
  2170  		case *cc.UnionType:
  2171  			// nop
  2172  		default:
  2173  			todo("%T %v", x, x)
  2174  		}
  2175  	}
  2176  }
  2177  
  2178  // produced && !initialized && hasInitializer
  2179  func (g *gen) escapedTLD2(n *cc.Declarator) {
  2180  	switch x := n.Type.(type) {
  2181  	case
  2182  		*cc.NamedType,
  2183  		*cc.TaggedStructType,
  2184  		*cc.TaggedUnionType:
  2185  
  2186  		g.enqueue(x)
  2187  	}
  2188  
  2189  	nm := n.Name()
  2190  
  2191  	defer func() { g.initializedExterns[nm] = struct{}{} }()
  2192  
  2193  	if g.isConstInitializer(n.Type, n.Initializer) {
  2194  		g.w("\n\nfunc init() {")
  2195  		g.w("%sCopy(%s, ds+%d, %d)", crt, g.mangleDeclarator(n), g.allocDS(n.Type, n.Initializer), g.model.Sizeof(n.Type))
  2196  		g.w("}")
  2197  		return
  2198  	}
  2199  
  2200  	switch x := cc.UnderlyingType(n.Type).(type) {
  2201  	case *cc.ArrayType:
  2202  		if x.Item.Kind() == cc.Char && n.Initializer.Expr.Operand.Value != nil {
  2203  			todo("%v:", g.position(n))
  2204  			g.w("\nvar %s = ds + %d\n", g.mangleDeclarator(n), g.allocDS(n.Type, n.Initializer))
  2205  			return
  2206  		}
  2207  	}
  2208  
  2209  	g.w("\n\nfunc init() {")
  2210  	g.w("*(*%s)(unsafe.Pointer(%s)) = ", g.typ(n.Type), g.mangleDeclarator(n))
  2211  	g.literal(n.Type, n.Initializer)
  2212  	g.w("}")
  2213  }
  2214  
  2215  func (g *gen) file(dir, fn0 string, tu *cc.TranslationUnit) error {
  2216  	g.enqueued = map[interface{}]struct{}{}
  2217  	g.externs = map[int]*cc.Declarator{}
  2218  	g.producedDeclarators = map[*cc.Declarator]struct{}{}
  2219  	g.staticDeclarators = map[int]*cc.Declarator{}
  2220  	fn, err := g.file0(dir, fn0, tu)
  2221  	if err != nil {
  2222  		return err
  2223  	}
  2224  
  2225  	f, err := os.Create(fn)
  2226  	if err != nil {
  2227  		return err
  2228  	}
  2229  
  2230  	defer func() {
  2231  		if e := f.Close(); e != nil && err == nil {
  2232  			err = e
  2233  		}
  2234  	}()
  2235  
  2236  	w := bufio.NewWriter(f)
  2237  
  2238  	defer func() {
  2239  		if e := w.Flush(); e != nil && err == nil {
  2240  			err = e
  2241  		}
  2242  	}()
  2243  
  2244  	o := newOpt()
  2245  	o.noBool2int = true
  2246  	s := ""
  2247  	os := ""
  2248  	_, crt0 := tu.FileScope.Idents[idStart]
  2249  	if crt0 {
  2250  		o.forceBool2int = true
  2251  		if err := g.crt0(); err != nil {
  2252  			return err
  2253  		}
  2254  		s = `const null = uintptr(0)
  2255  `
  2256  		os = "\n\t\"os\""
  2257  	}
  2258  
  2259  	w.WriteString(fmt.Sprintf(`package main
  2260  
  2261  import (
  2262  	"math"
  2263  	"unsafe"%s
  2264  
  2265  	"github.com/cznic/crt"
  2266  )
  2267  
  2268  var (
  2269  	_ = crt.Malloc
  2270  	_ = math.Pi
  2271  	_ unsafe.Pointer
  2272  )
  2273  
  2274  `, os))
  2275  	w.WriteString(s)
  2276  	if crt0 {
  2277  		g.w(mainSrc, crt)
  2278  	}
  2279  	return o.do(w, &g.out0, fn, 0)
  2280  }
  2281  
  2282  func (g *gen) crt0() error {
  2283  	if err := g.errs.Err(); err != nil {
  2284  		return fmt.Errorf("%s", errString(err))
  2285  	}
  2286  
  2287  	if g.needNZ64 {
  2288  		g.w("\n\nfunc init() { nz64 = -nz64 }")
  2289  	}
  2290  	if g.needNZ32 {
  2291  		g.w("\n\nfunc init() { nz32 = -nz32 }")
  2292  	}
  2293  
  2294  	var a []string
  2295  	for k := range g.opaqueStructTags {
  2296  		a = append(a, string(dict.S(k)))
  2297  	}
  2298  	sort.Strings(a)
  2299  	for _, k := range a {
  2300  		tag := dict.SID(k)
  2301  		if _, ok := g.producedStructTags[tag]; !ok {
  2302  			g.w("\ntype S%s struct{ uintptr }\n", k)
  2303  		}
  2304  	}
  2305  
  2306  	if g.needPreInc {
  2307  		g.w("\n\nfunc preinc(p *uintptr, n uintptr) uintptr { *p += n; return *p }")
  2308  	}
  2309  	if g.needAlloca {
  2310  		g.w("\n\nfunc alloca(p *[]uintptr, n int) uintptr { r := %sMustMalloc(n); *p = append(*p, r); return r }", crt)
  2311  	}
  2312  
  2313  	g.genHelpers()
  2314  
  2315  	g.w("\n\nvar (\n")
  2316  	if g.bss != 0 {
  2317  		g.w("bss = %sBSS(&bssInit[0])\n", crt)
  2318  		g.w("bssInit [%d]byte\n", g.bss)
  2319  	}
  2320  	if n := len(g.ds); n != 0 {
  2321  		if n < 16 {
  2322  			g.ds = append(g.ds, make([]byte, 16-n)...)
  2323  		}
  2324  		g.w("ds = %sDS(dsInit)\n", crt)
  2325  		g.w("dsInit = []byte{")
  2326  		if isTesting {
  2327  			g.w("\n")
  2328  		}
  2329  		for i, v := range g.ds {
  2330  			g.w("%#02x, ", v)
  2331  			if isTesting && i&15 == 15 {
  2332  				g.w("// %#x\n", i&^15)
  2333  			}
  2334  		}
  2335  		g.w("}\n")
  2336  	}
  2337  	if g.needNZ64 {
  2338  		g.w("nz64 float64\n")
  2339  	}
  2340  	if g.needNZ32 {
  2341  		g.w("nz32 float32\n")
  2342  	}
  2343  	g.w("ts = %sTS(\"", crt)
  2344  	for _, v := range g.text {
  2345  		s := fmt.Sprintf("%q", dict.S(v))
  2346  		g.w("%s\\x00", s[1:len(s)-1])
  2347  	}
  2348  	g.w("\")\n)\n")
  2349  	return nil
  2350  }
  2351  
  2352  func (g *gen) file0(dir, fn string, tu *cc.TranslationUnit) (f string, err error) {
  2353  	returned := false
  2354  
  2355  	defer func() {
  2356  		if e := recover(); !returned && err == nil {
  2357  			err = fmt.Errorf("PANIC: %v\n%s", e, compact(string(debugStack()), compactStack))
  2358  		}
  2359  	}()
  2360  
  2361  	bn := filepath.Base(fn)
  2362  	bn = bn[:len(bn)-len(filepath.Ext(bn))]
  2363  	s := ""
  2364  	i := -1
  2365  	for {
  2366  		fn0 := filepath.Join(dir, bn+s+".go")
  2367  		if _, ok := g.filenames[fn0]; !ok {
  2368  			f = fn0
  2369  			break
  2370  		}
  2371  		i++
  2372  		s = fmt.Sprintf("_%d", i)
  2373  	}
  2374  	g.in = []*cc.TranslationUnit{tu}
  2375  	g.out0 = bytes.Buffer{}
  2376  	switch {
  2377  	case g.model == nil:
  2378  		g.model = tu.Model
  2379  		g.fset = tu.FileSet
  2380  	default:
  2381  		if !g.model.Equal(tu.Model) {
  2382  			return "", fmt.Errorf("translation units use different memory models")
  2383  		}
  2384  	}
  2385  
  2386  	var a []string
  2387  	for nm := range tu.FileScope.Idents {
  2388  		a = append(a, string(dict.S(nm)))
  2389  	}
  2390  	sort.Strings(a)
  2391  	var a2 []int
  2392  next:
  2393  	for _, s := range a {
  2394  		nm := dict.SID(s)
  2395  		n := tu.FileScope.Idents[nm]
  2396  		switch x := n.(type) {
  2397  		case *cc.Declarator:
  2398  			switch x.Linkage {
  2399  			case cc.LinkageExternal:
  2400  				p := g.position(x).Filename
  2401  				for _, v := range searchPaths {
  2402  					if strings.HasPrefix(p, v) {
  2403  						switch nm := x.Name(); nm {
  2404  						case idStdin, idStdout, idStderr:
  2405  						default:
  2406  							g.producedExterns[nm] = struct{}{}
  2407  							continue next
  2408  						}
  2409  					}
  2410  				}
  2411  
  2412  				if x.Type.Kind() == cc.Function && x.Name() == idBacktrace {
  2413  					continue
  2414  				}
  2415  
  2416  				g.externs[nm] = x
  2417  				a2 = append(a2, nm)
  2418  			case cc.LinkageInternal:
  2419  				g.staticDeclarators[nm] = x
  2420  			}
  2421  		case *cc.EnumerationConstant:
  2422  			// nop
  2423  		default:
  2424  			todo("%v: %T %s", g.position0(n), x, nm)
  2425  		}
  2426  	}
  2427  	for _, nm := range a2 {
  2428  		g.define2(g.externs[nm])
  2429  	}
  2430  	returned = true
  2431  	return f, nil
  2432  }
  2433  
  2434  func TestCSmith0(t *testing.T) { //TODO-
  2435  	cc.FlushCache()
  2436  	csmith, err := exec.LookPath("csmith")
  2437  	if err != nil {
  2438  		t.Logf("%v: skipping test", err)
  2439  		return
  2440  	}
  2441  
  2442  	gcc, err := exec.LookPath("gcc")
  2443  	if err != nil {
  2444  		t.Logf("%v: skipping test", err)
  2445  		return
  2446  	}
  2447  
  2448  	var inc string
  2449  	switch runtime.GOOS {
  2450  	case "linux":
  2451  		inc = "/usr/include"
  2452  	default:
  2453  		t.Logf("unsupported OS")
  2454  		return
  2455  	}
  2456  	if _, err := os.Stat(filepath.Join(inc, "csmith.h")); err != nil {
  2457  		if os.IsNotExist(err) {
  2458  			t.Logf("%s not found: skipping test", inc)
  2459  			return
  2460  		}
  2461  
  2462  		t.Fatal(err)
  2463  	}
  2464  
  2465  	dir, err := ioutil.TempDir("", "test-ccgo-csmith-")
  2466  	if err != nil {
  2467  		t.Fatal(err)
  2468  	}
  2469  
  2470  	defer func() {
  2471  		if err := os.RemoveAll(dir); err != nil {
  2472  			t.Fatal(err)
  2473  		}
  2474  	}()
  2475  
  2476  	cwd, err := os.Getwd()
  2477  	if err != nil {
  2478  		t.Fatal(err)
  2479  	}
  2480  
  2481  	if err := os.Chdir(dir); err != nil {
  2482  		t.Fatal(err)
  2483  	}
  2484  
  2485  	defer func() {
  2486  		if err := os.Chdir(cwd); err != nil {
  2487  			t.Fatal(err)
  2488  		}
  2489  	}()
  2490  
  2491  	const (
  2492  		gccBin = "gcc"
  2493  		mainC  = "main.c"
  2494  	)
  2495  
  2496  	ch := time.After(*oCSmith)
  2497  	var cs, cc, ccgo, build, run, ok int
  2498  	t0 := time.Now()
  2499  out:
  2500  	for {
  2501  		select {
  2502  		case <-ch:
  2503  			break out
  2504  		default:
  2505  		}
  2506  
  2507  		out, err := exec.Command(
  2508  			csmith,
  2509  			"-o", mainC,
  2510  			"--bitfields",            // --bitfields | --no-bitfields: enable | disable full-bitfields structs (disabled by default).
  2511  			"--no-const-pointers",    // --const-pointers | --no-const-pointers: enable | disable const pointers (enabled by default).
  2512  			"--no-consts",            // --consts | --no-consts: enable | disable const qualifier (enabled by default).
  2513  			"--no-packed-struct",     // --packed-struct | --no-packed-struct: enable | disable packed structs by adding #pragma pack(1) before struct definition (disabled by default).
  2514  			"--no-volatile-pointers", // --volatile-pointers | --no-volatile-pointers: enable | disable volatile pointers (enabled by default).
  2515  			"--no-volatiles",         // --volatiles | --no-volatiles: enable | disable volatiles (enabled by default).
  2516  			"--paranoid",             // --paranoid | --no-paranoid: enable | disable pointer-related assertions (disabled by default).
  2517  		).Output()
  2518  		if err != nil {
  2519  			t.Fatalf("%v\n%s", err, out)
  2520  		}
  2521  
  2522  		if out, err := exec.Command(gcc, "-w", "-o", gccBin, mainC).CombinedOutput(); err != nil {
  2523  			t.Fatalf("%v\n%s", err, out)
  2524  		}
  2525  
  2526  		var gccOut []byte
  2527  		var gccT0 time.Time
  2528  		var gccT time.Duration
  2529  		func() {
  2530  			ctx, cancel := context.WithTimeout(context.Background(), testTimeout/10)
  2531  
  2532  			defer cancel()
  2533  
  2534  			gccT0 = time.Now()
  2535  			gccOut, err = exec.CommandContext(ctx, filepath.Join(dir, gccBin)).CombinedOutput()
  2536  			gccT = time.Since(gccT0)
  2537  		}()
  2538  		if err != nil {
  2539  			continue
  2540  		}
  2541  
  2542  		cs++
  2543  		build0 := build
  2544  		os.Remove("main.go")
  2545  		ccgoOut, err := test(t, false, &cc, &ccgo, &build, &run, "", "", []string{inc}, dir, []string{mainC})
  2546  		if err != nil {
  2547  			t.Log(err)
  2548  			csmithFatal(t, mainC, gccOut, ccgoOut, cc, ccgo, build, run, ok, cs, gccT)
  2549  		}
  2550  
  2551  		if build == build0 {
  2552  			continue
  2553  		}
  2554  
  2555  		if bytes.Equal(gccOut, ccgoOut) {
  2556  			ok++
  2557  			if *oEdit {
  2558  				fmt.Printf("cc %v ccgo %v build %v run %v ok %v (%.2f%%) csmith %v (%v)\n", cc, ccgo, build, run, ok, 100*float64(ok)/float64(cs), cs, time.Since(t0))
  2559  			}
  2560  			continue
  2561  		}
  2562  
  2563  		if *oNoCmp {
  2564  			continue
  2565  		}
  2566  
  2567  		csmithFatal(t, mainC, gccOut, ccgoOut, cc, ccgo, build, run, ok, cs, gccT)
  2568  	}
  2569  	d := time.Since(t0)
  2570  	t.Logf("cc %v ccgo %v build %v run %v ok %v (%.2f%%) csmith %v (%v)", cc, ccgo, build, run, ok, 100*float64(ok)/float64(cs), cs, d)
  2571  	if *oEdit {
  2572  		fmt.Printf("CSmith0\tcc %v ccgo %v build %v run %v ok %v (%.2f%%) csmith %v (%v)\n", cc, ccgo, build, run, ok, 100*float64(ok)/float64(cs), cs, d)
  2573  	}
  2574  }
  2575  
  2576  func csmithFatal(t *testing.T, mainC string, gccOut, ccgoOut []byte, cc, ccgo, build, run, ok, cs int, gccT time.Duration) {
  2577  	b, err := ioutil.ReadFile(mainC)
  2578  	if err != nil {
  2579  		t.Fatal(err)
  2580  	}
  2581  
  2582  	b2, err := ioutil.ReadFile("main.go")
  2583  	if err != nil {
  2584  		b2 = nil
  2585  	}
  2586  
  2587  	t.Fatalf(`
  2588  ==== CSmith code ==============================================================
  2589  %s
  2590  ==== Go code (if any ) ========================================================
  2591  %s
  2592  ===============================================================================
  2593   GCC   time: %v
  2594   GCC output: %s
  2595  CCGO output: %s
  2596  cc %v ccgo %v build %v run %v ok %v (%.2f%%) csmith %v (%v)
  2597  `,
  2598  		b, b2, gccT, bytes.TrimSpace(gccOut), bytes.TrimSpace(ccgoOut),
  2599  		cc, ccgo, build, run, ok, 100*float64(ok)/float64(cs), cs, *oCSmith)
  2600  }