github.com/aleksi/cc@v0.0.0-20171021204506-4b6ffb9b7827/all_test.go (about)

     1  // Copyright 2016 The CC 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  package cc
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"flag"
    11  	"fmt"
    12  	"go/scanner"
    13  	"go/token"
    14  	"io"
    15  	"io/ioutil"
    16  	"log"
    17  	"os"
    18  	"os/exec"
    19  	"path"
    20  	"path/filepath"
    21  	"regexp"
    22  	"runtime"
    23  	"runtime/debug"
    24  	"sort"
    25  	"strconv"
    26  	"strings"
    27  	"testing"
    28  	"unicode"
    29  
    30  	"github.com/cznic/golex/lex"
    31  	"github.com/cznic/mathutil"
    32  	"github.com/cznic/xc"
    33  )
    34  
    35  func printStack() { debug.PrintStack() }
    36  
    37  func caller(s string, va ...interface{}) {
    38  	if s == "" {
    39  		s = strings.Repeat("%v ", len(va))
    40  	}
    41  	_, fn, fl, _ := runtime.Caller(2)
    42  	fmt.Fprintf(os.Stderr, "caller: %s:%d: ", path.Base(fn), fl)
    43  	fmt.Fprintf(os.Stderr, s, va...)
    44  	fmt.Fprintln(os.Stderr)
    45  	_, fn, fl, _ = runtime.Caller(1)
    46  	fmt.Fprintf(os.Stderr, "\tcallee: %s:%d: ", path.Base(fn), fl)
    47  	fmt.Fprintln(os.Stderr)
    48  	os.Stderr.Sync()
    49  }
    50  
    51  func dbg(s string, va ...interface{}) {
    52  	if s == "" {
    53  		s = strings.Repeat("%v ", len(va))
    54  	}
    55  	_, fn, fl, _ := runtime.Caller(1)
    56  	fmt.Fprintf(os.Stderr, "dbg %s:%d: ", path.Base(fn), fl)
    57  	fmt.Fprintf(os.Stderr, s, va...)
    58  	fmt.Fprintln(os.Stderr)
    59  	os.Stderr.Sync()
    60  }
    61  
    62  func TODO(...interface{}) string {
    63  	_, fn, fl, _ := runtime.Caller(1)
    64  	return fmt.Sprintf("TODO: %s:%d:\n", path.Base(fn), fl)
    65  }
    66  
    67  func use(...interface{}) int { return 42 }
    68  
    69  var _ = use(printStack, caller, dbg, TODO, (*ctype).str, yyDefault, yyErrCode, yyMaxDepth)
    70  
    71  // ============================================================================
    72  
    73  var (
    74  	o1        = flag.String("1", "", "single file argument of TestPPParse1.")
    75  	oDev      = flag.Bool("dev", false, "enable WIP tests")
    76  	oFailFast = flag.Bool("ff", false, "crash on first reported error (in some tests.)")
    77  	oRe       = flag.String("re", "", "regexp filter.")
    78  	oTmp      = flag.Bool("tmp", false, "keep certain temp files.")
    79  	oTrace    = flag.Bool("trc", false, "print testDev path")
    80  
    81  	includes = []string{}
    82  
    83  	predefinedMacros = `
    84  #define __STDC_HOSTED__ 1
    85  #define __STDC_VERSION__ 199901L
    86  #define __STDC__ 1
    87  
    88  #define __MODEL64
    89  
    90  void __GO__(char *s, ...);
    91  `
    92  	sysIncludes = []string{}
    93  
    94  	testTweaks = &tweaks{
    95  		enableDefineOmitCommaBeforeDDD: true,
    96  		enableDlrInIdentifiers:         true,
    97  		enableEmptyDefine:              true,
    98  		enableUndefExtraTokens:         true,
    99  	}
   100  )
   101  
   102  func newTestReport() *xc.Report {
   103  	r := xc.NewReport()
   104  	r.ErrLimit = -1
   105  	if *oFailFast {
   106  		r.PanicOnError = true
   107  	}
   108  	return r
   109  }
   110  
   111  func init() {
   112  	isTesting = true
   113  	log.SetFlags(log.Llongfile)
   114  	flag.BoolVar(&debugIncludes, "dbgi", false, "debug include searches")
   115  	flag.BoolVar(&debugMacros, "dbgm", false, "debug macros")
   116  	flag.BoolVar(&debugTypeStrings, "xtypes", false, "add debug info to type strings")
   117  	flag.BoolVar(&isGenerating, "generating", false, "go generate is executing (false).")
   118  	flag.IntVar(&yyDebug, "yydebug", 0, "")
   119  }
   120  
   121  func newTestModel() *Model {
   122  	return &Model{ // 64
   123  		Items: map[Kind]ModelItem{
   124  			Ptr:               {8, 8, 8, nil},
   125  			UintPtr:           {8, 8, 8, nil},
   126  			Void:              {0, 1, 1, nil},
   127  			Char:              {1, 1, 1, nil},
   128  			SChar:             {1, 1, 1, nil},
   129  			UChar:             {1, 1, 1, nil},
   130  			Short:             {2, 2, 2, nil},
   131  			UShort:            {2, 2, 2, nil},
   132  			Int:               {4, 4, 4, nil},
   133  			UInt:              {4, 4, 4, nil},
   134  			Long:              {8, 8, 8, nil},
   135  			ULong:             {8, 8, 8, nil},
   136  			LongLong:          {8, 8, 8, nil},
   137  			ULongLong:         {8, 8, 8, nil},
   138  			Float:             {4, 4, 4, nil},
   139  			Double:            {8, 8, 8, nil},
   140  			LongDouble:        {16, 16, 16, nil},
   141  			Bool:              {1, 1, 1, nil},
   142  			FloatComplex:      {8, 8, 8, nil},
   143  			DoubleComplex:     {16, 16, 16, nil},
   144  			LongDoubleComplex: {16, 16, 16, nil},
   145  		},
   146  	}
   147  }
   148  
   149  func printError(w io.Writer, pref string, err error) {
   150  	switch x := err.(type) {
   151  	case scanner.ErrorList:
   152  		for i, v := range x {
   153  			fmt.Fprintf(w, "%s%v\n", pref, v)
   154  			if i == 50 {
   155  				fmt.Fprintln(w, "too many errors")
   156  				break
   157  			}
   158  		}
   159  	default:
   160  		fmt.Fprintf(w, "%s%v\n", pref, err)
   161  	}
   162  }
   163  
   164  func errString(err error) string {
   165  	var b bytes.Buffer
   166  	printError(&b, "", err)
   167  	return b.String()
   168  }
   169  
   170  func testUCNTable(t *testing.T, tab []rune, fOk, fOther func(rune) bool, fcategory func(rune) bool, tag string) {
   171  	m := map[rune]struct{}{}
   172  	for i := 0; i < len(tab); i += 2 {
   173  		l, h := tab[i], tab[i+1]
   174  		if h == 0 {
   175  			h = l
   176  		}
   177  		for r := rune(l); r <= rune(h); r++ {
   178  			m[r] = struct{}{}
   179  		}
   180  	}
   181  	for r := rune(0); r < 0xffff; r++ {
   182  		_, ok := m[r]
   183  		if g, e := fOk(r), ok; g != e {
   184  			t.Errorf("%#04x %v %v", r, g, e)
   185  		}
   186  
   187  		if ok {
   188  			if g, e := fOther(r), false; g != e {
   189  				t.Errorf("%#04x %v %v", r, g, e)
   190  			}
   191  		}
   192  	}
   193  }
   194  
   195  func TestUCNDigitsTable(t *testing.T) {
   196  	tab := []rune{
   197  		0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, 0x09E6, 0x09EF, 0x0A66, 0x0A6F,
   198  		0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF,
   199  		0x0D66, 0x0D6F, 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F33,
   200  	}
   201  	testUCNTable(t, tab, isUCNDigit, isUCNNonDigit, unicode.IsDigit, "unicode.IsDigit")
   202  }
   203  
   204  func TestUCNNonDigitsTable(t *testing.T) {
   205  	tab := []rune{
   206  		0x00AA, 0x0000, 0x00B5, 0x0000, 0x00B7, 0x0000, 0x00BA, 0x0000, 0x00C0, 0x00D6,
   207  		0x00D8, 0x00F6, 0x00F8, 0x01F5, 0x01FA, 0x0217, 0x0250, 0x02A8, 0x02B0, 0x02B8,
   208  		0x02BB, 0x0000, 0x02BD, 0x02C1, 0x02D0, 0x02D1, 0x02E0, 0x02E4, 0x037A, 0x0000,
   209  		0x0386, 0x0000, 0x0388, 0x038A, 0x038C, 0x0000, 0x038E, 0x03A1, 0x03A3, 0x03CE,
   210  		0x03D0, 0x03D6, 0x03DA, 0x0000, 0x03DC, 0x0000, 0x03DE, 0x0000, 0x03E0, 0x0000,
   211  		0x03E2, 0x03F3, 0x0401, 0x040C, 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481,
   212  		0x0490, 0x04C4, 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5,
   213  		0x04F8, 0x04F9, 0x0531, 0x0556, 0x0559, 0x0000, 0x0561, 0x0587, 0x05B0, 0x05B9,
   214  		0x05F0, 0x05F2, 0x0621, 0x063A, 0x0640, 0x0652, 0x0670, 0x06B7, 0x06BA, 0x06BE,
   215  		0x06C0, 0x06CE, 0x06D0, 0x06DC, 0x06E5, 0x06E8, 0x06EA, 0x06ED, 0x0901, 0x0903,
   216  		0x0905, 0x0939, 0x093D, 0x0000, 0x093E, 0x094D, 0x0950, 0x0952, 0x0958, 0x0963,
   217  		0x0981, 0x0983, 0x0985, 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0,
   218  		0x09B2, 0x0000, 0x09B6, 0x09B9, 0x09BE, 0x09C4, 0x09C7, 0x09C8, 0x09CB, 0x09CD,
   219  		0x09DC, 0x09DD, 0x09DF, 0x09E3, 0x09F0, 0x09F1, 0x0A02, 0x0000, 0x0A05, 0x0A0A,
   220  		0x0A0F, 0x0A10, 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36,
   221  		0x0A38, 0x0A39, 0x0A3E, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4D, 0x0A59, 0x0A5C,
   222  		0x0A5E, 0x0000, 0x0A74, 0x0000, 0x0A81, 0x0A83, 0x0A85, 0x0A8B, 0x0A8D, 0x0000,
   223  		0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9,
   224  		0x0ABD, 0x0AC5, 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0AD0, 0x0000, 0x0AE0, 0x0000,
   225  		0x0B01, 0x0B03, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 0x0B2A, 0x0B30,
   226  		0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B3D, 0x0000, 0x0B3E, 0x0B43, 0x0B47, 0x0B48,
   227  		0x0B4B, 0x0B4D, 0x0B5C, 0x0B5D, 0x0B5F, 0x0B61, 0x0B82, 0x0B83, 0x0B85, 0x0B8A,
   228  		0x0B8E, 0x0B90, 0x0B92, 0x0B95, 0x0B99, 0x0B9A, 0x0B9C, 0x0000, 0x0B9E, 0x0B9F,
   229  		0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA, 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0BBE, 0x0BC2,
   230  		0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10,
   231  		0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C3E, 0x0C44, 0x0C46, 0x0C48,
   232  		0x0C4A, 0x0C4D, 0x0C60, 0x0C61, 0x0C82, 0x0C83, 0x0C85, 0x0C8C, 0x0C8E, 0x0C90,
   233  		0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, 0x0CB5, 0x0CB9, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8,
   234  		0x0CCA, 0x0CCD, 0x0CDE, 0x0000, 0x0CE0, 0x0CE1, 0x0D02, 0x0D03, 0x0D05, 0x0D0C,
   235  		0x0D0E, 0x0D10, 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D3E, 0x0D43, 0x0D46, 0x0D48,
   236  		0x0D4A, 0x0D4D, 0x0D60, 0x0D61, 0x0E01, 0x0E3A,
   237  
   238  		// In [0], Annex D, Thai [0x0E40, 0x0E5B] overlaps with digits
   239  		// [0x0E50, 0x0E59]. Exclude them.
   240  		0x0E40, 0x0E4F,
   241  		0x0E5A, 0x0E5B,
   242  
   243  		0x0E81, 0x0E82,
   244  		0x0E84, 0x0000, 0x0E87, 0x0E88, 0x0E8A, 0x0000, 0x0E8D, 0x0000, 0x0E94, 0x0E97,
   245  		0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EA5, 0x0000, 0x0EA7, 0x0000, 0x0EAA, 0x0EAB,
   246  		0x0EAD, 0x0EAE, 0x0EB0, 0x0EB9, 0x0EBB, 0x0EBD, 0x0EC0, 0x0EC4, 0x0EC6, 0x0000,
   247  		0x0EC8, 0x0ECD, 0x0EDC, 0x0EDD, 0x0F00, 0x0000, 0x0F18, 0x0F19, 0x0F35, 0x0000,
   248  		0x0F37, 0x0000, 0x0F39, 0x0000, 0x0F3E, 0x0F47, 0x0F49, 0x0F69, 0x0F71, 0x0F84,
   249  		0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F97, 0x0000, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7,
   250  		0x0FB9, 0x0000, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9,
   251  		0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 0x1F50, 0x1F57,
   252  		0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4,
   253  		0x1FB6, 0x1FBC, 0x1FBE, 0x0000, 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3,
   254  		0x1FD6, 0x1FDB, 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x203F, 0x2040,
   255  		0x207F, 0x0000, 0x2102, 0x0000, 0x2107, 0x0000, 0x210A, 0x2113, 0x2115, 0x0000,
   256  		0x2118, 0x211D, 0x2124, 0x0000, 0x2126, 0x0000, 0x2128, 0x0000, 0x212A, 0x2131,
   257  		0x2133, 0x2138, 0x2160, 0x2182, 0x3005, 0x3007, 0x3021, 0x3029, 0x3041, 0x3093,
   258  		0x309B, 0x309C, 0x30A1, 0x30F6, 0x30FB, 0x30FC, 0x3105, 0x312C, 0x4E00, 0x9FA5,
   259  		0xAC00, 0xD7A3,
   260  	}
   261  	testUCNTable(t, tab, isUCNNonDigit, isUCNDigit, unicode.IsLetter, "unicode.IsLetter")
   262  }
   263  
   264  func charStr(c rune) string {
   265  	return yySymName(int(c))
   266  }
   267  
   268  func charsStr(chars []lex.Char, delta token.Pos) (a []string) {
   269  	for _, v := range chars {
   270  		a = append(a, fmt.Sprintf("{%s %d}", charStr(v.Rune), v.Pos()-delta))
   271  	}
   272  	return a
   273  }
   274  
   275  type x []struct {
   276  	c   rune
   277  	pos token.Pos
   278  }
   279  
   280  type lexerTests []struct {
   281  	src   string
   282  	chars x
   283  }
   284  
   285  func testLexer(t *testing.T, newLexer func(i int, src string, report *xc.Report) (*lexer, error), tab lexerTests) {
   286  nextTest:
   287  	for ti, test := range tab {
   288  		//dbg("==== %v", ti)
   289  		report := xc.NewReport()
   290  		lx, err := newLexer(ti, test.src, report)
   291  		if err != nil {
   292  			t.Fatal(err)
   293  		}
   294  
   295  		delta := token.Pos(lx.file.Base() - 1)
   296  		var chars []lex.Char
   297  		var c lex.Char
   298  		for i := 0; c.Rune != ccEOF && i < len(test.src)+2; i++ {
   299  			c = lx.scanChar()
   300  			chars = append(chars, c)
   301  		}
   302  		if c.Rune != ccEOF {
   303  			t.Errorf("%d: scanner stall %v", ti, charsStr(chars, delta))
   304  			continue
   305  		}
   306  
   307  		if g, e := report.Errors(true), error(nil); g != e {
   308  			t.Errorf("%d: lx.err %v %v %v", ti, g, e, charsStr(chars, delta))
   309  			continue
   310  		}
   311  
   312  		if g, e := len(chars), len(test.chars); g != e {
   313  			t.Errorf("%d: len(chars) %v %v %v", ti, g, e, charsStr(chars, delta))
   314  			continue
   315  		}
   316  
   317  		for i, c := range chars {
   318  			c = chars[i]
   319  			e := test.chars[i]
   320  			g := c.Rune
   321  			if c.Rune == ccEOF {
   322  				g = -1
   323  			}
   324  			if e := e.c; g != e {
   325  				t.Errorf("%d: c[%d] %v %v %v", ti, i, charStr(g), charStr(e), charsStr(chars, delta))
   326  				continue nextTest
   327  			}
   328  
   329  			if g, e := c.Pos()-delta, e.pos; g != e {
   330  				t.Errorf("%d: pos[%d] %v %v %v", ti, i, g, e, charsStr(chars, delta))
   331  				continue nextTest
   332  			}
   333  		}
   334  	}
   335  }
   336  
   337  func TestLexer(t *testing.T) {
   338  	testLexer(
   339  		t,
   340  		func(i int, src string, report *xc.Report) (*lexer, error) {
   341  			return newLexer(fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src), report, testTweaks)
   342  		},
   343  		lexerTests{
   344  			{"", x{{-1, 1}}},
   345  			{"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}},
   346  			{"%:%:", x{{PPPASTE, 1}, {-1, 5}}},
   347  			{"%>", x{{'}', 1}, {-1, 3}}},
   348  			{"0", x{{INTCONST, 1}, {-1, 2}}},
   349  			{"01", x{{INTCONST, 1}, {-1, 3}}},
   350  			{"0??/1\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}},
   351  			{"0??/1\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}},
   352  			{"0??/\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {-1, 6}}},
   353  			{"0??/\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   354  			{"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}},
   355  			{"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}},
   356  			{"0\\\n", x{{INTCONST, 1}, {-1, 4}}},
   357  			{"0\\\n2", x{{INTCONST, 1}, {-1, 5}}},
   358  			{"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}},
   359  			{"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}},
   360  			{":>", x{{']', 1}, {-1, 3}}},
   361  			{"<%", x{{'{', 1}, {-1, 3}}},
   362  			{"<:", x{{'[', 1}, {-1, 3}}},
   363  			{"??!", x{{'?', 1}, {'?', 2}, {'!', 3}, {-1, 4}}},
   364  			{"??!0", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 5}}},
   365  			{"??!01", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 6}}},
   366  			{"??!=", x{{'?', 1}, {'?', 2}, {NEQ, 3}, {-1, 5}}},
   367  			{"??'", x{{'?', 1}, {'?', 2}, {'\'', 3}, {-1, 4}}},
   368  			{"??(", x{{'?', 1}, {'?', 2}, {'(', 3}, {-1, 4}}},
   369  			{"??)", x{{'?', 1}, {'?', 2}, {')', 3}, {-1, 4}}},
   370  			{"??-", x{{'?', 1}, {'?', 2}, {'-', 3}, {-1, 4}}},
   371  			{"??/", x{{'?', 1}, {'?', 2}, {'/', 3}, {-1, 4}}},
   372  			{"??/1\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}},
   373  			{"??/1\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   374  			{"??/\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {-1, 5}}},
   375  			{"??/\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}},
   376  			{"??<", x{{'?', 1}, {'?', 2}, {'<', 3}, {-1, 4}}},
   377  			{"??=??=", x{{'?', 1}, {'?', 2}, {'=', 3}, {'?', 4}, {'?', 5}, {'=', 6}, {-1, 7}}},
   378  			{"??>", x{{'?', 1}, {'?', 2}, {'>', 3}, {-1, 4}}},
   379  			{"???!", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {-1, 5}}},
   380  			{"???!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {INTCONST, 5}, {-1, 6}}},
   381  			{"???/\n2", x{{'?', 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   382  			{"????!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}},
   383  			{"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}},
   384  			{"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'?', 5}, {'?', 6}, {'!', 7}, {INTCONST, 8}, {-1, 9}}},
   385  			{"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}},
   386  			{"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'?', 4}, {'?', 5}, {'!', 6}, {INTCONST, 7}, {-1, 8}}},
   387  			{"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}},
   388  			{"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}},
   389  			{"@", x{{'@', 1}, {-1, 2}}},
   390  			{"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}},
   391  			{"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}},
   392  			{"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}},
   393  			{"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}},
   394  			{"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}},
   395  			{"@??=", x{{'@', 1}, {'?', 2}, {'?', 3}, {'=', 4}, {-1, 5}}},
   396  			{"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}},
   397  			{"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}},
   398  			{"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}},
   399  			{"\\\n", x{{-1, 3}}},
   400  			{"\\\n2", x{{INTCONST, 3}, {-1, 4}}},
   401  			{"\\\r\n", x{{-1, 4}}},
   402  			{"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}},
   403  			{"\r", x{{-1, 2}}},
   404  			{"\r0", x{{INTCONST, 2}, {-1, 3}}},
   405  			{"\r01", x{{INTCONST, 2}, {-1, 4}}},
   406  			{"\x00", x{{0, 1}, {-1, 2}}},
   407  			{"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}},
   408  		},
   409  	)
   410  }
   411  
   412  func TestLexer2(t *testing.T) {
   413  	testLexer(
   414  		t,
   415  		func(i int, src string, report *xc.Report) (*lexer, error) {
   416  			tweaks := *testTweaks
   417  			tweaks.enableTrigraphs = true
   418  			return newLexer(fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src), report, &tweaks)
   419  		},
   420  		lexerTests{
   421  			{"", x{{-1, 1}}},
   422  			{"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}},
   423  			{"%:%:", x{{PPPASTE, 1}, {-1, 5}}},
   424  			{"%>", x{{'}', 1}, {-1, 3}}},
   425  			{"0", x{{INTCONST, 1}, {-1, 2}}},
   426  			{"01", x{{INTCONST, 1}, {-1, 3}}},
   427  			{"0??/1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}},
   428  			{"0??/1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}},
   429  			{"0??/\n", x{{INTCONST, 1}, {-1, 6}}},
   430  			{"0??/\n2", x{{INTCONST, 1}, {-1, 7}}},
   431  			{"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}},
   432  			{"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}},
   433  			{"0\\\n", x{{INTCONST, 1}, {-1, 4}}},
   434  			{"0\\\n2", x{{INTCONST, 1}, {-1, 5}}},
   435  			{"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}},
   436  			{"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}},
   437  			{":>", x{{']', 1}, {-1, 3}}},
   438  			{"<%", x{{'{', 1}, {-1, 3}}},
   439  			{"<:", x{{'[', 1}, {-1, 3}}},
   440  			{"??!", x{{'|', 1}, {-1, 4}}},
   441  			{"??!0", x{{'|', 1}, {INTCONST, 4}, {-1, 5}}},
   442  			{"??!01", x{{'|', 1}, {INTCONST, 4}, {-1, 6}}},
   443  			{"??!=", x{{ORASSIGN, 1}, {-1, 5}}},
   444  			{"??'", x{{'^', 1}, {-1, 4}}},
   445  			{"??(", x{{'[', 1}, {-1, 4}}},
   446  			{"??)", x{{']', 1}, {-1, 4}}},
   447  			{"??-", x{{'~', 1}, {-1, 4}}},
   448  			{"??/", x{{'\\', 1}, {-1, 4}}},
   449  			{"??/1\n", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}},
   450  			{"??/1\n2", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   451  			{"??/\n", x{{-1, 5}}},
   452  			{"??/\n2", x{{INTCONST, 5}, {-1, 6}}},
   453  			{"??<", x{{'{', 1}, {-1, 4}}},
   454  			{"??=??=", x{{PPPASTE, 1}, {-1, 7}}},
   455  			{"??>", x{{'}', 1}, {-1, 4}}},
   456  			{"???!", x{{'?', 1}, {'|', 2}, {-1, 5}}},
   457  			{"???!0", x{{'?', 1}, {'|', 2}, {INTCONST, 5}, {-1, 6}}},
   458  			{"???/\n2", x{{'?', 1}, {INTCONST, 6}, {-1, 7}}},
   459  			{"????!0", x{{'?', 1}, {'?', 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}},
   460  			{"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}},
   461  			{"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'|', 5}, {INTCONST, 8}, {-1, 9}}},
   462  			{"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}},
   463  			{"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'|', 4}, {INTCONST, 7}, {-1, 8}}},
   464  			{"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}},
   465  			{"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}},
   466  			{"@", x{{'@', 1}, {-1, 2}}},
   467  			{"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}},
   468  			{"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}},
   469  			{"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}},
   470  			{"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}},
   471  			{"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}},
   472  			{"@??=", x{{'@', 1}, {'#', 2}, {-1, 5}}},
   473  			{"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}},
   474  			{"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}},
   475  			{"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}},
   476  			{"\\\n", x{{-1, 3}}},
   477  			{"\\\n2", x{{INTCONST, 3}, {-1, 4}}},
   478  			{"\\\r\n", x{{-1, 4}}},
   479  			{"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}},
   480  			{"\r", x{{-1, 2}}},
   481  			{"\r0", x{{INTCONST, 2}, {-1, 3}}},
   482  			{"\r01", x{{INTCONST, 2}, {-1, 4}}},
   483  			{"\x00", x{{0, 1}, {-1, 2}}},
   484  			{"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}},
   485  		},
   486  	)
   487  }
   488  
   489  func testPreprocessor(t *testing.T, fname string) string {
   490  	var buf bytes.Buffer
   491  	_, err := Parse(
   492  		"",
   493  		[]string{fname},
   494  		newTestModel(),
   495  		preprocessOnly(),
   496  		Cpp(func(toks []xc.Token) {
   497  			//dbg("____ cpp toks\n%s", PrettyString(toks))
   498  			for _, v := range toks {
   499  				buf.WriteString(TokSrc(v))
   500  			}
   501  			buf.WriteByte('\n')
   502  		}),
   503  		EnableDefineOmitCommaBeforeDDD(),
   504  	)
   505  	if err != nil {
   506  		t.Fatal(errString(err))
   507  	}
   508  	return strings.TrimSpace(buf.String())
   509  }
   510  
   511  func TestStdExample6_10_3_3_4(t *testing.T) {
   512  	if g, e := testPreprocessor(t, "testdata/example-6.10.3.3-4.h"), `char p[] = "x ## y";`; g != e {
   513  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
   514  	}
   515  }
   516  
   517  func TestStdExample6_10_3_5_3(t *testing.T) {
   518  	if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-3.h"),
   519  		`f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
   520  f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) &
   521  f(2 * (0,1))^m(0,1);
   522  int i[] = { 1, 23, 4, 5,  };
   523  char c[2][6] = { "hello", "" };`; g != e {
   524  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
   525  	}
   526  }
   527  
   528  func TestStdExample6_10_3_5_4(t *testing.T) {
   529  	if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-4.h"),
   530  		`printf("x1= %d, x2= %s", x1, x2);
   531  fputs(
   532  "strncmp(\"abc\\0d\", \"abc\", '\\4') == 0: @\n", s);
   533  vers2.h included from testdata/example-6.10.3.5-4.h
   534  "hello";
   535  "hello, world"`; g != e {
   536  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
   537  	}
   538  }
   539  
   540  func TestStdExample6_10_3_5_5(t *testing.T) {
   541  	if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-5.h"),
   542  		`int j[] = { 123, 45, 67, 89,
   543  10, 11, 12,  };`; g != e {
   544  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
   545  	}
   546  }
   547  
   548  func TestStdExample6_10_3_5_6(t *testing.T) {
   549  	if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-6.h"),
   550  		`ok`; g != e {
   551  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
   552  	}
   553  }
   554  
   555  func TestStdExample6_10_3_5_7(t *testing.T) {
   556  	if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-7.h"),
   557  		`fprintf(stderr, "Flag");
   558  fprintf(stderr, "X = %d\n", x);
   559  puts("The first, second, and third items.");
   560  ((x>y)?puts("x>y"): printf("x is %d but y is %d", x, y));`; g != e {
   561  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
   562  	}
   563  }
   564  
   565  type cppCmpError struct {
   566  	error
   567  }
   568  
   569  func testDev1(ppPredefine, cppPredefine, parsePredefine string, cppOpts []string, wd, src string, ppOpts, parseOpts []Opt) error {
   570  	fp := filepath.Join(wd, src)
   571  	if re := *oRe; re != "" {
   572  		ok, err := regexp.MatchString(re, fp)
   573  		if err != nil {
   574  			return err
   575  		}
   576  
   577  		if !ok {
   578  			return nil
   579  		}
   580  	}
   581  
   582  	logf, err := os.Create("log-" + filepath.Base(src))
   583  	if err != nil {
   584  		return err
   585  	}
   586  
   587  	defer logf.Close()
   588  
   589  	logw := bufio.NewWriter(logf)
   590  
   591  	defer logw.Flush()
   592  
   593  	if *oTrace {
   594  		fmt.Println(fp)
   595  		fmt.Println(logf.Name())
   596  	}
   597  
   598  	var got, exp []xc.Token
   599  	var lpos token.Position
   600  
   601  	var tw tweaks
   602  	_, err = Parse(
   603  		ppPredefine,
   604  		[]string{src},
   605  		newTestModel(),
   606  		append(
   607  			ppOpts,
   608  			getTweaks(&tw),
   609  			preprocessOnly(),
   610  			Cpp(func(toks []xc.Token) {
   611  				if len(toks) != 0 {
   612  					p := toks[0].Position()
   613  					if p.Filename != lpos.Filename {
   614  						fmt.Fprintf(logw, "# %d %q\n", p.Line, p.Filename)
   615  					}
   616  					lpos = p
   617  				}
   618  				for _, v := range toks {
   619  					logw.WriteString(TokSrc(toC(v, &tw)))
   620  					if v.Rune != ' ' {
   621  						got = append(got, v)
   622  					}
   623  				}
   624  				logw.WriteByte('\n')
   625  			}),
   626  			disableWarnings(),
   627  			disablePredefinedLineMacro(),
   628  		)...,
   629  	)
   630  	if err != nil {
   631  		return err
   632  	}
   633  
   634  	out, err := exec.Command("cpp", append(cppOpts, src)...).CombinedOutput()
   635  	if err != nil {
   636  		return fmt.Errorf("%v: %v", src, err)
   637  	}
   638  
   639  	f, err := ioutil.TempFile("", "cc-test-")
   640  	if err != nil {
   641  		return err
   642  	}
   643  
   644  	if *oTrace {
   645  		fmt.Println(f.Name())
   646  	}
   647  	defer func() {
   648  		if !*oTmp {
   649  			os.Remove(f.Name())
   650  		}
   651  		f.Close()
   652  	}()
   653  
   654  	if _, err := f.Write(out); err != nil {
   655  		return err
   656  	}
   657  
   658  	if _, err := Parse(
   659  		cppPredefine,
   660  		[]string{f.Name()},
   661  		newTestModel(),
   662  		preprocessOnly(),
   663  		Cpp(func(toks []xc.Token) {
   664  			for _, tok := range toks {
   665  				if tok.Rune != ' ' {
   666  					exp = append(exp, tok)
   667  				}
   668  			}
   669  		}),
   670  		disableWarnings(),
   671  	); err != nil {
   672  		return err
   673  	}
   674  
   675  	for i, g := range got {
   676  		if i >= len(exp) {
   677  			break
   678  		}
   679  
   680  		g = toC(g, &tw)
   681  		e := toC(exp[i], &tw)
   682  		if g.Rune != e.Rune || g.Val != e.Val {
   683  
   684  			if g.Rune == STRINGLITERAL && e.Rune == STRINGLITERAL && bytes.Contains(g.S(), []byte(fakeTime)) {
   685  				continue
   686  			}
   687  
   688  			if g.Rune == IDENTIFIER && e.Rune == INTCONST && g.Val == idLine {
   689  				n, err := strconv.ParseUint(string(e.S()), 10, mathutil.IntBits-1)
   690  				if err != nil {
   691  					return err
   692  				}
   693  
   694  				d := g.Position().Line - int(n)
   695  				if d < 0 {
   696  					d = -d
   697  				}
   698  				if d <= 3 {
   699  					continue
   700  				}
   701  			}
   702  
   703  			return cppCmpError{fmt.Errorf("%d\ngot %s\nexp %s", i, PrettyString(g), PrettyString(e))}
   704  		}
   705  	}
   706  
   707  	if g, e := len(got), len(exp); g != e {
   708  		return cppCmpError{fmt.Errorf("%v: got %d tokens, expected %d tokens (∆ %d)", src, g, e, g-e)}
   709  	}
   710  
   711  	logf2, err := os.Create("log2-" + filepath.Base(src))
   712  	if err != nil {
   713  		return err
   714  	}
   715  
   716  	defer logf2.Close()
   717  
   718  	logw2 := bufio.NewWriter(logf2)
   719  
   720  	defer logw2.Flush()
   721  
   722  	if *oTrace {
   723  		fmt.Println(logf2.Name())
   724  	}
   725  
   726  	_, err = Parse(
   727  		parsePredefine,
   728  		[]string{src},
   729  		newTestModel(),
   730  		append(
   731  			parseOpts,
   732  			disableWarnings(),
   733  			Cpp(func(toks []xc.Token) {
   734  				if len(toks) != 0 {
   735  					p := toks[0].Position()
   736  					if p.Filename != lpos.Filename {
   737  						fmt.Fprintf(logw2, "# %d %q\n", p.Line, p.Filename)
   738  					}
   739  					lpos = p
   740  				}
   741  				for _, v := range toks {
   742  					logw2.WriteString(TokSrc(toC(v, &tw)))
   743  				}
   744  				logw2.WriteByte('\n')
   745  			}),
   746  		)...,
   747  	)
   748  	return err
   749  }
   750  
   751  func testDev(t *testing.T, ppPredefine, cppPredefine, parsePredefine string, cppOpts, src []string, wd string, ppOpts, parseOpts []Opt) {
   752  	if !dirExists(t, wd) {
   753  		t.Logf("skipping: %v", wd)
   754  		return
   755  	}
   756  
   757  	cwd, err := os.Getwd()
   758  	if err != nil {
   759  		t.Fatal(err)
   760  	}
   761  
   762  	if err := os.Chdir(wd); err != nil {
   763  		t.Fatal(err)
   764  	}
   765  
   766  	defer os.Chdir(cwd)
   767  
   768  	for _, src := range src {
   769  		fi, err := os.Stat(src)
   770  		if err != nil {
   771  			t.Error(err)
   772  			continue
   773  		}
   774  
   775  		if !fi.Mode().IsRegular() {
   776  			t.Errorf("not a regular file: %s", filepath.Join(wd, src))
   777  			continue
   778  		}
   779  
   780  		if err := testDev1(ppPredefine, cppPredefine, parsePredefine, cppOpts, wd, src, ppOpts, parseOpts); err != nil {
   781  			t.Error(errString(err))
   782  		}
   783  	}
   784  }
   785  
   786  func dirExists(t *testing.T, dir string) bool {
   787  	dir = filepath.FromSlash(dir)
   788  	fi, err := os.Stat(dir)
   789  	if err != nil {
   790  		if os.IsNotExist(err) {
   791  			return false
   792  		}
   793  
   794  		t.Fatal(err)
   795  	}
   796  
   797  	if !fi.IsDir() {
   798  		t.Fatal(dir, "is not a directory")
   799  	}
   800  
   801  	return true
   802  }
   803  
   804  func TestPreprocessor(t *testing.T) {
   805  	if err := testDev1("", "", "", nil, "", "testdata/arith-1.h", nil, nil); err != nil {
   806  		t.Fatal(err)
   807  	}
   808  }
   809  
   810  func TestDevSDL(t *testing.T) {
   811  	predefined, includePaths, sysIncludePaths, err := HostConfig()
   812  	if err != nil {
   813  		t.Logf("skipping: %v", err)
   814  		return
   815  	}
   816  
   817  	ppOpts := []Opt{
   818  		IncludePaths(includePaths),
   819  		SysIncludePaths(sysIncludePaths),
   820  		devTest(),
   821  		EnableIncludeNext(),
   822  	}
   823  	if *oFailFast {
   824  		ppOpts = append(ppOpts, CrashOnError())
   825  	}
   826  	parseOpts := []Opt{
   827  		IncludePaths(includePaths),
   828  		SysIncludePaths(sysIncludePaths),
   829  		devTest(),
   830  		gccEmu(),
   831  	}
   832  	if *oFailFast {
   833  		parseOpts = append(parseOpts, CrashOnError())
   834  	}
   835  
   836  	testDev(
   837  		t,
   838  		predefined,
   839  		predefined,
   840  		predefined+`
   841  #define __inline inline
   842  `,
   843  		nil,
   844  		[]string{
   845  			"SDL.h",
   846  		},
   847  		"testdata/dev/SDL-1.2.15/include/",
   848  		ppOpts,
   849  		parseOpts,
   850  	)
   851  }
   852  
   853  func TestDevSqlite(t *testing.T) {
   854  	predefined, includePaths, sysIncludePaths, err := HostConfig()
   855  	if err != nil {
   856  		t.Logf("skipping: %v", err)
   857  		return
   858  	}
   859  
   860  	ppOpts := []Opt{
   861  		IncludePaths(includePaths),
   862  		SysIncludePaths(sysIncludePaths),
   863  		devTest(),
   864  		EnableIncludeNext(),
   865  	}
   866  	if *oFailFast {
   867  		ppOpts = append(ppOpts, CrashOnError())
   868  	}
   869  	parseOpts := []Opt{
   870  		IncludePaths(includePaths),
   871  		SysIncludePaths(sysIncludePaths),
   872  		devTest(),
   873  		gccEmu(),
   874  	}
   875  	if *oFailFast {
   876  		parseOpts = append(parseOpts, CrashOnError())
   877  	}
   878  
   879  	testDev(
   880  		t,
   881  		predefined,
   882  		predefined,
   883  		predefined+`
   884  #define __const const
   885  #define __inline inline
   886  #define __restrict restrict
   887  `,
   888  		nil,
   889  		[]string{
   890  			"shell.c",
   891  			"sqlite3.c",
   892  			"sqlite3.h",
   893  			"sqlite3ext.h",
   894  		},
   895  		"testdata/dev/sqlite3",
   896  		ppOpts,
   897  		parseOpts,
   898  	)
   899  }
   900  
   901  func TestDevVim(t *testing.T) {
   902  	predefined, includePaths, sysIncludePaths, err := HostConfig()
   903  	if err != nil {
   904  		t.Logf("skipping: %v", err)
   905  		return
   906  	}
   907  
   908  	ppOpts := []Opt{
   909  		IncludePaths([]string{
   910  			".",
   911  			"proto",
   912  		}),
   913  		IncludePaths(includePaths),
   914  		SysIncludePaths(sysIncludePaths),
   915  		EnableIncludeNext(),
   916  		EnableDefineOmitCommaBeforeDDD(),
   917  		devTest(),
   918  	}
   919  	if *oFailFast {
   920  		ppOpts = append(ppOpts, CrashOnError())
   921  	}
   922  	parseOpts := []Opt{
   923  		IncludePaths([]string{
   924  			".",
   925  			"proto",
   926  		}),
   927  		IncludePaths(includePaths),
   928  		SysIncludePaths(sysIncludePaths),
   929  		devTest(),
   930  		gccEmu(),
   931  	}
   932  	if *oFailFast {
   933  		parseOpts = append(parseOpts, CrashOnError())
   934  	}
   935  
   936  	p := predefined + `
   937  #define _FORTIFY_SOURCE 1
   938  #define HAVE_CONFIG_H
   939  `
   940  	testDev(
   941  		t,
   942  		p,
   943  		p,
   944  		p+`
   945  #define __const const
   946  #define __inline inline
   947  #define __restrict restrict
   948  #define __typeof typeof
   949  `,
   950  		[]string{
   951  			"-I.",
   952  			"-Iproto",
   953  			"-DHAVE_CONFIG_H",
   954  			"-U_FORTIFY_SOURCE",
   955  			"-D_FORTIFY_SOURCE=1",
   956  		},
   957  		[]string{
   958  			"auto/pathdef.c",
   959  			"blowfish.c",
   960  			"buffer.c",
   961  			"channel.c",
   962  			"charset.c",
   963  			"crypt.c",
   964  			"crypt_zip.c",
   965  			"diff.c",
   966  			"digraph.c",
   967  			"edit.c",
   968  			"eval.c",
   969  			"ex_cmds.c",
   970  			"ex_cmds2.c",
   971  			"ex_docmd.c",
   972  			"ex_eval.c",
   973  			"ex_getln.c",
   974  			"fileio.c",
   975  			"fold.c",
   976  			"getchar.c",
   977  			"hardcopy.c",
   978  			"hashtab.c",
   979  			"if_cscope.c",
   980  			"if_xcmdsrv.c",
   981  			"json.c",
   982  			"main.c",
   983  			"mark.c",
   984  			"mbyte.c",
   985  			"memfile.c",
   986  			"memline.c",
   987  			"menu.c",
   988  			"message.c",
   989  			"misc1.c",
   990  			"misc2.c",
   991  			"move.c",
   992  			"netbeans.c",
   993  			"normal.c",
   994  			"ops.c",
   995  			"option.c",
   996  			"os_unix.c",
   997  			"popupmnu.c",
   998  			"quickfix.c",
   999  			"regexp.c",
  1000  			"screen.c",
  1001  			"search.c",
  1002  			"sha256.c",
  1003  			"spell.c",
  1004  			"syntax.c",
  1005  			"tag.c",
  1006  			"term.c",
  1007  			"ui.c",
  1008  			"undo.c",
  1009  			"version.c",
  1010  			"window.c",
  1011  		},
  1012  		"testdata/dev/vim/vim/src",
  1013  		ppOpts,
  1014  		parseOpts,
  1015  	)
  1016  }
  1017  
  1018  func TestDevBash(t *testing.T) {
  1019  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  1020  	if err != nil {
  1021  		t.Logf("skipping: %v", err)
  1022  		return
  1023  	}
  1024  
  1025  	ppOpts := []Opt{
  1026  		IncludePaths([]string{
  1027  			".",
  1028  			"include",
  1029  			"lib",
  1030  		}),
  1031  		IncludePaths(includePaths),
  1032  		SysIncludePaths(sysIncludePaths),
  1033  		EnableIncludeNext(),
  1034  		devTest(),
  1035  	}
  1036  	if *oFailFast {
  1037  		ppOpts = append(ppOpts, CrashOnError())
  1038  	}
  1039  	parseOpts := []Opt{
  1040  		IncludePaths([]string{
  1041  			".",
  1042  			"include",
  1043  			"lib",
  1044  		}),
  1045  		IncludePaths(includePaths),
  1046  		SysIncludePaths(sysIncludePaths),
  1047  		devTest(),
  1048  		gccEmu(),
  1049  	}
  1050  	if *oFailFast {
  1051  		parseOpts = append(parseOpts, CrashOnError())
  1052  	}
  1053  
  1054  	p := predefined + `
  1055  #define PROGRAM "bash"
  1056  #define CONF_HOSTTYPE "x86_64"
  1057  #define CONF_OSTYPE "linux-gnu"
  1058  #define CONF_MACHTYPE "x86_64-unknown-linux-gnu"
  1059  #defien CONF_VENDOR "unknown"
  1060  #define LOCALEDIR "/usr/local/share/locale"
  1061  #define PACKAGE "bash"
  1062  #define SHELL
  1063  #define HAVE_CONFIG_H
  1064  `
  1065  	testDev(
  1066  		t,
  1067  		p,
  1068  		p,
  1069  		p+`
  1070  #define __const const
  1071  #define __inline inline
  1072  #define __restrict __restrict__
  1073  #define __typeof typeof
  1074  		`,
  1075  		[]string{
  1076  			`-DPROGRAM="bash"`,
  1077  			`-DCONF_HOSTTYPE="x86_64"`,
  1078  			`-DCONF_OSTYPE="linux-gnu"`,
  1079  			`-DCONF_MACHTYPE="x86_64-unknown-linux-gnu"`,
  1080  			`-DCONF_VENDOR="unknown"`,
  1081  			`-DLOCALEDIR="/usr/local/share/locale"`,
  1082  			`-DPACKAGE="bash"`,
  1083  			"-DSHELL",
  1084  			"-DHAVE_CONFIG_H",
  1085  			"-I.",
  1086  			"-Iinclude",
  1087  			"-Ilib",
  1088  		},
  1089  		[]string{
  1090  			"alias.c",
  1091  			"array.c",
  1092  			"arrayfunc.c",
  1093  			"assoc.c",
  1094  			"bashhist.c",
  1095  			"bashline.c",
  1096  			"bracecomp.c",
  1097  			"braces.c",
  1098  			"copy_cmd.c",
  1099  			"dispose_cmd.c",
  1100  			"error.c",
  1101  			"eval.c",
  1102  			"expr.c",
  1103  			"findcmd.c",
  1104  			"flags.c",
  1105  			"general.c",
  1106  			"hashcmd.c",
  1107  			"hashlib.c",
  1108  			"input.c",
  1109  			"jobs.c",
  1110  			"list.c",
  1111  			"locale.c",
  1112  			"mailcheck.c",
  1113  			"make_cmd.c",
  1114  			"mksyntax.c",
  1115  			"pathexp.c",
  1116  			"pcomplete.c",
  1117  			"pcomplib.c",
  1118  			"print_cmd.c",
  1119  			"redir.c",
  1120  			"shell.c",
  1121  			"sig.c",
  1122  			"stringlib.c",
  1123  			"subst.c",
  1124  			"support/bashversion.c",
  1125  			"support/mksignames.c",
  1126  			"support/signames.c",
  1127  			"syntax.c",
  1128  			"test.c",
  1129  			"trap.c",
  1130  			"unwind_prot.c",
  1131  			"variables.c",
  1132  			"version.c",
  1133  			"version.c",
  1134  			"xmalloc.c",
  1135  			"y.tab.c",
  1136  			//"execute_cmd.c", // Composite type K&R fn def style vs prototype decl lefts an undefined param.
  1137  		},
  1138  		"testdata/dev/bash-4.3/",
  1139  		ppOpts,
  1140  		parseOpts,
  1141  	)
  1142  
  1143  	ppOpts = []Opt{
  1144  		IncludePaths([]string{
  1145  			".",
  1146  			"..",
  1147  			"../include",
  1148  			"../lib",
  1149  		}),
  1150  		IncludePaths(includePaths),
  1151  		SysIncludePaths(sysIncludePaths),
  1152  		EnableIncludeNext(),
  1153  		devTest(),
  1154  	}
  1155  	if *oFailFast {
  1156  		ppOpts = append(ppOpts, CrashOnError())
  1157  	}
  1158  	parseOpts = []Opt{
  1159  		IncludePaths([]string{
  1160  			".",
  1161  			"..",
  1162  			"../include",
  1163  			"../lib",
  1164  		}),
  1165  		IncludePaths(includePaths),
  1166  		SysIncludePaths(sysIncludePaths),
  1167  		devTest(),
  1168  		gccEmu(),
  1169  	}
  1170  	if *oFailFast {
  1171  		parseOpts = append(parseOpts, CrashOnError())
  1172  	}
  1173  
  1174  	p = predefined + `
  1175  #define HAVE_CONFIG_H
  1176  #define SHELL
  1177  `
  1178  	testDev(
  1179  		t,
  1180  		p,
  1181  		p,
  1182  		p+`
  1183  #define __const const
  1184  #define __restrict __restrict__
  1185  #define __inline inline
  1186  `,
  1187  		[]string{
  1188  			"-DSHELL",
  1189  			"-DHAVE_CONFIG_H",
  1190  			"-I.",
  1191  			"-I..",
  1192  			"-I../include",
  1193  			"-I../lib",
  1194  		},
  1195  		[]string{
  1196  			"builtins.c",
  1197  			"common.c",
  1198  			"evalfile.c",
  1199  			"evalstring.c",
  1200  			"mkbuiltins.c",
  1201  			"psize.c",
  1202  		},
  1203  		"testdata/dev/bash-4.3/builtins",
  1204  		ppOpts,
  1205  		parseOpts,
  1206  	)
  1207  
  1208  	ppOpts = []Opt{
  1209  		IncludePaths([]string{
  1210  			".",
  1211  			"../..",
  1212  			"../../include",
  1213  			"../../lib",
  1214  		}),
  1215  		IncludePaths(includePaths),
  1216  		SysIncludePaths(sysIncludePaths),
  1217  		EnableIncludeNext(),
  1218  		devTest(),
  1219  	}
  1220  	if *oFailFast {
  1221  		ppOpts = append(ppOpts, CrashOnError())
  1222  	}
  1223  	parseOpts = []Opt{
  1224  		IncludePaths([]string{
  1225  			".",
  1226  			"../..",
  1227  			"../../include",
  1228  			"../../lib",
  1229  		}),
  1230  		IncludePaths(includePaths),
  1231  		SysIncludePaths(sysIncludePaths),
  1232  		devTest(),
  1233  		gccEmu(),
  1234  	}
  1235  	if *oFailFast {
  1236  		parseOpts = append(parseOpts, CrashOnError())
  1237  	}
  1238  
  1239  	p = predefined + `
  1240  #define HAVE_CONFIG_H
  1241  #define SHELL
  1242  `
  1243  	testDev(
  1244  		t,
  1245  		p,
  1246  		p,
  1247  		p+`
  1248  #define __const const
  1249  #define __inline inline
  1250  #define __restrict __restrict__
  1251  `,
  1252  		[]string{
  1253  			"-DSHELL",
  1254  			"-DHAVE_CONFIG_H",
  1255  			"-I.",
  1256  			"-I../..",
  1257  			"-I../../include",
  1258  			"-I../../lib",
  1259  		},
  1260  		[]string{
  1261  			"glob.c",
  1262  			"gmisc.c",
  1263  			"smatch.c",
  1264  			"strmatch.c",
  1265  			"xmbsrtowcs.c",
  1266  		},
  1267  		"testdata/dev/bash-4.3/lib/glob",
  1268  		ppOpts,
  1269  		parseOpts,
  1270  	)
  1271  
  1272  	testDev(
  1273  		t,
  1274  		p,
  1275  		p,
  1276  		p+`
  1277  #define __const const
  1278  #define __inline inline
  1279  #define __restrict __restrict__
  1280  `,
  1281  		[]string{
  1282  			"-DSHELL",
  1283  			"-DHAVE_CONFIG_H",
  1284  			"-I.",
  1285  			"-I../..",
  1286  			"-I../../include",
  1287  			"-I../../lib",
  1288  		},
  1289  		[]string{
  1290  			"casemod.c",
  1291  			"clktck.c",
  1292  			"clock.c",
  1293  			"eaccess.c",
  1294  			"fmtullong.c",
  1295  			"fmtulong.c",
  1296  			"fmtumax.c",
  1297  			"fnxform.c",
  1298  			"fpurge.c",
  1299  			"getenv.c",
  1300  			"input_avail.c",
  1301  			"itos.c",
  1302  			"mailstat.c",
  1303  			"makepath.c",
  1304  			"mbscasecmp.c",
  1305  			"mbschr.c",
  1306  			"mbscmp.c",
  1307  			"netconn.c",
  1308  			"netopen.c",
  1309  			"oslib.c",
  1310  			"pathcanon.c",
  1311  			"pathphys.c",
  1312  			"setlinebuf.c",
  1313  			"shmatch.c",
  1314  			"shmbchar.c",
  1315  			"shquote.c",
  1316  			"shtty.c",
  1317  			"snprintf.c",
  1318  			"spell.c",
  1319  			"stringlist.c",
  1320  			"stringvec.c",
  1321  			"strnlen.c",
  1322  			"strtrans.c",
  1323  			"timeval.c",
  1324  			"tmpfile.c",
  1325  			"uconvert.c",
  1326  			"ufuncs.c",
  1327  			"unicode.c",
  1328  			"wcsdup.c",
  1329  			"wcsnwidth.c",
  1330  			"winsize.c",
  1331  			"zcatfd.c",
  1332  			"zgetline.c",
  1333  			"zmapfd.c",
  1334  			"zread.c",
  1335  			"zwrite.c",
  1336  		},
  1337  		"testdata/dev/bash-4.3/lib/sh",
  1338  		ppOpts,
  1339  		parseOpts,
  1340  	)
  1341  
  1342  	testDev(
  1343  		t,
  1344  		p,
  1345  		p,
  1346  		p+`
  1347  #define __const const
  1348  #define __inline inline
  1349  #define __restrict __restrict__
  1350  `,
  1351  		[]string{
  1352  			"-DSHELL",
  1353  			"-DHAVE_CONFIG_H",
  1354  			"-I.",
  1355  			"-I../..",
  1356  			"-I../../include",
  1357  			"-I../../lib",
  1358  		},
  1359  		[]string{
  1360  			"bind.c",
  1361  			"callback.c",
  1362  			"colors.c",
  1363  			"compat.c",
  1364  			"complete.c",
  1365  			"display.c",
  1366  			"funmap.c",
  1367  			"histexpand.c",
  1368  			"histfile.c",
  1369  			"history.c",
  1370  			"histsearch.c",
  1371  			"input.c",
  1372  			"isearch.c",
  1373  			"keymaps.c",
  1374  			"kill.c",
  1375  			"macro.c",
  1376  			"mbutil.c",
  1377  			"misc.c",
  1378  			"nls.c",
  1379  			"parens.c",
  1380  			"parse-colors.c",
  1381  			"readline.c",
  1382  			"rltty.c",
  1383  			"savestring.c",
  1384  			"search.c",
  1385  			"shell.c",
  1386  			"signals.c",
  1387  			"terminal.c",
  1388  			"text.c",
  1389  			"tilde.c",
  1390  			"undo.c",
  1391  			"util.c",
  1392  			"vi_mode.c",
  1393  			"xfree.c",
  1394  			"xmalloc.c",
  1395  		},
  1396  		"testdata/dev/bash-4.3/lib/readline",
  1397  		ppOpts,
  1398  		parseOpts,
  1399  	)
  1400  
  1401  	p = predefined + `
  1402  #define HAVE_CONFIG_H
  1403  #define SHELL
  1404  #define RCHECK
  1405  #define botch programming_error
  1406  `
  1407  	testDev(
  1408  		t,
  1409  		p,
  1410  		p,
  1411  		p+`
  1412  #define __const const
  1413  #define __inline inline
  1414  #define __restrict __restrict__
  1415  `,
  1416  		[]string{
  1417  			"-DSHELL",
  1418  			"-DHAVE_CONFIG_H",
  1419  			"-DRCHECK",
  1420  			"-Dbotch=programming_error",
  1421  			"-I.",
  1422  			"-I../..",
  1423  			"-I../../include",
  1424  			"-I../../lib",
  1425  		},
  1426  		[]string{
  1427  			"malloc.c",
  1428  			"trace.c",
  1429  			"stats.c",
  1430  			"table.c",
  1431  			"watch.c",
  1432  		},
  1433  		"testdata/dev/bash-4.3/lib/malloc",
  1434  		ppOpts,
  1435  		parseOpts,
  1436  	)
  1437  }
  1438  
  1439  func TestDevMake(t *testing.T) {
  1440  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  1441  	if err != nil {
  1442  		t.Logf("skipping: %v", err)
  1443  		return
  1444  	}
  1445  
  1446  	ppOpts := []Opt{
  1447  		IncludePaths([]string{
  1448  			".",
  1449  		}),
  1450  		IncludePaths(includePaths),
  1451  		SysIncludePaths(sysIncludePaths),
  1452  		EnableIncludeNext(),
  1453  		devTest(),
  1454  	}
  1455  	if *oFailFast {
  1456  		ppOpts = append(ppOpts, CrashOnError())
  1457  	}
  1458  	parseOpts := []Opt{
  1459  		IncludePaths([]string{
  1460  			".",
  1461  		}),
  1462  		IncludePaths(includePaths),
  1463  		SysIncludePaths(sysIncludePaths),
  1464  		devTest(),
  1465  		gccEmu(),
  1466  	}
  1467  	if *oFailFast {
  1468  		parseOpts = append(parseOpts, CrashOnError())
  1469  	}
  1470  
  1471  	p := predefined + `
  1472  #define LOCALEDIR "/usr/local/share/locale"
  1473  #define LIBDIR "/usr/local/lib"
  1474  #define INCLUDEDIR "/usr/local/include"
  1475  #define HAVE_CONFIG_H
  1476  `
  1477  	testDev(
  1478  		t,
  1479  		p,
  1480  		p,
  1481  		p+`
  1482  #define __const const
  1483  #define __inline inline
  1484  #define __restrict __restrict__
  1485  #define __typeof typeof
  1486  `,
  1487  		[]string{
  1488  			"-DLOCALEDIR=\"/usr/local/share/locale\"",
  1489  			"-DLIBDIR=\"/usr/local/lib\"",
  1490  			"-DINCLUDEDIR=\"/usr/local/include\"",
  1491  			"-DHAVE_CONFIG_H",
  1492  			"-I.",
  1493  		},
  1494  		[]string{
  1495  			"ar.c",
  1496  			"arscan.c",
  1497  			"commands.c",
  1498  			"default.c",
  1499  			"dir.c",
  1500  			"expand.c",
  1501  			"file.c",
  1502  			"function.c",
  1503  			"getopt.c",
  1504  			"getopt1.c",
  1505  			"guile.c",
  1506  			"hash.c",
  1507  			"implicit.c",
  1508  			"job.c",
  1509  			"load.c",
  1510  			"loadapi.c",
  1511  			"main.c",
  1512  			"misc.c",
  1513  			"output.c",
  1514  			"read.c",
  1515  			"remake.c",
  1516  			"remote-stub.c",
  1517  			"rule.c",
  1518  			"signame.c",
  1519  			"strcache.c",
  1520  			"variable.c",
  1521  			"version.c",
  1522  			"vpath.c",
  1523  		},
  1524  		"testdata/dev/make-4.1/",
  1525  		ppOpts,
  1526  		parseOpts,
  1527  	)
  1528  }
  1529  
  1530  func TestDevBc(t *testing.T) {
  1531  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  1532  	if err != nil {
  1533  		t.Logf("skipping: %v", err)
  1534  		return
  1535  	}
  1536  
  1537  	ppOpts := []Opt{
  1538  		IncludePaths([]string{
  1539  			".",
  1540  			"..",
  1541  			"./../h",
  1542  		}),
  1543  		IncludePaths(includePaths),
  1544  		SysIncludePaths(sysIncludePaths),
  1545  		EnableIncludeNext(),
  1546  		devTest(),
  1547  	}
  1548  	if *oFailFast {
  1549  		ppOpts = append(ppOpts, CrashOnError())
  1550  	}
  1551  	parseOpts := []Opt{
  1552  		IncludePaths([]string{
  1553  			".",
  1554  			"..",
  1555  			"./../h",
  1556  		}),
  1557  		IncludePaths(includePaths),
  1558  		SysIncludePaths(sysIncludePaths),
  1559  		devTest(),
  1560  		gccEmu(),
  1561  	}
  1562  	if *oFailFast {
  1563  		parseOpts = append(parseOpts, CrashOnError())
  1564  	}
  1565  
  1566  	p := predefined + `
  1567  #define HAVE_CONFIG_H
  1568  `
  1569  	testDev(
  1570  		t,
  1571  		p,
  1572  		p,
  1573  		p+`
  1574  #define __const const
  1575  #define __inline inline
  1576  #define __restrict __restrict__
  1577  `,
  1578  		[]string{
  1579  			"-DHAVE_CONFIG_H",
  1580  			"-I.",
  1581  			"-I..",
  1582  			"-I./../h",
  1583  		},
  1584  		[]string{
  1585  			"getopt.c",
  1586  			"getopt1.c",
  1587  			"number.c",
  1588  			"vfprintf.c",
  1589  		},
  1590  		"testdata/dev/bc-1.06/lib/",
  1591  		ppOpts,
  1592  		parseOpts,
  1593  	)
  1594  
  1595  	testDev(
  1596  		t,
  1597  		p,
  1598  		p,
  1599  		p+`
  1600  #define __const const
  1601  #define __inline inline
  1602  #define __restrict __restrict__
  1603  `,
  1604  		[]string{
  1605  			"-DHAVE_CONFIG_H",
  1606  			"-I.",
  1607  			"-I..",
  1608  			"-I./../h",
  1609  		},
  1610  		[]string{
  1611  			"main.c",
  1612  			"bc.c",
  1613  			"scan.c",
  1614  			"execute.c",
  1615  			"load.c",
  1616  			"storage.c",
  1617  			"util.c",
  1618  			"global.c",
  1619  		},
  1620  		"testdata/dev/bc-1.06/bc",
  1621  		ppOpts,
  1622  		parseOpts,
  1623  	)
  1624  
  1625  	testDev(
  1626  		t,
  1627  		p,
  1628  		p,
  1629  		p+`
  1630  #define __const const
  1631  #define __inline inline
  1632  #define __restrict __restrict__
  1633  `,
  1634  		[]string{
  1635  			"-DHAVE_CONFIG_H",
  1636  			"-I.",
  1637  			"-I..",
  1638  			"-I./../h",
  1639  		},
  1640  		[]string{
  1641  			"dc.c",
  1642  			"misc.c",
  1643  			"eval.c",
  1644  			"stack.c",
  1645  			"array.c",
  1646  			"numeric.c",
  1647  			"string.c",
  1648  		},
  1649  		"testdata/dev/bc-1.06/dc",
  1650  		ppOpts,
  1651  		parseOpts,
  1652  	)
  1653  }
  1654  
  1655  func TestDevEmacs(t *testing.T) {
  1656  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  1657  	if err != nil {
  1658  		t.Logf("skipping: %v", err)
  1659  		return
  1660  	}
  1661  
  1662  	ppOpts := []Opt{
  1663  		IncludePaths([]string{
  1664  			".",
  1665  			"../lib",
  1666  			"../src",
  1667  		}),
  1668  		IncludePaths(includePaths),
  1669  		SysIncludePaths(sysIncludePaths),
  1670  		EnableIncludeNext(),
  1671  		devTest(),
  1672  	}
  1673  	if *oFailFast {
  1674  		ppOpts = append(ppOpts, CrashOnError())
  1675  	}
  1676  	parseOpts := []Opt{
  1677  		IncludePaths([]string{
  1678  			".",
  1679  			"../lib",
  1680  			"../src",
  1681  		}),
  1682  		IncludePaths(includePaths),
  1683  		SysIncludePaths(sysIncludePaths),
  1684  		devTest(),
  1685  		gccEmu(),
  1686  	}
  1687  	if *oFailFast {
  1688  		parseOpts = append(parseOpts, CrashOnError())
  1689  	}
  1690  
  1691  	p := predefined + `
  1692  #define HAVE_CONFIG_H
  1693  #define _GCC_MAX_ALIGN_T
  1694  `
  1695  	testDev(
  1696  		t,
  1697  		p+`
  1698  #define _Noreturn __attribute__ ((__noreturn__))
  1699  `,
  1700  		p,
  1701  		p+`
  1702  #define __const const
  1703  #define __getopt_argv_const const
  1704  #define __inline inline
  1705  #define __restrict __restrict__
  1706  `,
  1707  		[]string{
  1708  			"-std=gnu99",
  1709  			"-DHAVE_CONFIG_H",
  1710  			"-I.",
  1711  			"-I../lib",
  1712  			"-I../src",
  1713  		},
  1714  		[]string{
  1715  			"acl-errno-valid.c",
  1716  			"allocator.c",
  1717  			"binary-io.c",
  1718  			"c-ctype.c",
  1719  			"c-strcasecmp.c",
  1720  			"c-strncasecmp.c",
  1721  			"careadlinkat.c",
  1722  			"close-stream.c",
  1723  			"count-one-bits.c",
  1724  			"count-trailing-zeros.c",
  1725  			"dtoastr.c",
  1726  			"dtotimespec.c",
  1727  			"fcntl.c",
  1728  			"file-has-acl.c",
  1729  			"filemode.c",
  1730  			"getopt.c",
  1731  			"getopt1.c",
  1732  			"gettime.c",
  1733  			"md5.c",
  1734  			"openat-die.c",
  1735  			"pipe2.c",
  1736  			"pthread_sigmask.c",
  1737  			"qcopy-acl.c",
  1738  			"qset-acl.c",
  1739  			"save-cwd.c",
  1740  			"sha1.c",
  1741  			"sha256.c",
  1742  			"sha512.c",
  1743  			"sig2str.c",
  1744  			"stat-time.c",
  1745  			"strftime.c",
  1746  			"timespec-add.c",
  1747  			"timespec-sub.c",
  1748  			"timespec.c",
  1749  			"u64.c",
  1750  			"unistd.c",
  1751  			"utimens.c",
  1752  		},
  1753  		"testdata/dev/emacs-24.5/lib",
  1754  		ppOpts,
  1755  		parseOpts,
  1756  	)
  1757  
  1758  	p = predefined + `
  1759   #define CTAGS
  1760   #define EMACS_NAME "GNU Emacs"
  1761   #define HAVE_CONFIG_H
  1762   #define HAVE_SHARED_GAME_DIR "/usr/local/var/games/emacs"
  1763   #define VERSION "24.5"
  1764   `
  1765  	testDev(
  1766  		t,
  1767  		p+`
  1768  #define _GCC_MAX_ALIGN_T
  1769  #define _Noreturn __attribute__ ((__noreturn__))
  1770  `,
  1771  		p,
  1772  		p+`
  1773  #define __const const
  1774  #define __inline inline
  1775  #define __restrict __restrict__
  1776  #define __typeof typeof
  1777  `,
  1778  		[]string{
  1779  			"-std=gnu99",
  1780  			"-I.",
  1781  			"-I../lib",
  1782  			"-I../src",
  1783  			"-DEMACS_NAME=\"GNU Emacs\"",
  1784  			"-DCTAGS",
  1785  			"-DHAVE_SHARED_GAME_DIR=\"/usr/local/var/games/emacs\"",
  1786  			"-DVERSION=\"24.5\"",
  1787  		},
  1788  		[]string{
  1789  			"./../src/regex.c",
  1790  			"./ebrowse.c",
  1791  			"./emacsclient.c",
  1792  			"./etags.c",
  1793  			"./hexl.c",
  1794  			"./make-docfile.c",
  1795  			"./movemail.c",
  1796  			"./pop.c",
  1797  			"./profile.c",
  1798  			"./test-distrib.c",
  1799  			"./update-game-score.c",
  1800  		},
  1801  		"testdata/dev/emacs-24.5/lib-src/",
  1802  		ppOpts,
  1803  		parseOpts,
  1804  	)
  1805  
  1806  	ppOpts = []Opt{
  1807  		IncludePaths([]string{
  1808  			".",
  1809  			"../lib",
  1810  			"/usr/include/gtk-3.0",
  1811  			"/usr/include/pango-1.0",
  1812  			"/usr/include/gio-unix-2.0/",
  1813  			"/usr/include/atk-1.0",
  1814  			"/usr/include/cairo",
  1815  			"/usr/include/gdk-pixbuf-2.0",
  1816  			"/usr/include/freetype2",
  1817  			"/usr/include/glib-2.0",
  1818  			"/usr/lib/x86_64-linux-gnu/glib-2.0/include",
  1819  			"/usr/include/pixman-1",
  1820  			"/usr/include/libpng12",
  1821  		}),
  1822  		IncludePaths(includePaths),
  1823  		SysIncludePaths(sysIncludePaths),
  1824  		EnableDefineOmitCommaBeforeDDD(),
  1825  		EnableIncludeNext(),
  1826  		devTest(),
  1827  	}
  1828  	if *oFailFast {
  1829  		ppOpts = append(ppOpts, CrashOnError())
  1830  	}
  1831  	parseOpts = []Opt{
  1832  		IncludePaths([]string{
  1833  			".",
  1834  			"../lib",
  1835  			"/usr/include/gtk-3.0",
  1836  			"/usr/include/pango-1.0",
  1837  			"/usr/include/gio-unix-2.0/",
  1838  			"/usr/include/atk-1.0",
  1839  			"/usr/include/cairo",
  1840  			"/usr/include/gdk-pixbuf-2.0",
  1841  			"/usr/include/freetype2",
  1842  			"/usr/include/glib-2.0",
  1843  			"/usr/lib/x86_64-linux-gnu/glib-2.0/include",
  1844  			"/usr/include/pixman-1",
  1845  			"/usr/include/libpng12",
  1846  		}),
  1847  		IncludePaths(includePaths),
  1848  		SysIncludePaths(sysIncludePaths),
  1849  		devTest(),
  1850  		gccEmu(),
  1851  	}
  1852  	if *oFailFast {
  1853  		parseOpts = append(parseOpts, CrashOnError())
  1854  	}
  1855  
  1856  	p = predefined + `
  1857  #define _GCC_MAX_ALIGN_T
  1858  #define emacs
  1859  `
  1860  
  1861  	testDev(
  1862  		t,
  1863  		p+`
  1864  #define _Noreturn __attribute__ ((__noreturn__))
  1865  `,
  1866  		p,
  1867  		p+`
  1868  #define _Alignas(x)
  1869  #define __const const
  1870  #define __inline inline
  1871  #define __restrict __restrict__
  1872  #define __typeof typeof
  1873  `,
  1874  		[]string{
  1875  			"-std=gnu99",
  1876  			"-Demacs",
  1877  			"-I.",
  1878  			"-I../lib",
  1879  			"-I/usr/include/gtk-3.0",
  1880  			"-I/usr/include/pango-1.0",
  1881  			"-I/usr/include/gio-unix-2.0/",
  1882  			"-I/usr/include/atk-1.0",
  1883  			"-I/usr/include/cairo",
  1884  			"-I/usr/include/gdk-pixbuf-2.0",
  1885  			"-I/usr/include/freetype2",
  1886  			"-I/usr/include/glib-2.0",
  1887  			"-I/usr/lib/x86_64-linux-gnu/glib-2.0/include",
  1888  			"-I/usr/include/pixman-1",
  1889  			"-I/usr/include/libpng12",
  1890  		},
  1891  		[]string{
  1892  			"alloc.c",
  1893  			"atimer.c",
  1894  			"bidi.c",
  1895  			"buffer.c",
  1896  			"callint.c",
  1897  			"callproc.c",
  1898  			"casefiddle.c",
  1899  			"casetab.c",
  1900  			"category.c",
  1901  			"ccl.c",
  1902  			"character.c",
  1903  			"charset.c",
  1904  			"chartab.c",
  1905  			"cm.c",
  1906  			"cmds.c",
  1907  			"coding.c",
  1908  			"composite.c",
  1909  			"data.c",
  1910  			"decompress.c",
  1911  			"dired.c",
  1912  			"dispnew.c",
  1913  			"doc.c",
  1914  			"doprnt.c",
  1915  			"editfns.c",
  1916  			"emacs.c",
  1917  			"eval.c",
  1918  			"fileio.c",
  1919  			"filelock.c",
  1920  			"floatfns.c",
  1921  			"fns.c",
  1922  			"font.c",
  1923  			"fontset.c",
  1924  			"frame.c",
  1925  			"fringe.c",
  1926  			"ftfont.c",
  1927  			"gfilenotify.c",
  1928  			"gnutls.c",
  1929  			"gtkutil.c",
  1930  			"indent.c",
  1931  			"insdel.c",
  1932  			"intervals.c",
  1933  			"keyboard.c",
  1934  			"keymap.c",
  1935  			"lastfile.c",
  1936  			"lread.c",
  1937  			"macros.c",
  1938  			"marker.c",
  1939  			"menu.c",
  1940  			"minibuf.c",
  1941  			"print.c",
  1942  			"process.c",
  1943  			"profiler.c",
  1944  			"region-cache.c",
  1945  			"scroll.c",
  1946  			"search.c",
  1947  			"sound.c",
  1948  			"syntax.c",
  1949  			"sysdep.c",
  1950  			"term.c",
  1951  			"terminal.c",
  1952  			"terminfo.c",
  1953  			"textprop.c",
  1954  			"undo.c",
  1955  			"vm-limit.c",
  1956  			"window.c",
  1957  			"xdisp.c",
  1958  			"xfaces.c",
  1959  			"xfns.c",
  1960  			"xfont.c",
  1961  			"xgselect.c",
  1962  			"xmenu.c",
  1963  			"xml.c",
  1964  			"xrdb.c",
  1965  			"xselect.c",
  1966  			"xsmfns.c",
  1967  			"xterm.c",
  1968  			/// "bytecode.c",      // [lo ... hi] = expr
  1969  			/// "emacsgtkfixed.c", // /usr/include/gtk-3.0/gtk/gtkversion.h:98:9: cannot redefine macro: argument names differ
  1970  			/// "ftxfont.c",       // ftxfont.c:145:7: undefined: ftfont_driver
  1971  			/// "unexelf.c",       // /usr/include/x86_64-linux-gnu/bits/link.h:97:3: unexpected identifier __int128_t, expected one of ['}', _Bool, _Complex, _Static_assert, char, const, double, enum, float, int, long, restrict, short, signed, struct, typedefname, typeof, union, unsigned, void, volatile]
  1972  			/// "xftfont.c",       // lisp.h:2041:13: unexpected typedefname, expected optional type qualifier list or pointer or one of ['(', ')', '*', ',', '[', const, identifier, restrict, volatile]
  1973  			/// "xsettings.c",     // xsettings.c:431:36: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile]
  1974  			///"image.c",         // /usr/include/gif_lib.h:269:44: unexpected typedefname, expected optional type qualifier list or pointer or one of ['(', ')', '*', ',', '[', const, identifier, restrict, volatile]
  1975  		},
  1976  		"testdata/dev/emacs-24.5/src/",
  1977  		ppOpts,
  1978  		parseOpts,
  1979  	)
  1980  }
  1981  func TestDevM4(t *testing.T) {
  1982  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  1983  	if err != nil {
  1984  		t.Logf("skipping: %v", err)
  1985  		return
  1986  	}
  1987  
  1988  	ppOpts := []Opt{
  1989  		IncludePaths([]string{
  1990  			".",
  1991  		}),
  1992  		IncludePaths(includePaths),
  1993  		SysIncludePaths(sysIncludePaths),
  1994  		devTest(),
  1995  		EnableIncludeNext(),
  1996  	}
  1997  	if *oFailFast {
  1998  		ppOpts = append(ppOpts, CrashOnError())
  1999  	}
  2000  	parseOpts := []Opt{
  2001  		IncludePaths([]string{
  2002  			".",
  2003  		}),
  2004  		IncludePaths(includePaths),
  2005  		SysIncludePaths(sysIncludePaths),
  2006  		devTest(),
  2007  		gccEmu(),
  2008  	}
  2009  	if *oFailFast {
  2010  		parseOpts = append(parseOpts, CrashOnError())
  2011  	}
  2012  
  2013  	p := predefined
  2014  
  2015  	testDev(
  2016  		t,
  2017  		p,
  2018  		p,
  2019  		p+`
  2020  #define __const
  2021  #define __inline inline
  2022  #define __restrict __restrict__
  2023  #define __typeof typeof
  2024  `,
  2025  		[]string{
  2026  			"-I.",
  2027  		},
  2028  		[]string{
  2029  			"asnprintf.c",
  2030  			"asprintf.c",
  2031  			"basename-lgpl.c",
  2032  			"basename.c",
  2033  			"binary-io.c",
  2034  			"c-ctype.c",
  2035  			"c-strcasecmp.c",
  2036  			"c-strncasecmp.c",
  2037  			"clean-temp.c",
  2038  			"cloexec.c",
  2039  			"close-stream.c",
  2040  			"closein.c",
  2041  			"closeout.c",
  2042  			"dirname-lgpl.c",
  2043  			"dirname.c",
  2044  			"dup-safer-flag.c",
  2045  			"dup-safer.c",
  2046  			"exitfail.c",
  2047  			"fatal-signal.c",
  2048  			"fclose.c",
  2049  			"fcntl.c",
  2050  			"fd-hook.c",
  2051  			"fd-safer-flag.c",
  2052  			"fd-safer.c",
  2053  			"fflush.c",
  2054  			"filenamecat-lgpl.c",
  2055  			"filenamecat.c",
  2056  			"fopen-safer.c",
  2057  			"fpurge.c",
  2058  			"freadahead.c",
  2059  			"freading.c",
  2060  			"fseek.c",
  2061  			"fseeko.c",
  2062  			"gl_avltree_oset.c",
  2063  			"gl_linkedhash_list.c",
  2064  			"gl_list.c",
  2065  			"gl_oset.c",
  2066  			"gl_xlist.c",
  2067  			"gl_xoset.c",
  2068  			"glthread/lock.c",
  2069  			"glthread/threadlib.c",
  2070  			"glthread/tls.c",
  2071  			"localcharset.c",
  2072  			"malloca.c",
  2073  			"math.c",
  2074  			"memchr2.c",
  2075  			"mkstemp-safer.c",
  2076  			"pipe-safer.c",
  2077  			"pipe2-safer.c",
  2078  			"pipe2.c",
  2079  			"printf-args.c",
  2080  			"printf-frexp.c",
  2081  			"printf-parse.c",
  2082  			"progname.c",
  2083  			"quotearg.c",
  2084  			"sig-handler.c",
  2085  			"stripslash.c",
  2086  			"tempname.c",
  2087  			"tmpdir.c",
  2088  			"unistd.c",
  2089  			"vasprintf.c",
  2090  			"verror.c",
  2091  			"version-etc-fsf.c",
  2092  			"version-etc.c",
  2093  			"wait-process.c",
  2094  			"wctype-h.c",
  2095  			"xalloc-die.c",
  2096  			"xasprintf.c",
  2097  			"xmalloc.c",
  2098  			"xmalloca.c",
  2099  			"xprintf.c",
  2100  			"xsize.c",
  2101  			"xstrndup.c",
  2102  			"xvasprintf.c",
  2103  			/// "c-stack.c", c-stack.c:119:3: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile]
  2104  			/// "execute.c", spawn.h:457:9: cannot redefine macro using a replacement list of different length
  2105  			/// "isnanl.c", float+.h:145:32: array size must be positive: -1
  2106  			/// "printf-frexpl.c", printf-frexp.c:72:3: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile]
  2107  			/// "spawn-pipe.c", spawn.h:457:9: cannot redefine macro using a replacement list of different length
  2108  			/// "vasnprintf.c", vasnprintf.c:3624:25: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile]
  2109  		},
  2110  		"testdata/dev/m4-1.4.17/lib/",
  2111  		ppOpts,
  2112  		parseOpts,
  2113  	)
  2114  }
  2115  
  2116  func TestDevStbVorbis(t *testing.T) {
  2117  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  2118  	if err != nil {
  2119  		t.Logf("skipping: %v", err)
  2120  		return
  2121  	}
  2122  
  2123  	ppOpts := []Opt{
  2124  		IncludePaths(includePaths),
  2125  		SysIncludePaths(sysIncludePaths),
  2126  		devTest(),
  2127  		EnableIncludeNext(),
  2128  	}
  2129  	if *oFailFast {
  2130  		ppOpts = append(ppOpts, CrashOnError())
  2131  	}
  2132  	parseOpts := []Opt{
  2133  		IncludePaths(includePaths),
  2134  		SysIncludePaths(sysIncludePaths),
  2135  		devTest(),
  2136  		gccEmu(),
  2137  	}
  2138  	if *oFailFast {
  2139  		parseOpts = append(parseOpts, CrashOnError())
  2140  	}
  2141  
  2142  	testDev(
  2143  		t,
  2144  		predefined,
  2145  		predefined,
  2146  		predefined+`
  2147  #define __inline inline
  2148  #define __const const
  2149  #define __restrict restrict
  2150  `,
  2151  		nil,
  2152  		[]string{
  2153  			"stb_vorbis.c",
  2154  		},
  2155  		"testdata/dev/stb",
  2156  		ppOpts,
  2157  		parseOpts,
  2158  	)
  2159  }
  2160  
  2161  func TestDevGMP(t *testing.T) {
  2162  	predefined, includePaths, sysIncludePaths, err := HostConfig()
  2163  	if err != nil {
  2164  		t.Logf("skipping: %v", err)
  2165  		return
  2166  	}
  2167  
  2168  	ppOpts := []Opt{
  2169  		IncludePaths(includePaths),
  2170  		SysIncludePaths(sysIncludePaths),
  2171  		devTest(),
  2172  		EnableIncludeNext(),
  2173  	}
  2174  	if *oFailFast {
  2175  		ppOpts = append(ppOpts, CrashOnError())
  2176  	}
  2177  	parseOpts := []Opt{
  2178  		IncludePaths(includePaths),
  2179  		SysIncludePaths(sysIncludePaths),
  2180  		devTest(),
  2181  		gccEmu(),
  2182  	}
  2183  	if *oFailFast {
  2184  		parseOpts = append(parseOpts, CrashOnError())
  2185  	}
  2186  
  2187  	testDev(
  2188  		t,
  2189  		predefined,
  2190  		predefined,
  2191  		predefined,
  2192  		nil,
  2193  		[]string{
  2194  			"gmp.h",
  2195  		},
  2196  		"testdata/dev/gmp-6.1.0/",
  2197  		ppOpts,
  2198  		parseOpts,
  2199  	)
  2200  }
  2201  
  2202  func TestPPParse1(t *testing.T) {
  2203  	path := *o1
  2204  	if path == "" {
  2205  		return
  2206  	}
  2207  
  2208  	testReport := newTestReport()
  2209  	testReport.ClearErrors()
  2210  	_, err := ppParse(path, testReport, testTweaks)
  2211  	if err != nil {
  2212  		t.Fatal(err)
  2213  	}
  2214  
  2215  	if err := testReport.Errors(true); err != nil {
  2216  		t.Fatal(errString(err))
  2217  	}
  2218  }
  2219  
  2220  func TestFinalInjection(t *testing.T) {
  2221  	const src = "int f() {}"
  2222  
  2223  	if strings.HasSuffix(src, "\n") {
  2224  		t.Fatal("internal error")
  2225  	}
  2226  
  2227  	ast, err := ppParseString("test.c", src, xc.NewReport(), &tweaks{})
  2228  	if err != nil {
  2229  		t.Fatal(errString(err))
  2230  	}
  2231  
  2232  	t.Log(PrettyString(ast))
  2233  }
  2234  
  2235  func TestRedecl(t *testing.T) {
  2236  	testParse(t, []string{"testdata/redecl.c"}, "")
  2237  }
  2238  
  2239  func TestParse1(t *testing.T) {
  2240  	path := *o1
  2241  	if path == "" {
  2242  		return
  2243  	}
  2244  
  2245  	testParse(t, []string{path}, "")
  2246  }
  2247  
  2248  func testParse(t *testing.T, paths []string, ignoreError string, opts ...Opt) *TranslationUnit {
  2249  	last := paths[len(paths)-1]
  2250  	ln := filepath.Base(last)
  2251  	f, err := os.Create("log-" + ln)
  2252  	if err != nil {
  2253  		t.Fatal(err)
  2254  	}
  2255  
  2256  	defer f.Close()
  2257  
  2258  	b := bufio.NewWriter(f)
  2259  	defer b.Flush()
  2260  
  2261  	b.WriteString("// +build ignore\n\n")
  2262  	var a []string
  2263  	crash := nopOpt()
  2264  	if *oFailFast {
  2265  		crash = CrashOnError()
  2266  	}
  2267  	opts = append(
  2268  		opts,
  2269  		IncludePaths(includes),
  2270  		SysIncludePaths(sysIncludes),
  2271  		Cpp(func(toks []xc.Token) {
  2272  			a = a[:0]
  2273  			for _, v := range toks {
  2274  				a = append(a, TokSrc(v))
  2275  			}
  2276  			fmt.Fprintf(b, "%s\n", strings.Join(a, " "))
  2277  		}),
  2278  		crash,
  2279  		ErrLimit(-1),
  2280  	)
  2281  	ast, err := Parse(
  2282  		predefinedMacros,
  2283  		paths,
  2284  		newTestModel(),
  2285  		opts...,
  2286  	)
  2287  	if err != nil {
  2288  		if s := strings.TrimSpace(errString(err)); s != ignoreError {
  2289  			t.Fatal(errString(err))
  2290  		}
  2291  	}
  2292  
  2293  	t.Log(paths)
  2294  	return ast
  2295  }
  2296  
  2297  func ddsStr(dds []*DirectDeclarator) string {
  2298  	buf := bytes.NewBufferString("|")
  2299  	for i, dd := range dds {
  2300  		if i == 0 {
  2301  			fmt.Fprintf(buf, "(@%p)", &dds[0])
  2302  		}
  2303  		switch dd.Case {
  2304  		case 0: // IDENTIFIER
  2305  			fmt.Fprintf(buf, "IDENTIFIER(%s: %s)", dd.Token.Position(), dd.Token.S())
  2306  		case 1: // '(' Declarator ')'
  2307  			buf.WriteString("(")
  2308  			buf.WriteString(strings.Repeat("*", dd.Declarator.stars()))
  2309  			fmt.Fprintf(buf, "Declarator.%v)", dds[i-1].Case)
  2310  		case 2: // DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']'
  2311  			fmt.Fprintf(buf, "DirectDeclarator[TypeQualifierListOpt ExpressionOpt.%v]", dd.elements)
  2312  		case 3: // DirectDeclarator '[' "static" TypeQualifierListOpt Expression ']'
  2313  			fmt.Fprintf(buf, "DirectDeclarator[static TypeQualifierListOpt Expression.%v]", dd.elements)
  2314  		case 4: // DirectDeclarator '[' TypeQualifierList "static" Expression ']'
  2315  			fmt.Fprintf(buf, "DirectDeclarator[TypeQualifierList static Expression.%v]", dd.elements)
  2316  		case 5: // DirectDeclarator '[' TypeQualifierListOpt '*' ']'
  2317  			fmt.Fprintf(buf, "DirectDeclarator[TypeQualifierListOpt*.%v]", dd.elements)
  2318  		case 6: // DirectDeclarator '(' ParameterTypeList ')'
  2319  			buf.WriteString("DirectDeclarator(ParameterTypeList)")
  2320  		case 7: // DirectDeclarator '(' IdentifierListOpt ')'
  2321  			buf.WriteString("DirectDeclarator(IdentifierListOpt)")
  2322  		}
  2323  		buf.WriteString("|")
  2324  	}
  2325  	return buf.String()
  2326  }
  2327  
  2328  func (n *ctype) str() string {
  2329  	return fmt.Sprintf("R%v S%v %v", n.resultStars, n.stars, ddsStr(n.dds))
  2330  }
  2331  
  2332  func (n *ctype) str0() string {
  2333  	return fmt.Sprintf("R%v S%v %v", n.resultStars, n.stars, ddsStr(n.dds0))
  2334  }
  2335  
  2336  func TestIssue3(t *testing.T) {
  2337  	if _, err := Parse("", []string{"testdata/issue3.h"}, newTestModel()); err != nil {
  2338  		t.Fatal(errString(err))
  2339  	}
  2340  }
  2341  
  2342  func TestIssue8(t *testing.T) {
  2343  	if _, err := Parse("", []string{"testdata/issue8.h"}, newTestModel()); err != nil {
  2344  		t.Fatal(errString(err))
  2345  	}
  2346  }
  2347  
  2348  func TestIssue4(t *testing.T) {
  2349  	_, err := Parse("", []string{"testdata/issue4.c"}, newTestModel())
  2350  	if err == nil {
  2351  		t.Fatal("unexpected sucess")
  2352  	}
  2353  
  2354  	l, ok := err.(scanner.ErrorList)
  2355  	if !ok {
  2356  		t.Fatalf("unexpected error type %T", err)
  2357  	}
  2358  
  2359  	if g, e := l.Len(), 2; g != e {
  2360  		t.Fatal(g, e)
  2361  	}
  2362  
  2363  	if g, e := l[0].Error(), "testdata/issue4.c:5:13: redeclaration of foo as different kind of symbol, previous declaration at testdata/issue4.c:4:5"; g != e {
  2364  		t.Fatal(g, e)
  2365  	}
  2366  
  2367  	if g, e := l[1].Error(), "testdata/issue4.c:9:15: redeclaration of foo2 as different kind of symbol, previous declaration at testdata/issue4.c:8:7"; g != e {
  2368  		t.Fatal(g, e)
  2369  	}
  2370  }
  2371  
  2372  func unpackType(typ Type) Type {
  2373  	for {
  2374  		switch typ.Kind() {
  2375  		case Ptr, Array:
  2376  			typ = typ.Element()
  2377  		default:
  2378  			return typ
  2379  		}
  2380  	}
  2381  }
  2382  
  2383  func TestIssue9(t *testing.T) {
  2384  	const exp = `original:  typedef short[64] Array
  2385  unpacked:  typedef short Short
  2386  original: JBLOCK short(*)[64] Ptr
  2387  unpacked: JBLOCK short Short
  2388  original: JBLOCKROW short(**)[64] Ptr
  2389  unpacked: JBLOCKROW short Short
  2390  original: JBLOCKARRAY short(***)[64] Ptr
  2391  unpacked: JBLOCKARRAY short Short
  2392  original:  short[64] Array
  2393  unpacked:  short Short
  2394  original:  short[64] Array
  2395  unpacked:  short Short
  2396  original: JBLOCK short[64] Array
  2397  unpacked: JBLOCK short Short
  2398  original: JBLOCK short[64] Array
  2399  unpacked: JBLOCK short Short
  2400  original:  short(*)[64] Ptr
  2401  unpacked:  short Short
  2402  original:  short(*)[64] Ptr
  2403  unpacked:  short Short
  2404  original:  short(*)[64] Ptr
  2405  unpacked:  short Short
  2406  original: JBLOCKROW short(*)[64] Ptr
  2407  unpacked: JBLOCKROW short Short
  2408  original: JBLOCKROW short(*)[64] Ptr
  2409  unpacked: JBLOCKROW short Short
  2410  original:  short(**)[64] Ptr
  2411  unpacked:  short Short
  2412  original:  short(**)[64] Ptr
  2413  unpacked:  short Short
  2414  original:  short(**)[64] Ptr
  2415  unpacked:  short Short
  2416  original: JBLOCKARRAY short(**)[64] Ptr
  2417  unpacked: JBLOCKARRAY short Short
  2418  original: JBLOCKARRAY short(**)[64] Ptr
  2419  unpacked: JBLOCKARRAY short Short
  2420  original:  short(***)[64] Ptr
  2421  unpacked:  short Short
  2422  original:  short(***)[64] Ptr
  2423  unpacked:  short Short
  2424  original:  short(***)[64] Ptr
  2425  unpacked:  short Short
  2426  original: JBLOCKIMAGE short(***)[64] Ptr
  2427  unpacked: JBLOCKIMAGE short Short
  2428  original: JBLOCKIMAGE short(***)[64] Ptr
  2429  unpacked: JBLOCKIMAGE short Short
  2430  `
  2431  
  2432  	tu, err := Parse("", []string{"testdata/issue9.c"}, newTestModel())
  2433  	if err != nil {
  2434  		t.Fatal(errString(err))
  2435  	}
  2436  
  2437  	var buf bytes.Buffer
  2438  	for tu != nil {
  2439  		declr := tu.ExternalDeclaration.Declaration.InitDeclaratorListOpt.InitDeclaratorList.InitDeclarator.Declarator
  2440  		name := string(xc.Dict.S(declr.RawSpecifier().TypedefName()))
  2441  		fmt.Fprintln(&buf, "original:", name, declr.Type, declr.Type.Kind())
  2442  		unpacked := unpackType(declr.Type)
  2443  		fmt.Fprintln(&buf, "unpacked:", name, unpacked, unpacked.Kind())
  2444  		tu = tu.TranslationUnit
  2445  	}
  2446  	if g, e := buf.String(), exp; g != e {
  2447  		t.Fatalf("got:\n%s\nexp:\n%s", g, e)
  2448  	}
  2449  }
  2450  
  2451  func TestEnumConstToks(t *testing.T) {
  2452  	tu, err := Parse("", []string{"testdata/enum.c"}, newTestModel())
  2453  	if err != nil {
  2454  		t.Fatal(errString(err))
  2455  	}
  2456  
  2457  	sc := tu.Declarations
  2458  	foo := sc.Lookup(NSIdentifiers, xc.Dict.SID("foo"))
  2459  	if foo.Node == nil {
  2460  		t.Fatal("internal error")
  2461  	}
  2462  
  2463  	switch x := foo.Node.(type) {
  2464  	case *DirectDeclarator:
  2465  		typ := x.TopDeclarator().Type
  2466  		if g, e := typ.Kind(), Enum; g != e {
  2467  			t.Fatal(g, e)
  2468  		}
  2469  
  2470  		l := typ.EnumeratorList()
  2471  		if g, e := PrettyString(
  2472  			l),
  2473  			`[]cc.EnumConstant{ // len 2
  2474  · 0: cc.EnumConstant{
  2475  · · DefTok: testdata/enum.c:4:2: IDENTIFIER "c",
  2476  · · Value: 18,
  2477  · · Tokens: []xc.Token{ // len 3
  2478  · · · 0: testdata/enum.c:4:6: INTCONST "42",
  2479  · · · 1: testdata/enum.c:4:9: '-',
  2480  · · · 2: testdata/enum.c:4:11: INTCONST "24",
  2481  · · },
  2482  · },
  2483  · 1: cc.EnumConstant{
  2484  · · DefTok: testdata/enum.c:5:2: IDENTIFIER "d",
  2485  · · Value: 592,
  2486  · · Tokens: []xc.Token{ // len 3
  2487  · · · 0: testdata/enum.c:5:6: INTCONST "314",
  2488  · · · 1: testdata/enum.c:5:10: '+',
  2489  · · · 2: testdata/enum.c:5:12: INTCONST "278",
  2490  · · },
  2491  · },
  2492  }`; g != e {
  2493  			t.Fatalf("got\n%s\nexp\n%s", g, e)
  2494  		}
  2495  		var a []string
  2496  		for _, e := range l {
  2497  			var b []string
  2498  			for _, t := range e.Tokens {
  2499  				b = append(b, TokSrc(t))
  2500  			}
  2501  			a = append(a, strings.Join(b, " "))
  2502  		}
  2503  		if g, e := strings.Join(a, "\n"), "42 - 24\n314 + 278"; g != e {
  2504  			t.Fatalf("got\n%s\nexp\n%s", g, e)
  2505  		}
  2506  	default:
  2507  		t.Fatalf("%T", x)
  2508  	}
  2509  }
  2510  
  2511  func TestPaste(t *testing.T) {
  2512  	testParse(t, []string{"testdata/paste.c"}, "")
  2513  }
  2514  
  2515  func TestPaste2(t *testing.T) {
  2516  	testParse(t, []string{"testdata/paste2.c"}, "")
  2517  }
  2518  
  2519  func TestFunc(t *testing.T) {
  2520  	testParse(t, []string{"testdata/func.c"}, "")
  2521  }
  2522  
  2523  func TestEmptyMacroArg(t *testing.T) {
  2524  	testParse(t, []string{"testdata/empty.c"}, "")
  2525  }
  2526  
  2527  func TestFuncFuncParams(t *testing.T) {
  2528  	testParse(t, []string{"testdata/funcfunc.c"}, "")
  2529  }
  2530  
  2531  func TestAnonStructField(t *testing.T) {
  2532  	testParse(
  2533  		t,
  2534  		[]string{"testdata/anon.c"},
  2535  		"testdata/anon.c:4:7: only unnamed structs and unions are allowed",
  2536  		EnableAnonymousStructFields(),
  2537  	)
  2538  }
  2539  
  2540  func tokStr(toks []xc.Token) string {
  2541  	var b []byte
  2542  	for _, v := range toks {
  2543  		switch v.Rune {
  2544  		case sentinel:
  2545  			b = append(b, []byte("@:")...)
  2546  		case IDENTIFIER_NONREPL:
  2547  			b = append(b, []byte("-:")...)
  2548  		}
  2549  		b = append(b, xc.Dict.S(tokVal(v))...)
  2550  	}
  2551  	return string(b)
  2552  }
  2553  
  2554  func tokStr2(toks [][]xc.Token) string {
  2555  	var a []string
  2556  	for _, v := range toks {
  2557  		a = append(a, tokStr(v))
  2558  	}
  2559  	return strings.Join(a, ", ")
  2560  }
  2561  
  2562  func TestIssue50(t *testing.T) {
  2563  	if _, err := Parse("", []string{"testdata/issue50.h"}, newTestModel()); err == nil {
  2564  		t.Fatal("unexpected success")
  2565  	}
  2566  }
  2567  
  2568  // https://github.com/cznic/cc/issues/57
  2569  func TestIssue57(t *testing.T) {
  2570  	tu, err := Parse("", []string{"testdata/issue57.c"}, newTestModel())
  2571  	if err != nil {
  2572  		t.Fatal(errString(err))
  2573  	}
  2574  
  2575  	bool_func := tu.Declarations.Identifiers[dict.SID("bool_func")].Node.(*DirectDeclarator).TopDeclarator()
  2576  	typ := bool_func.Type
  2577  	if g, e := typ.String(), "int(*)()"; g != e {
  2578  		t.Fatalf("%q %q", g, e)
  2579  	}
  2580  	typ = typ.Element() // deref function pointer
  2581  	if g, e := typ.Result().String(), "int"; g != e {
  2582  		t.Fatalf("%q %q", g, e)
  2583  	}
  2584  	// bool_t -> ok!
  2585  	if g, e := typ.Result().RawDeclarator().RawSpecifier().TypedefName(), dict.SID("bool_t"); g != e {
  2586  		t.Fatal(g, e)
  2587  	}
  2588  
  2589  	func1 := tu.Declarations.Identifiers[dict.SID("func1")].Node.(*DirectDeclarator).TopDeclarator()
  2590  	typ = func1.Type
  2591  	if g, e := typ.String(), "int(*)()"; g != e {
  2592  		t.Fatalf("%q %q", g, e)
  2593  	}
  2594  	typ = typ.Element() // deref function pointer
  2595  	if g, e := typ.String(), "int()"; g != e {
  2596  		t.Fatalf("%q %q", g, e)
  2597  	}
  2598  	if g, e := typ.Result().String(), "int"; g != e {
  2599  		t.Fatalf("%q %q", g, e)
  2600  	}
  2601  	// try to get bool_t the way we got it above
  2602  	if g, e := typ.Result().RawDeclarator().RawSpecifier().TypedefName(), dict.SID("bool_t"); g != e {
  2603  		t.Fatal(string(xc.Dict.S(g)), string(xc.Dict.S(e))) // bool_func, how to get bool_t?
  2604  	}
  2605  }
  2606  
  2607  // https://github.com/cznic/cc/issues/62
  2608  func TestIssue62(t *testing.T) {
  2609  	tu, err := Parse("", []string{"testdata/issue62.c"}, newTestModel())
  2610  	if err != nil {
  2611  		t.Fatal(errString(err))
  2612  	}
  2613  
  2614  	for ; tu != nil; tu = tu.TranslationUnit {
  2615  		d := tu.ExternalDeclaration.Declaration.Declarator()
  2616  		var e Linkage
  2617  		tag := string(xc.Dict.S(d.Type.Tag()))
  2618  		t.Logf("%s: %s", position(d.Pos()), tag)
  2619  		switch {
  2620  		case strings.HasPrefix(tag, "global"):
  2621  			e = External
  2622  		case strings.HasPrefix(tag, "local"):
  2623  			e = Internal
  2624  		}
  2625  		if g := d.Linkage; g != e {
  2626  			t.Fatalf("%v %v", g, e)
  2627  		}
  2628  	}
  2629  }
  2630  
  2631  // https://github.com/cznic/cc/issues/64
  2632  func TestIssue64(t *testing.T) {
  2633  	if _, err := Parse("", []string{"testdata/issue64.c"}, newTestModel()); err == nil {
  2634  		t.Fatal("expected error")
  2635  	} else {
  2636  		t.Log(errString(err))
  2637  	}
  2638  }
  2639  
  2640  // https://github.com/cznic/cc/issues/65
  2641  func TestIssue65(t *testing.T) {
  2642  	tu, err := Parse("", []string{"testdata/issue65.c"}, newTestModel())
  2643  	if err != nil {
  2644  		t.Fatal(errString(err))
  2645  	}
  2646  
  2647  	foo, ok := tu.Declarations.Identifiers[xc.Dict.SID("foo")]
  2648  	if !ok {
  2649  		t.Fatal("undefined: foo")
  2650  	}
  2651  
  2652  	ft := foo.Node.(*DirectDeclarator).TopDeclarator().Type
  2653  	m, _ := ft.Members()
  2654  	tab := map[string]int{
  2655  		"i": -1,
  2656  		"j": 0,
  2657  		"k": 1,
  2658  		"l": 3,
  2659  		"m": -1,
  2660  	}
  2661  	for _, v := range m {
  2662  		ofs, ok := tab[string(xc.Dict.S(v.Name))]
  2663  		if !ok {
  2664  			t.Fatal(PrettyString(v))
  2665  		}
  2666  
  2667  		if ofs < 0 {
  2668  			if v.Bits != 0 {
  2669  				t.Fatal(PrettyString(v))
  2670  			}
  2671  			continue
  2672  		}
  2673  
  2674  		if v.Bits == 0 {
  2675  			t.Fatal(PrettyString(v))
  2676  		}
  2677  
  2678  		if g, e := v.BitOffsetOf, ofs; g != e {
  2679  			t.Log(PrettyString(v))
  2680  			t.Fatal(g, e)
  2681  		}
  2682  	}
  2683  }
  2684  
  2685  // https://github.com/cznic/cc/issues/66
  2686  func TestIssue66(t *testing.T) {
  2687  	tu, err := Parse("", []string{"testdata/issue66.c"}, newTestModel())
  2688  	if err != nil {
  2689  		t.Fatal(errString(err))
  2690  	}
  2691  
  2692  	e := tu.ExternalDeclaration.Declaration.InitDeclaratorListOpt.InitDeclaratorList.InitDeclarator.Initializer.Expression
  2693  	if e.Value == nil {
  2694  		t.Fatal("expected constant expression")
  2695  	}
  2696  
  2697  	switch g := e.Value.(type) {
  2698  	case uintptr:
  2699  		if e := uintptr(13); g != e {
  2700  			t.Fatal(g, e)
  2701  		}
  2702  	default:
  2703  		t.Fatalf("%T(%#v)", g, g)
  2704  	}
  2705  }
  2706  
  2707  // https://github.com/cznic/cc/issues/67
  2708  func TestIssue67(t *testing.T) {
  2709  	tu, err := Parse("", []string{"testdata/issue67.c"}, newTestModel(), KeepComments())
  2710  	if err != nil {
  2711  		t.Fatal(errString(err))
  2712  	}
  2713  
  2714  	var a []string
  2715  	for k, v := range tu.Comments {
  2716  		a = append(a, fmt.Sprintf("%s: %q", xc.FileSet.Position(k), xc.Dict.S(v)))
  2717  	}
  2718  	sort.Strings(a)
  2719  	if g, e := strings.Join(a, "\n"), `testdata/issue67.c:14:1: "/* abc11 */\n/* def12\n */"
  2720  testdata/issue67.c:19:1: "/* abc16\n */\n/* def18 */"
  2721  testdata/issue67.c:23:1: "/* abc21 */\n// def22"
  2722  testdata/issue67.c:27:1: "// def25\n/* abc26 */"
  2723  testdata/issue67.c:2:1: "// bar1"
  2724  testdata/issue67.c:32:1: "// def31"
  2725  testdata/issue67.c:5:1: "/*\nbaz3\n*/"
  2726  testdata/issue67.c:9:1: "// abc7\n// def8"`; g != e {
  2727  		t.Fatalf("got\n%s\nexp\n%s", g, e)
  2728  	}
  2729  }
  2730  
  2731  // https://github.com/cznic/cc/issues/68
  2732  func TestIssue68(t *testing.T) {
  2733  	if _, err := Parse("", []string{"testdata/issue68.h"}, newTestModel()); err == nil {
  2734  		t.Fatal("expected error")
  2735  	}
  2736  
  2737  	if _, err := Parse("", []string{"testdata/issue68.h"}, newTestModel(), EnableEmptyDeclarations()); err != nil {
  2738  		t.Fatal(err)
  2739  	}
  2740  }
  2741  
  2742  // https://github.com/cznic/cc/issues/69
  2743  func TestIssue69(t *testing.T) {
  2744  	if _, err := Parse("", []string{"testdata/issue69.h"}, newTestModel()); err != nil {
  2745  		t.Fatal(err)
  2746  	}
  2747  }
  2748  
  2749  // https://github.com/cznic/cc/issues/72
  2750  func TestIssue72(t *testing.T) {
  2751  	if _, err := Parse(
  2752  		"", []string{"testdata/issue72.h"}, newTestModel(),
  2753  		EnableWideEnumValues(),
  2754  	); err != nil {
  2755  		t.Fatal(err)
  2756  	}
  2757  }
  2758  
  2759  // https://github.com/cznic/cc/issues/74
  2760  func TestIssue74EnableWideBitFieldTypes(t *testing.T) {
  2761  	if _, err := Parse(
  2762  		"", []string{"testdata/issue74.h"}, newTestModel(),
  2763  		EnableWideBitFieldTypes(),
  2764  	); err != nil {
  2765  		t.Fatal(err)
  2766  	}
  2767  }
  2768  
  2769  // https://github.com/cznic/cc/issues/77
  2770  func TestIssue77(t *testing.T) {
  2771  	if _, err := Parse(
  2772  		"", []string{"testdata/issue77.c"}, newTestModel(),
  2773  	); err != nil {
  2774  		t.Fatal(err)
  2775  	}
  2776  }
  2777  
  2778  // https://github.com/cznic/cc/issues/78
  2779  func TestIssue78(t *testing.T) {
  2780  	if _, err := Parse(
  2781  		"", []string{"testdata/issue78.c"}, newTestModel(),
  2782  	); err == nil {
  2783  		t.Fatal("expected error")
  2784  	}
  2785  
  2786  	tu, err := Parse(
  2787  		"", []string{"testdata/issue78.c"}, newTestModel(), EnableOmitFuncRetType(),
  2788  	)
  2789  	if err != nil {
  2790  		t.Fatal(err)
  2791  	}
  2792  
  2793  	b := tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("f"))
  2794  	if b.Node == nil {
  2795  		t.Fatal("lookup fail")
  2796  	}
  2797  
  2798  	typ := b.Node.(*DirectDeclarator).TopDeclarator().Type
  2799  	if typ == nil {
  2800  		t.Fatal("missing type")
  2801  	}
  2802  
  2803  	if typ = typ.Result(); typ == nil {
  2804  		t.Fatal("missing result type")
  2805  	}
  2806  
  2807  	if g, e := typ.String(), "int"; g != e {
  2808  		t.Fatalf("%q %q", g, e)
  2809  	}
  2810  }
  2811  
  2812  // https://github.com/cznic/cc/issues/80
  2813  func TestIssue80(t *testing.T) {
  2814  	tu, err := Parse(
  2815  		"", []string{"testdata/issue80.c"}, newTestModel(),
  2816  	)
  2817  	if err != nil {
  2818  		t.Fatal(errString(err))
  2819  	}
  2820  
  2821  	b := tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("s"))
  2822  	if b.Node == nil {
  2823  		t.Fatal("lookup fail")
  2824  	}
  2825  
  2826  	typ := b.Node.(*DirectDeclarator).TopDeclarator().Type
  2827  	if typ == nil {
  2828  		t.Fatal("missing type")
  2829  	}
  2830  
  2831  	if g, e := typ.Kind(), Array; g != e {
  2832  		t.Errorf("Kind: %v %v", g, e)
  2833  	}
  2834  
  2835  	if g, e := typ.Elements(), 7; g != e {
  2836  		t.Errorf("Elements: %v %v", g, e)
  2837  	}
  2838  
  2839  	if g, e := typ.SizeOf(), 7; g != e {
  2840  		t.Fatalf("Sizeof: %v %v", g, e)
  2841  	}
  2842  
  2843  	b = tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("t"))
  2844  	if b.Node == nil {
  2845  		t.Fatal("lookup fail")
  2846  	}
  2847  
  2848  	typ = b.Node.(*DirectDeclarator).TopDeclarator().Type
  2849  	if typ == nil {
  2850  		t.Fatal("missing type")
  2851  	}
  2852  
  2853  	if g, e := typ.Kind(), Ptr; g != e {
  2854  		t.Errorf("Kind: %v %v", g, e)
  2855  	}
  2856  
  2857  	if g, e := typ.Elements(), -1; g != e {
  2858  		t.Errorf("Elements: %v %v", g, e)
  2859  	}
  2860  
  2861  	if g, e := typ.SizeOf(), 8; g != e {
  2862  		t.Fatalf("Sizeof: %v %v", g, e)
  2863  	}
  2864  
  2865  	b = tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("u"))
  2866  	if b.Node == nil {
  2867  		t.Fatal("lookup fail")
  2868  	}
  2869  
  2870  	typ = b.Node.(*DirectDeclarator).TopDeclarator().Type
  2871  	if typ == nil {
  2872  		t.Fatal("missing type")
  2873  	}
  2874  
  2875  	if g, e := typ.Kind(), Array; g != e {
  2876  		t.Errorf("Kind: %v %v", g, e)
  2877  	}
  2878  
  2879  	if g, e := typ.Elements(), 11; g != e {
  2880  		t.Errorf("Elements: %v %v", g, e)
  2881  	}
  2882  
  2883  	if g, e := typ.SizeOf(), 11; g != e {
  2884  		t.Fatalf("Sizeof: %v %v", g, e)
  2885  	}
  2886  }
  2887  
  2888  // https://github.com/cznic/cc/issues/81
  2889  func TestIssue81(t *testing.T) {
  2890  	tu, err := Parse(
  2891  		"", []string{"testdata/issue81.c"}, newTestModel(),
  2892  	)
  2893  	if err != nil {
  2894  		t.Fatal(err)
  2895  	}
  2896  
  2897  	_ = tu
  2898  	for l := tu; l != nil; l = l.TranslationUnit {
  2899  		d := l.ExternalDeclaration.Declaration
  2900  		for l := d.InitDeclaratorListOpt.InitDeclaratorList; l != nil; l = l.InitDeclaratorList {
  2901  			x := l.InitDeclarator.Initializer.Expression
  2902  			s := xc.Dict.S(int(x.Value.(StringLitID)))
  2903  			if g, e := len(s), 3; g != e {
  2904  				t.Fatalf("%v |% x| \n%v %v", position(x.Pos()), s, g, e)
  2905  			}
  2906  
  2907  			if g, e := s, []byte{0, 255, 0}; !bytes.Equal(g, e) {
  2908  				t.Fatalf("%v |% x| |% x|", position(x.Pos()), g, e)
  2909  			}
  2910  		}
  2911  	}
  2912  }
  2913  
  2914  // https://github.com/cznic/cc/issues/82
  2915  func TestIssue82(t *testing.T) {
  2916  	if g, e := testPreprocessor(t, "testdata/issue82.c"),
  2917  		`d(2)
  2918  d(2, 3)`; g != e {
  2919  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
  2920  	}
  2921  }
  2922  
  2923  // https://github.com/cznic/cc/issues/84
  2924  func TestIssue84(t *testing.T) {
  2925  	if g, e := testPreprocessor(t, "testdata/issue84.c"),
  2926  		`c(1, 2, 3);
  2927  c(1, 2);
  2928  c(1, );`; g != e {
  2929  		t.Fatalf("\ngot\n%s\nexp\n%s", g, e)
  2930  	}
  2931  }
  2932  
  2933  var vectorAttr = regexp.MustCompile(`__attribute__ *\(\((__)?vector_size(__)? *\(`)
  2934  
  2935  func testDir(t *testing.T, dir string) {
  2936  
  2937  	var re *regexp.Regexp
  2938  	if s := *oRe; s != "" {
  2939  		re = regexp.MustCompile(s)
  2940  	}
  2941  
  2942  	dir = filepath.FromSlash(dir)
  2943  	t.Log(dir)
  2944  	m, err := filepath.Glob(filepath.Join(dir, "*.c"))
  2945  	if err != nil {
  2946  		t.Fatal(err)
  2947  	}
  2948  
  2949  	sort.Strings(m)
  2950  	predefined, _, sysIncludePaths, err := HostConfig()
  2951  	if err != nil {
  2952  		t.Fatal(err)
  2953  	}
  2954  
  2955  	blacklist := []string{
  2956  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/20011217-2.c", // (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
  2957  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/20020320-1.c", // static T *p = x;
  2958  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr37056.c",    // ? ({void *__s = (u.buf + off); __s;}) : ...
  2959  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr42196-1.c",  // __complex__ int c;
  2960  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr42196-2.c",  // __complex__ int ci;
  2961  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr42196-3.c",  // __complex__ int ci;
  2962  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr54559.c",    // return x + y * (T) (__extension__ 1.0iF);
  2963  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr54713-2.c",  // #include: typedef int V __attribute__((vector_size (N * sizeof (int))));
  2964  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr54713-3.c",  // #include: typedef int V __attribute__((vector_size (N * sizeof (int))));
  2965  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr67143.c",    // __sync_add_and_fetch(&a, 536870912);
  2966  
  2967  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/20041124-1.c",    // struct s { _Complex unsigned short x; };
  2968  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/20041201-1.c",    // typedef struct { _Complex char a; _Complex char b; } Scc2;
  2969  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/20071211-1.c",    // __asm__ volatile ("" : : : "memory");
  2970  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr19449.c",       // int z = __builtin_choose_expr (!__builtin_constant_p (y), 3, 4);
  2971  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr38151.c",       // _Complex int b;
  2972  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr39228.c",       // if (testl (1.18973149535723176502e+4932L) < 1)
  2973  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr56982.c",       // __asm__ volatile ("" : : : "memory");
  2974  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr71626-2.c",     // #include: typedef __INTPTR_TYPE__ V __attribute__((__vector_size__(sizeof (__INTPTR_TYPE__))));
  2975  		"testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pushpop_macro.c", // #pragma push_macro("_")
  2976  	}
  2977  
  2978  	const attempt2prototypes = `
  2979  void exit();
  2980  void abort();
  2981  `
  2982  
  2983  	var pass, gccFail int
  2984  	defer func() {
  2985  		t.Logf("pass %v, gccFail %v (sum %v), total test cases %v", pass, gccFail, pass+gccFail, len(m))
  2986  	}()
  2987  outer:
  2988  	for i, v := range m {
  2989  		if re != nil && !re.MatchString(v) {
  2990  			continue
  2991  		}
  2992  
  2993  		for _, w := range blacklist {
  2994  			if strings.HasSuffix(filepath.ToSlash(v), w) {
  2995  				continue outer
  2996  			}
  2997  		}
  2998  
  2999  		b, err := ioutil.ReadFile(v)
  3000  		if err != nil {
  3001  			t.Fatal(err)
  3002  		}
  3003  
  3004  		if vectorAttr.Match(b) {
  3005  			continue
  3006  		}
  3007  
  3008  		attempt := 1
  3009  	retry:
  3010  		func() {
  3011  			defer func() {
  3012  				if e := recover(); e != nil {
  3013  					err = fmt.Errorf("PANIC\n%s\n%v", debug.Stack(), e)
  3014  				}
  3015  			}()
  3016  
  3017  			s := predefined
  3018  			if attempt == 2 {
  3019  				s += attempt2prototypes
  3020  			}
  3021  			err = testDev1(
  3022  				s,
  3023  				s,
  3024  				s,
  3025  				[]string{},
  3026  				"",
  3027  				v,
  3028  				[]Opt{
  3029  					ErrLimit(-1),
  3030  					SysIncludePaths(sysIncludePaths),
  3031  					EnableIncludeNext(),
  3032  					EnableDefineOmitCommaBeforeDDD(),
  3033  				},
  3034  				[]Opt{
  3035  					ErrLimit(-1),
  3036  					SysIncludePaths(sysIncludePaths),
  3037  					EnableIncludeNext(),
  3038  					EnableWideBitFieldTypes(),
  3039  					EnableEmptyDeclarations(),
  3040  					gccEmu(),
  3041  				},
  3042  			)
  3043  		}()
  3044  
  3045  		if err != nil {
  3046  			//dbg("%T(%v)", err, err)
  3047  			switch err.(type) {
  3048  			case cppCmpError:
  3049  				// fail w/o retry.
  3050  			default:
  3051  				if attempt == 1 { // retry with {abort,exit} prototype.
  3052  					attempt++
  3053  					goto retry
  3054  				}
  3055  
  3056  				s := errString(err)
  3057  				if !strings.Contains(s, "PANIC") && !strings.Contains(s, "TODO") && !strings.Contains(s, "undefined: __builtin_") {
  3058  					if out, err := exec.Command("gcc", "-o", os.DevNull, "-c", "-std=c99", "--pedantic", "-fmax-errors=10", v).CombinedOutput(); len(out) != 0 || err != nil {
  3059  						// Auto blacklist if gcc fails to compile as well.
  3060  						if n := 4000; len(out) > n {
  3061  							out = out[:n]
  3062  						}
  3063  						t.Logf("%s\n==== gcc reports\n%s\n%v", s, out, err)
  3064  						gccFail++
  3065  						continue
  3066  					}
  3067  
  3068  				}
  3069  			}
  3070  
  3071  			t.Errorf("%v\n%v/%v, %v ok(+%v=%v)\nFAIL\n%s (%T)", v, i+1, len(m), pass, gccFail, pass+gccFail, errString(err), err)
  3072  			return
  3073  		}
  3074  
  3075  		pass++
  3076  		if re != nil {
  3077  			t.Logf("%v: %v ok", v, pass)
  3078  		}
  3079  	}
  3080  }
  3081  
  3082  func TestTCCTests(t *testing.T) {
  3083  	if !*oDev {
  3084  		t.Log("enable with -dev")
  3085  		return
  3086  	}
  3087  
  3088  	testDir(t, "testdata/tcc-0.9.26/tests/tests2/")
  3089  }
  3090  
  3091  func TestGCCTests(t *testing.T) {
  3092  	if !*oDev {
  3093  		t.Log("enable with -dev")
  3094  		return
  3095  	}
  3096  
  3097  	testDir(t, "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compat/")
  3098  	testDir(t, "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/")
  3099  	testDir(t, "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/")
  3100  }
  3101  
  3102  // https://github.com/cznic/cc/issues/85
  3103  func TestIssue85(t *testing.T) {
  3104  	tu, err := Parse(
  3105  		"", []string{"testdata/issue85.c"}, newTestModel(), EnableOmitFuncRetType(),
  3106  	)
  3107  	if err != nil {
  3108  		t.Fatal(err)
  3109  	}
  3110  
  3111  	b := tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("i"))
  3112  	if b.Node == nil {
  3113  		t.Fatal("lookup fail")
  3114  	}
  3115  
  3116  	d := b.Node.(*DirectDeclarator).TopDeclarator()
  3117  	if g, e := d.Linkage, External; g != e {
  3118  		t.Fatal(g, e)
  3119  	}
  3120  
  3121  	if g, e := d.Type.Specifier().IsExtern(), false; g != e {
  3122  		t.Fatal(g, e)
  3123  	}
  3124  
  3125  	b = tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("j"))
  3126  	if b.Node == nil {
  3127  		t.Fatal("lookup fail")
  3128  	}
  3129  
  3130  	d = b.Node.(*DirectDeclarator).TopDeclarator()
  3131  	if g, e := d.Linkage, External; g != e {
  3132  		t.Fatal(g, e)
  3133  	}
  3134  
  3135  	if g, e := d.Type.Specifier().IsExtern(), true; g != e {
  3136  		t.Fatal(g, e)
  3137  	}
  3138  }
  3139  
  3140  // https://github.com/cznic/cc/issues/86
  3141  func TestIssue86(t *testing.T) {
  3142  	_, err := Parse(
  3143  		"", []string{"testdata/issue86.c"}, newTestModel(), EnableOmitFuncRetType(),
  3144  	)
  3145  	if err == nil {
  3146  		t.Fatal("missed error")
  3147  	}
  3148  
  3149  	if g, e := err.Error(), "testdata/issue86.c:2:12: 'j' initialized and declared 'extern'"; g != e {
  3150  		t.Fatalf("%q %q", g, e)
  3151  	}
  3152  
  3153  	t.Log(err)
  3154  }
  3155  
  3156  func TestArray(t *testing.T) {
  3157  	ast, err := Parse(
  3158  		"", []string{"testdata/array.c"}, newTestModel(), EnableOmitFuncRetType(),
  3159  	)
  3160  	if err != nil {
  3161  		t.Fatal(errString(err))
  3162  	}
  3163  
  3164  	expr := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody.
  3165  		CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItem.
  3166  		Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression
  3167  
  3168  	if g, e := expr.Type.Kind(), Ptr; g != e {
  3169  		t.Fatal(g, e)
  3170  	}
  3171  
  3172  	dd := expr.IdentResolutionScope().Lookup(NSIdentifiers, dict.SID("a")).Node.(*DirectDeclarator)
  3173  	if g, e := dd.TopDeclarator().Type.Kind(), Array; g != e {
  3174  		t.Fatal(g, e)
  3175  	}
  3176  }
  3177  
  3178  // https://github.com/cznic/cc/issues/87
  3179  func TestIssue87(t *testing.T) {
  3180  	if _, err := Parse(
  3181  		"", []string{"testdata/issue87.c"}, newTestModel(),
  3182  	); err == nil {
  3183  		t.Fatal("missed error")
  3184  	}
  3185  
  3186  	if _, err := Parse(
  3187  		"", []string{"testdata/issue87.c"}, newTestModel(), AllowCompatibleTypedefRedefinitions(),
  3188  	); err != nil {
  3189  		t.Fatal(err)
  3190  	}
  3191  }
  3192  
  3193  // https://github.com/cznic/cc/issues/88
  3194  func TestIssue88(t *testing.T) {
  3195  	ast, err := Parse(
  3196  		"", []string{"testdata/issue88.c"}, newTestModel(),
  3197  	)
  3198  	if err != nil {
  3199  		t.Fatal(errString(err))
  3200  	}
  3201  
  3202  	exp := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody.
  3203  		CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItem.
  3204  		Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression
  3205  
  3206  	if g := exp.BinOpType; g != nil {
  3207  		t.Fatalf("unexpected non-nil BinOpType %s", g)
  3208  	}
  3209  }
  3210  
  3211  // https://github.com/cznic/cc/issues/89
  3212  func TestIssue89(t *testing.T) {
  3213  	ast, err := Parse(
  3214  		"", []string{"testdata/issue89.c"}, newTestModel(), EnableImplicitFuncDef(),
  3215  	)
  3216  	if err != nil {
  3217  		t.Fatal(errString(err))
  3218  	}
  3219  
  3220  	exp := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody.
  3221  		CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItemList.BlockItem.
  3222  		Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression.
  3223  		ArgumentExpressionListOpt.ArgumentExpressionList.Expression
  3224  
  3225  	if g := exp.Type; g == nil {
  3226  		t.Errorf("'a.f': missing expression type")
  3227  	}
  3228  	if g := exp.Expression.Type; g == nil {
  3229  		t.Errorf("'a': missing expression type")
  3230  	}
  3231  }
  3232  
  3233  // https://github.com/cznic/cc/issues/90
  3234  func TestIssue90(t *testing.T) {
  3235  	ast, err := Parse(
  3236  		"", []string{"testdata/issue90.c"}, newTestModel(), EnableImplicitFuncDef(),
  3237  	)
  3238  	if err != nil {
  3239  		t.Fatal(errString(err))
  3240  	}
  3241  
  3242  	expr := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody.
  3243  		CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItem.
  3244  		Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression
  3245  
  3246  	if g, e := expr.Type.Kind(), UInt; g != e {
  3247  		t.Errorf("expr: %v %v", g, e)
  3248  	}
  3249  	if g, e := expr.Expression.Type.Kind(), UInt; g != e {
  3250  		t.Errorf("expr.Expression: %v %v", g, e)
  3251  	}
  3252  	if g, e := expr.Expression2.Type.Kind(), UInt; g != e {
  3253  		t.Errorf("expr.Expression2: %v %v", g, e)
  3254  	}
  3255  }
  3256  
  3257  // https://github.com/cznic/cc/issues/92
  3258  func TestIssue92(t *testing.T) {
  3259  	if _, err := Parse(
  3260  		"", []string{"testdata/issue92.c"}, newTestModel(),
  3261  	); err == nil {
  3262  		t.Fatal("missed error")
  3263  	}
  3264  
  3265  	if _, err := Parse(
  3266  		"", []string{"testdata/issue92.c"}, newTestModel(), AllowCompatibleTypedefRedefinitions(),
  3267  	); err != nil {
  3268  		t.Fatal(err)
  3269  	}
  3270  }
  3271  
  3272  // https://github.com/cznic/cc/issues/93
  3273  func TestIssue93(t *testing.T) {
  3274  	if _, err := Parse(
  3275  		"", []string{"testdata/issue93.c"}, newTestModel(),
  3276  	); err != nil {
  3277  		t.Fatal(err)
  3278  	}
  3279  }