modernc.org/cc@v1.0.1/v2/all_test.go (about) 1 // Copyright 2017 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 // import "modernc.org/cc/v2" 6 7 // [0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 8 9 import ( 10 "bytes" 11 "flag" 12 "fmt" 13 "go/token" 14 "io" 15 "io/ioutil" 16 "os" 17 "path" 18 "path/filepath" 19 "regexp" 20 "runtime" 21 "strings" 22 "testing" 23 "unicode" 24 "unicode/utf8" 25 26 "modernc.org/golex/lex" 27 "modernc.org/xc" 28 ) 29 30 func caller(s string, va ...interface{}) { 31 if s == "" { 32 s = strings.Repeat("%v ", len(va)) 33 } 34 _, fn, fl, _ := runtime.Caller(2) 35 fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl) 36 fmt.Fprintf(os.Stderr, s, va...) 37 fmt.Fprintln(os.Stderr) 38 _, fn, fl, _ = runtime.Caller(1) 39 fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl) 40 fmt.Fprintln(os.Stderr) 41 os.Stderr.Sync() 42 } 43 44 func caller3(s string, va ...interface{}) { 45 if s == "" { 46 s = strings.Repeat("%v ", len(va)) 47 } 48 _, fn, fl, _ := runtime.Caller(3) 49 fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl) 50 fmt.Fprintf(os.Stderr, s, va...) 51 fmt.Fprintln(os.Stderr) 52 _, fn, fl, _ = runtime.Caller(1) 53 fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl) 54 fmt.Fprintln(os.Stderr) 55 os.Stderr.Sync() 56 } 57 58 func dbg(s string, va ...interface{}) { 59 if s == "" { 60 s = strings.Repeat("%v ", len(va)) 61 } 62 _, fn, fl, _ := runtime.Caller(1) 63 fmt.Fprintf(os.Stderr, "# dbg %s:%d: ", path.Base(fn), fl) 64 fmt.Fprintf(os.Stderr, s, va...) 65 fmt.Fprintln(os.Stderr) 66 os.Stderr.Sync() 67 } 68 69 func TODO(...interface{}) string { //TODOOK 70 _, fn, fl, _ := runtime.Caller(1) 71 return fmt.Sprintf("# TODO: %s:%d:\n", path.Base(fn), fl) //TODOOK 72 } 73 74 func use(...interface{}) {} 75 76 func init() { 77 use(caller, caller3, dbg, TODO, toksDump) //TODOOK 78 flag.IntVar(&yyDebug, "yydebug", 0, "") 79 flag.BoolVar(&traceMacroDefs, "macros", false, "") 80 } 81 82 // ============================================================================ 83 84 var ( 85 oRE = flag.String("re", "", "") 86 87 shellc = filepath.FromSlash("testdata/_sqlite/sqlite-amalgamation-3210000/shell.c") 88 sqlite3c = filepath.FromSlash("testdata/_sqlite/sqlite-amalgamation-3210000/sqlite3.c") 89 searchPaths []string 90 ) 91 92 func init() { 93 var err error 94 searchPaths, err = Paths(true) 95 if err != nil { 96 panic(err) 97 } 98 } 99 100 func testUCNTable(t *testing.T, tab []rune, fOk, fOther func(rune) bool, fcategory func(rune) bool, tag string) { 101 m := map[rune]struct{}{} 102 for i := 0; i < len(tab); i += 2 { 103 l, h := tab[i], tab[i+1] 104 if h == 0 { 105 h = l 106 } 107 for r := l; r <= h; r++ { 108 m[r] = struct{}{} 109 } 110 } 111 for r := rune(0); r < 0xffff; r++ { 112 _, ok := m[r] 113 if g, e := fOk(r), ok; g != e { 114 t.Errorf("%#04x %v %v", r, g, e) 115 } 116 117 if ok { 118 if g, e := fOther(r), false; g != e { 119 t.Errorf("%#04x %v %v", r, g, e) 120 } 121 } 122 } 123 } 124 125 func TestUCNDigitsTable(t *testing.T) { 126 tab := []rune{ 127 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 128 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 129 0x0D66, 0x0D6F, 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F33, 130 } 131 testUCNTable(t, tab, isUCNDigit, isUCNNonDigit, unicode.IsDigit, "unicode.IsDigit") 132 } 133 134 func TestUCNNonDigitsTable(t *testing.T) { 135 tab := []rune{ 136 0x00AA, 0x0000, 0x00B5, 0x0000, 0x00B7, 0x0000, 0x00BA, 0x0000, 0x00C0, 0x00D6, 137 0x00D8, 0x00F6, 0x00F8, 0x01F5, 0x01FA, 0x0217, 0x0250, 0x02A8, 0x02B0, 0x02B8, 138 0x02BB, 0x0000, 0x02BD, 0x02C1, 0x02D0, 0x02D1, 0x02E0, 0x02E4, 0x037A, 0x0000, 139 0x0386, 0x0000, 0x0388, 0x038A, 0x038C, 0x0000, 0x038E, 0x03A1, 0x03A3, 0x03CE, 140 0x03D0, 0x03D6, 0x03DA, 0x0000, 0x03DC, 0x0000, 0x03DE, 0x0000, 0x03E0, 0x0000, 141 0x03E2, 0x03F3, 0x0401, 0x040C, 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 142 0x0490, 0x04C4, 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5, 143 0x04F8, 0x04F9, 0x0531, 0x0556, 0x0559, 0x0000, 0x0561, 0x0587, 0x05B0, 0x05B9, 144 0x05F0, 0x05F2, 0x0621, 0x063A, 0x0640, 0x0652, 0x0670, 0x06B7, 0x06BA, 0x06BE, 145 0x06C0, 0x06CE, 0x06D0, 0x06DC, 0x06E5, 0x06E8, 0x06EA, 0x06ED, 0x0901, 0x0903, 146 0x0905, 0x0939, 0x093D, 0x0000, 0x093E, 0x094D, 0x0950, 0x0952, 0x0958, 0x0963, 147 0x0981, 0x0983, 0x0985, 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0, 148 0x09B2, 0x0000, 0x09B6, 0x09B9, 0x09BE, 0x09C4, 0x09C7, 0x09C8, 0x09CB, 0x09CD, 149 0x09DC, 0x09DD, 0x09DF, 0x09E3, 0x09F0, 0x09F1, 0x0A02, 0x0000, 0x0A05, 0x0A0A, 150 0x0A0F, 0x0A10, 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36, 151 0x0A38, 0x0A39, 0x0A3E, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4D, 0x0A59, 0x0A5C, 152 0x0A5E, 0x0000, 0x0A74, 0x0000, 0x0A81, 0x0A83, 0x0A85, 0x0A8B, 0x0A8D, 0x0000, 153 0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9, 154 0x0ABD, 0x0AC5, 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0AD0, 0x0000, 0x0AE0, 0x0000, 155 0x0B01, 0x0B03, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 0x0B2A, 0x0B30, 156 0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B3D, 0x0000, 0x0B3E, 0x0B43, 0x0B47, 0x0B48, 157 0x0B4B, 0x0B4D, 0x0B5C, 0x0B5D, 0x0B5F, 0x0B61, 0x0B82, 0x0B83, 0x0B85, 0x0B8A, 158 0x0B8E, 0x0B90, 0x0B92, 0x0B95, 0x0B99, 0x0B9A, 0x0B9C, 0x0000, 0x0B9E, 0x0B9F, 159 0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA, 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0BBE, 0x0BC2, 160 0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10, 161 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C3E, 0x0C44, 0x0C46, 0x0C48, 162 0x0C4A, 0x0C4D, 0x0C60, 0x0C61, 0x0C82, 0x0C83, 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 163 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, 0x0CB5, 0x0CB9, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8, 164 0x0CCA, 0x0CCD, 0x0CDE, 0x0000, 0x0CE0, 0x0CE1, 0x0D02, 0x0D03, 0x0D05, 0x0D0C, 165 0x0D0E, 0x0D10, 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D3E, 0x0D43, 0x0D46, 0x0D48, 166 0x0D4A, 0x0D4D, 0x0D60, 0x0D61, 0x0E01, 0x0E3A, 167 168 // In [0], Annex D, Thai [0x0E40, 0x0E5B] overlaps with digits 169 // [0x0E50, 0x0E59]. Exclude them. 170 0x0E40, 0x0E4F, 171 0x0E5A, 0x0E5B, 172 173 0x0E81, 0x0E82, 174 0x0E84, 0x0000, 0x0E87, 0x0E88, 0x0E8A, 0x0000, 0x0E8D, 0x0000, 0x0E94, 0x0E97, 175 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EA5, 0x0000, 0x0EA7, 0x0000, 0x0EAA, 0x0EAB, 176 0x0EAD, 0x0EAE, 0x0EB0, 0x0EB9, 0x0EBB, 0x0EBD, 0x0EC0, 0x0EC4, 0x0EC6, 0x0000, 177 0x0EC8, 0x0ECD, 0x0EDC, 0x0EDD, 0x0F00, 0x0000, 0x0F18, 0x0F19, 0x0F35, 0x0000, 178 0x0F37, 0x0000, 0x0F39, 0x0000, 0x0F3E, 0x0F47, 0x0F49, 0x0F69, 0x0F71, 0x0F84, 179 0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F97, 0x0000, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7, 180 0x0FB9, 0x0000, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9, 181 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 0x1F50, 0x1F57, 182 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 183 0x1FB6, 0x1FBC, 0x1FBE, 0x0000, 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 184 0x1FD6, 0x1FDB, 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x203F, 0x2040, 185 0x207F, 0x0000, 0x2102, 0x0000, 0x2107, 0x0000, 0x210A, 0x2113, 0x2115, 0x0000, 186 0x2118, 0x211D, 0x2124, 0x0000, 0x2126, 0x0000, 0x2128, 0x0000, 0x212A, 0x2131, 187 0x2133, 0x2138, 0x2160, 0x2182, 0x3005, 0x3007, 0x3021, 0x3029, 0x3041, 0x3093, 188 0x309B, 0x309C, 0x30A1, 0x30F6, 0x30FB, 0x30FC, 0x3105, 0x312C, 0x4E00, 0x9FA5, 189 0xAC00, 0xD7A3, 190 } 191 testUCNTable(t, tab, isUCNNonDigit, isUCNDigit, unicode.IsLetter, "unicode.IsLetter") 192 } 193 194 func charStr(c rune) string { return yySymName(int(c)) } 195 196 func charsStr(chars []lex.Char, delta token.Pos) (a []string) { 197 for _, v := range chars { 198 a = append(a, fmt.Sprintf("{%s %d}", charStr(v.Rune), v.Pos()-delta)) 199 } 200 return a 201 } 202 203 type x []struct { 204 c rune 205 pos token.Pos 206 } 207 208 type lexerTests []struct { 209 src string 210 chars x 211 } 212 213 func testLexer(t *testing.T, newLexer func(i int, src string) (*lexer, error), tab lexerTests) { 214 nextTest: 215 for ti, test := range tab { 216 lx, err := newLexer(ti, test.src) 217 if err != nil { 218 t.Fatal(err) 219 } 220 221 delta := token.Pos(lx.File.Base() - 1) 222 var chars []lex.Char 223 var c lex.Char 224 var lval yySymType 225 for i := 0; c.Rune >= 0 && i < len(test.src)+2; i++ { 226 lx.Lex(&lval) 227 c = lval.Token.Char 228 chars = append(chars, c) 229 } 230 if c.Rune >= 0 { 231 t.Errorf("%d: scanner stall %v", ti, charsStr(chars, delta)) 232 continue 233 } 234 235 if g, e := lx.error(), error(nil); g != e { 236 t.Errorf("%d: lx.err %v %v %v", ti, g, e, charsStr(chars, delta)) 237 continue 238 } 239 240 if g, e := len(chars), len(test.chars); g != e { 241 t.Errorf("%d: len(chars) %v %v %v", ti, g, e, charsStr(chars, delta)) 242 continue 243 } 244 245 for i, c := range chars { 246 c = chars[i] 247 e := test.chars[i] 248 g := c.Rune 249 if e := e.c; g != e { 250 t.Errorf("%d: c[%d] %v %v %v", ti, i, charStr(g), charStr(e), charsStr(chars, delta)) 251 continue nextTest 252 } 253 254 if g, e := c.Pos()-delta, e.pos; g != e { 255 t.Errorf("%d: pos[%d] %v %v %v", ti, i, g, e, charsStr(chars, delta)) 256 continue nextTest 257 } 258 } 259 } 260 } 261 262 func TestLexer(t *testing.T) { 263 ctx, err := newContext(&Tweaks{}) 264 if err != nil { 265 t.Fatal(err) 266 } 267 268 testLexer( 269 t, 270 func(i int, src string) (*lexer, error) { 271 return newLexer(ctx, fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src)) 272 }, 273 lexerTests{ 274 {"", x{{-1, 1}}}, 275 {"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}}, 276 {"%:%:", x{{PPPASTE, 1}, {-1, 5}}}, 277 {"%>", x{{'}', 1}, {-1, 3}}}, 278 {"0", x{{INTCONST, 1}, {-1, 2}}}, 279 {"01", x{{INTCONST, 1}, {-1, 3}}}, 280 {"0??/1\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}}, 281 {"0??/1\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}}, 282 {"0??/\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {-1, 6}}}, 283 {"0??/\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 284 {"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}}, 285 {"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}}, 286 {"0\\\n", x{{INTCONST, 1}, {-1, 4}}}, 287 {"0\\\n2", x{{INTCONST, 1}, {-1, 5}}}, 288 {"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}}, 289 {"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}}, 290 {":>", x{{']', 1}, {-1, 3}}}, 291 {"<%", x{{'{', 1}, {-1, 3}}}, 292 {"<:", x{{'[', 1}, {-1, 3}}}, 293 {"??!", x{{'?', 1}, {'?', 2}, {'!', 3}, {-1, 4}}}, 294 {"??!0", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 5}}}, 295 {"??!01", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 6}}}, 296 {"??!=", x{{'?', 1}, {'?', 2}, {NEQ, 3}, {-1, 5}}}, 297 {"??'", x{{'?', 1}, {'?', 2}, {'\'', 3}, {-1, 4}}}, 298 {"??(", x{{'?', 1}, {'?', 2}, {'(', 3}, {-1, 4}}}, 299 {"??)", x{{'?', 1}, {'?', 2}, {')', 3}, {-1, 4}}}, 300 {"??-", x{{'?', 1}, {'?', 2}, {'-', 3}, {-1, 4}}}, 301 {"??/", x{{'?', 1}, {'?', 2}, {'/', 3}, {-1, 4}}}, 302 {"??/1\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}}, 303 {"??/1\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 304 {"??/\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {-1, 5}}}, 305 {"??/\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}}, 306 {"??<", x{{'?', 1}, {'?', 2}, {'<', 3}, {-1, 4}}}, 307 {"??=??=", x{{'?', 1}, {'?', 2}, {'=', 3}, {'?', 4}, {'?', 5}, {'=', 6}, {-1, 7}}}, 308 {"??>", x{{'?', 1}, {'?', 2}, {'>', 3}, {-1, 4}}}, 309 {"???!", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {-1, 5}}}, 310 {"???!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {INTCONST, 5}, {-1, 6}}}, 311 {"???/\n2", x{{'?', 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 312 {"????!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}}, 313 {"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}}, 314 {"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'?', 5}, {'?', 6}, {'!', 7}, {INTCONST, 8}, {-1, 9}}}, 315 {"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}}, 316 {"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'?', 4}, {'?', 5}, {'!', 6}, {INTCONST, 7}, {-1, 8}}}, 317 {"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}}, 318 {"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}}, 319 {"@", x{{'@', 1}, {-1, 2}}}, 320 {"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}}, 321 {"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}}, 322 {"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}}, 323 {"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}}, 324 {"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}}, 325 {"@??=", x{{'@', 1}, {'?', 2}, {'?', 3}, {'=', 4}, {-1, 5}}}, 326 {"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}}, 327 {"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}}, 328 {"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}}, 329 {"\\\n", x{{-1, 3}}}, 330 {"\\\n2", x{{INTCONST, 3}, {-1, 4}}}, 331 {"\\\r\n", x{{-1, 4}}}, 332 {"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}}, 333 {"\r", x{{-1, 2}}}, 334 {"\r0", x{{INTCONST, 2}, {-1, 3}}}, 335 {"\r01", x{{INTCONST, 2}, {-1, 4}}}, 336 {"\x00", x{{0, 1}, {-1, 2}}}, 337 {"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}}, 338 }, 339 ) 340 } 341 342 func TestLexerTrigraphs(t *testing.T) { 343 ctx, err := newContext(&Tweaks{EnableTrigraphs: true}) 344 if err != nil { 345 t.Fatal(err) 346 } 347 348 testLexer( 349 t, 350 func(i int, src string) (*lexer, error) { 351 return newLexer(ctx, fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src)) 352 }, 353 lexerTests{ 354 {"", x{{-1, 1}}}, 355 {"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}}, 356 {"%:%:", x{{PPPASTE, 1}, {-1, 5}}}, 357 {"%>", x{{'}', 1}, {-1, 3}}}, 358 {"0", x{{INTCONST, 1}, {-1, 2}}}, 359 {"01", x{{INTCONST, 1}, {-1, 3}}}, 360 {"0??/1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}}, 361 {"0??/1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}}, 362 {"0??/\n", x{{INTCONST, 1}, {-1, 6}}}, 363 {"0??/\n2", x{{INTCONST, 1}, {-1, 7}}}, 364 {"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}}, 365 {"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}}, 366 {"0\\\n", x{{INTCONST, 1}, {-1, 4}}}, 367 {"0\\\n2", x{{INTCONST, 1}, {-1, 5}}}, 368 {"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}}, 369 {"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}}, 370 {":>", x{{']', 1}, {-1, 3}}}, 371 {"<%", x{{'{', 1}, {-1, 3}}}, 372 {"<:", x{{'[', 1}, {-1, 3}}}, 373 {"??!", x{{'|', 1}, {-1, 4}}}, 374 {"??!0", x{{'|', 1}, {INTCONST, 4}, {-1, 5}}}, 375 {"??!01", x{{'|', 1}, {INTCONST, 4}, {-1, 6}}}, 376 {"??!=", x{{ORASSIGN, 1}, {-1, 5}}}, 377 {"??'", x{{'^', 1}, {-1, 4}}}, 378 {"??(", x{{'[', 1}, {-1, 4}}}, 379 {"??)", x{{']', 1}, {-1, 4}}}, 380 {"??-", x{{'~', 1}, {-1, 4}}}, 381 {"??/", x{{'\\', 1}, {-1, 4}}}, 382 {"??/1\n", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}}, 383 {"??/1\n2", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 384 {"??/\n", x{{-1, 5}}}, 385 {"??/\n2", x{{INTCONST, 5}, {-1, 6}}}, 386 {"??<", x{{'{', 1}, {-1, 4}}}, 387 {"??=??=", x{{PPPASTE, 1}, {-1, 7}}}, 388 {"??>", x{{'}', 1}, {-1, 4}}}, 389 {"???!", x{{'?', 1}, {'|', 2}, {-1, 5}}}, 390 {"???!0", x{{'?', 1}, {'|', 2}, {INTCONST, 5}, {-1, 6}}}, 391 {"???/\n2", x{{'?', 1}, {INTCONST, 6}, {-1, 7}}}, 392 {"????!0", x{{'?', 1}, {'?', 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}}, 393 {"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}}, 394 {"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'|', 5}, {INTCONST, 8}, {-1, 9}}}, 395 {"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}}, 396 {"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'|', 4}, {INTCONST, 7}, {-1, 8}}}, 397 {"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}}, 398 {"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}}, 399 {"@", x{{'@', 1}, {-1, 2}}}, 400 {"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}}, 401 {"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}}, 402 {"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}}, 403 {"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}}, 404 {"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}}, 405 {"@??=", x{{'@', 1}, {'#', 2}, {-1, 5}}}, 406 {"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}}, 407 {"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}}, 408 {"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}}, 409 {"\\\n", x{{-1, 3}}}, 410 {"\\\n2", x{{INTCONST, 3}, {-1, 4}}}, 411 {"\\\r\n", x{{-1, 4}}}, 412 {"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}}, 413 {"\r", x{{-1, 2}}}, 414 {"\r0", x{{INTCONST, 2}, {-1, 3}}}, 415 {"\r01", x{{INTCONST, 2}, {-1, 4}}}, 416 {"\x00", x{{0, 1}, {-1, 2}}}, 417 {"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}}, 418 }, 419 ) 420 } 421 422 func exampleAST(rule int, src string) interface{} { 423 ctx, err := newContext(&Tweaks{ 424 EnableAnonymousStructFields: true, 425 EnableEmptyStructs: true, 426 EnableOmitFuncDeclSpec: true, 427 }) 428 if err != nil { 429 return fmt.Sprintf("TODO: %v", err) //TODOOK 430 } 431 432 ctx.exampleRule = rule 433 src = strings.TrimSpace(src) 434 r, n := utf8.DecodeRuneInString(src) 435 src = src[n:] 436 l, err := newLexer(ctx, fmt.Sprintf("example%v.c", rule), len(src), strings.NewReader(src)) 437 if err != nil { 438 return fmt.Sprintf("TODO: %v", err) //TODOOK 439 } 440 441 l.unget(cppToken{Token: xc.Token{Char: lex.Char{Rune: r}}}) 442 yyParse(l) 443 if err := ctx.error(); err != nil { 444 return fmt.Sprintf("TODO: %v", err) //TODOOK 445 } 446 447 if ctx.exampleAST == nil { 448 return "TODO: nil" //TODOOK 449 } 450 451 return ctx.exampleAST 452 } 453 454 func testCPPParseSource(ctx *context, src Source) (*cpp, tokenReader, error) { 455 if ctx == nil { 456 var err error 457 if ctx, err = newContext(&Tweaks{}); err != nil { 458 return nil, nil, err 459 } 460 } 461 462 c := newCPP(ctx) 463 r, err := c.parse(src) 464 if err != nil { 465 return nil, nil, err 466 } 467 468 return c, r, nil 469 } 470 471 func testCPPParseFile(ctx *context, nm string) (*cpp, tokenReader, error) { 472 return testCPPParseSource(ctx, MustFileSource(nm)) 473 } 474 475 func testCPPParseString(ctx *context, name, src string) (*cpp, tokenReader, error) { 476 return testCPPParseSource(ctx, NewStringSource(name, src)) 477 } 478 479 func TestCPPParse0(t *testing.T) { 480 ctx, err := newContext(&Tweaks{}) 481 if err != nil { 482 t.Fatal(err) 483 } 484 485 for i, v := range []string{ 486 "", 487 "\n", 488 "foo\n", 489 `#if 1 490 #endif 491 `, 492 `#if 1 493 # /* foo */ 494 #endif 495 `, 496 } { 497 if _, _, err := testCPPParseString(ctx, "test", v); err != nil { 498 t.Error(i, err) 499 } 500 } 501 } 502 503 func TestCPPExpand(t *testing.T) { 504 var re *regexp.Regexp 505 if s := *oRE; s != "" { 506 re = regexp.MustCompile(s) 507 } 508 509 model, err := NewModel() 510 if err != nil { 511 t.Fatal(err) 512 } 513 514 if err := filepath.Walk(filepath.FromSlash("testdata/cpp-expand/"), func(path string, info os.FileInfo, err error) error { 515 if err != nil { 516 return err 517 } 518 519 if info.IsDir() || (!strings.HasSuffix(path, ".c") && !strings.HasSuffix(path, ".h")) { 520 return nil 521 } 522 523 if re != nil && !re.MatchString(path) { 524 return nil 525 } 526 527 t.Log(path) 528 ctx, err := newContext(&Tweaks{ 529 cppExpandTest: true, 530 }) 531 if err != nil { 532 t.Fatal(err) 533 } 534 535 ctx.model = model 536 b, err := ioutil.ReadFile(path) 537 if err != nil { 538 t.Fatal(err) 539 } 540 541 c, r, err := testCPPParseFile(ctx, path) 542 if err != nil { 543 t.Fatal(ErrString(err)) 544 } 545 546 var tb tokenBuffer 547 if err := c.eval(r, &tb); err != nil { 548 t.Fatal(ErrString(err)) 549 } 550 551 switch { 552 case strings.Contains(filepath.ToSlash(path), "/mustfail/"): 553 err := c.error() 554 if err != nil { 555 t.Logf(ErrString(err)) 556 return nil 557 } 558 559 t.Fatalf("unexpected success: %s", path) 560 default: 561 if err := c.error(); err != nil { 562 t.Fatal(ErrString(err)) 563 } 564 } 565 566 var a []string 567 for { 568 t := tb.read() 569 if t.Rune == ccEOF { 570 break 571 } 572 573 a = append(a, TokSrc(t.Token)) 574 } 575 s := strings.Join(a, "") 576 exp, err := ioutil.ReadFile(path + ".expect") 577 if err != nil { 578 t.Fatal(err) 579 } 580 581 if g, e := s, string(exp); g != e { 582 t.Errorf("\n---- src %s\n%s---- got\n%s---- exp %s\n%s", path, b, g, path+".expect", e) 583 } 584 return nil 585 }); err != nil { 586 t.Fatal(err) 587 } 588 } 589 590 func (b *tokenBuffer) WriteTo(fset *token.FileSet, w io.Writer) { 591 var lpos token.Position 592 for { 593 t := b.read() 594 if t.Rune == ccEOF { 595 return 596 } 597 598 pos := fset.Position(t.Pos()) 599 if pos.Filename != lpos.Filename { 600 fmt.Fprintf(w, "# %d %v\n", pos.Line, pos.Filename) 601 } 602 lpos = pos 603 w.Write([]byte(TokSrc(t.Token))) 604 } 605 } 606 607 func (b *tokenBuffer) Bytes(fset *token.FileSet) []byte { 608 var buf bytes.Buffer 609 b.WriteTo(fset, &buf) 610 return buf.Bytes() 611 } 612 613 func TestPreprocessSQLite(t *testing.T) { 614 model, err := NewModel() 615 if err != nil { 616 t.Fatal(err) 617 } 618 619 ctx, err := newContext(&Tweaks{}) 620 if err != nil { 621 t.Fatal(err) 622 } 623 624 ctx.model = model 625 cpp := newCPP(ctx) 626 cpp.includePaths = []string{"@"} 627 cpp.sysIncludePaths = searchPaths 628 r, err := cpp.parse(MustBuiltin(), MustFileSource(sqlite3c)) 629 if err != nil { 630 t.Fatalf("%v: %v", sqlite3c, err) 631 } 632 633 var w tokenBuffer 634 if err := cpp.eval(r, &w); err != nil { 635 t.Fatalf("%v: %v", sqlite3c, ErrString(err)) 636 } 637 638 if err := cpp.error(); err != nil { 639 t.Fatalf("%v: %v", sqlite3c, ErrString(err)) 640 } 641 642 if n := len(cpp.lx.ungetBuffer); n != 0 { 643 t.Fatal(n) 644 } 645 } 646 647 func TestParseSQLite(t *testing.T) { 648 model, err := NewModel() 649 if err != nil { 650 t.Fatal(err) 651 } 652 653 ctx, err := newContext(&Tweaks{ 654 EnableAnonymousStructFields: true, 655 EnableEmptyStructs: true, 656 }) 657 if err != nil { 658 t.Fatal(err) 659 } 660 661 ctx.model = model 662 ctx.includePaths = []string{"@"} 663 ctx.sysIncludePaths = searchPaths 664 if _, err := ctx.parse([]Source{MustBuiltin(), MustFileSource(sqlite3c)}); err != nil { 665 t.Fatalf("%v", ErrString(err)) 666 } 667 } 668 669 func TestFunc(t *testing.T) { 670 model, err := NewModel() 671 if err != nil { 672 t.Fatal(err) 673 } 674 675 ctx, err := newContext(&Tweaks{InjectFinalNL: true}) 676 if err != nil { 677 t.Fatal(err) 678 } 679 680 ctx.model = model 681 tu, err := ctx.parse( 682 []Source{NewStringSource("testfunc.c", `int (*foo(char bar))(double baz){}`)}, 683 ) 684 if err != nil { 685 t.Fatalf("%v", ErrString(err)) 686 } 687 688 if err := tu.ExternalDeclarationList.check(ctx); err != nil { 689 t.Fatal(err) 690 } 691 692 if err := ctx.error(); err != nil { 693 t.Fatal(err) 694 } 695 696 fileScope := ctx.scope 697 n := fileScope.LookupIdent(dict.SID("foo")) 698 d, ok := n.(*Declarator) 699 if !ok { 700 t.Fatalf("%T", n) 701 } 702 703 fd := d 704 if g, e := d.Type.String(), "function (char) returning pointer to function (double) returning int"; g != e { 705 t.Fatalf("got %q\nexp %q", g, e) 706 } 707 708 if g, e := fmt.Sprint(d.Type.(*FunctionType).Params), "[char]"; g != e { 709 t.Fatalf("got %q\nexp %q", g, e) 710 } 711 712 fnScope := tu.ExternalDeclarationList.ExternalDeclaration.FunctionDefinition.FunctionBody.CompoundStmt.scope 713 n = fnScope.LookupIdent(dict.SID("bar")) 714 if d, ok = n.(*Declarator); !ok { 715 t.Fatalf("%T", n) 716 } 717 718 if g, e := fmt.Sprint(d.Type), "char"; g != e { 719 t.Fatalf("got %q\nexp %q", g, e) 720 } 721 722 names := fd.ParameterNames() 723 if g, e := len(names), 1; g != e { 724 t.Fatal(g, e) 725 } 726 727 if g, e := names[0], dict.SID("bar"); g != e { 728 t.Fatal(g, e) 729 } 730 731 params := fd.Parameters 732 if g, e := len(params), 1; g != e { 733 t.Fatal(g, e) 734 } 735 736 if g, e := params[0].Name(), dict.SID("bar"); g != e { 737 t.Fatal(g, e) 738 } 739 } 740 741 func TestTypecheckSQLite(t *testing.T) { 742 if _, err := Translate( 743 &Tweaks{ 744 EnableAnonymousStructFields: true, 745 EnableEmptyStructs: true, 746 }, 747 []string{"@"}, 748 searchPaths, 749 MustBuiltin(), 750 MustFileSource(sqlite3c), 751 ); err != nil { 752 t.Fatal(err) 753 } 754 } 755 756 func TestTypecheckSQLiteShell(t *testing.T) { 757 if _, err := Translate( 758 &Tweaks{ 759 EnableAnonymousStructFields: true, 760 EnableEmptyStructs: true, 761 }, 762 []string{"@"}, 763 searchPaths, 764 MustBuiltin(), 765 MustCrt0(), 766 MustFileSource(shellc), 767 ); err != nil { 768 t.Fatal(err) 769 } 770 } 771 772 func TestTypecheckTCCTests(t *testing.T) { 773 blacklist := map[string]struct{}{ 774 "34_array_assignment.c": {}, // gcc: main.c:16:6: error: incompatible types when assigning to type ‘int[4]’ from type ‘int *’ 775 "46_grep.c": {}, // gcc: 46_grep.c:489:12: error: ‘documentation’ undeclared (first use in this function) 776 } 777 m, err := filepath.Glob("testdata/tcc-0.9.26/tests/tests2/*.c") 778 if err != nil { 779 t.Fatal(err) 780 } 781 782 for _, pth := range m { 783 if _, ok := blacklist[filepath.Base(pth)]; ok { 784 continue 785 } 786 787 if _, err := Translate( 788 &Tweaks{ 789 EnableBinaryLiterals: true, 790 EnableEmptyStructs: true, 791 EnableImplicitDeclarations: true, 792 EnableReturnExprInVoidFunc: true, 793 EnableAnonymousStructFields: true, 794 }, 795 []string{"@"}, 796 searchPaths, 797 MustBuiltin(), 798 MustCrt0(), 799 MustFileSource(pth), 800 ); err != nil { 801 t.Fatal(ErrString(err)) 802 } 803 } 804 } 805 806 func TestParseJhjourdan(t *testing.T) { 807 var blacklist = map[string]struct{}{ 808 "bitfield_declaration_ambiguity.fail.c": {}, // fails only during typecheck 809 } 810 811 var re *regexp.Regexp 812 if s := *oRE; s != "" { 813 re = regexp.MustCompile(s) 814 } 815 816 model, err := NewModel() 817 if err != nil { 818 t.Fatal(err) 819 } 820 821 var ok, n int 822 if err := filepath.Walk(filepath.FromSlash("testdata/jhjourdan/"), func(path string, info os.FileInfo, err error) error { 823 if err != nil { 824 return err 825 } 826 827 if info.IsDir() || !strings.HasSuffix(path, ".c") { 828 return nil 829 } 830 831 if _, ok := blacklist[filepath.Base(path)]; ok { 832 return nil 833 } 834 835 if re != nil && !re.MatchString(path) { 836 return nil 837 } 838 839 ctx, err := newContext(&Tweaks{}) 840 if err != nil { 841 t.Fatal(err) 842 } 843 844 ctx.model = model 845 ctx.includePaths = []string{"@"} 846 ctx.sysIncludePaths = searchPaths 847 n++ 848 shouldFail := strings.HasSuffix(path, ".fail.c") 849 //dbg("", path) 850 switch _, err := ctx.parse([]Source{MustBuiltin(), MustFileSource(path)}); { 851 case err != nil: 852 if !shouldFail { 853 t.Errorf("%v", ErrString(err)) 854 return nil 855 } 856 default: 857 if shouldFail { 858 t.Errorf("%v: unexpected success", path) 859 return nil 860 } 861 } 862 863 ok++ 864 return nil 865 }); err != nil { 866 t.Fatal(err) 867 } 868 t.Logf("jhjourdan parse\tok %v n %v\n", ok, n) 869 } 870 871 func TestTypecheckJhjourdan(t *testing.T) { 872 var blacklist = map[string]struct{}{ 873 "bitfield_declaration_ambiguity.c": {}, //TODO 874 "dangling_else_lookahead.if.c": {}, //TODO 875 "designator.c": {}, //TODO 876 "expressions.c": {}, //TODO 877 "function_parameter_scope_extends.c": {}, //TODO 878 "if_scopes.c": {}, //TODO 879 "loop_scopes.c": {}, //TODO 880 } 881 882 var re *regexp.Regexp 883 if s := *oRE; s != "" { 884 re = regexp.MustCompile(s) 885 } 886 887 var ok, n int 888 if err := filepath.Walk(filepath.FromSlash("testdata/jhjourdan/"), func(path string, info os.FileInfo, err error) error { 889 if err != nil { 890 return err 891 } 892 893 if info.IsDir() || !strings.HasSuffix(path, ".c") { 894 return nil 895 } 896 897 if _, ok := blacklist[filepath.Base(path)]; ok { 898 return nil 899 } 900 901 if re != nil && !re.MatchString(path) { 902 return nil 903 } 904 905 n++ 906 shouldFail := strings.HasSuffix(path, ".fail.c") 907 _, err = Translate( 908 &Tweaks{}, 909 []string{"@"}, 910 searchPaths, 911 MustBuiltin(), 912 MustFileSource(path), 913 ) 914 switch { 915 case err != nil: 916 if !shouldFail { 917 dbg("%q, err: %v, shouldFail: %v", path, err, shouldFail) 918 t.Errorf("%v", ErrString(err)) 919 return nil 920 } 921 default: 922 if shouldFail { 923 dbg("%q, err: %v, shouldFail: %v", path, err, shouldFail) 924 t.Errorf("%v: unexpected success", path) 925 return nil 926 } 927 } 928 929 ok++ 930 return nil 931 }); err != nil { 932 t.Fatal(err) 933 } 934 t.Logf("jhjourdan typecheck\tok %v n %v\n", ok, n) 935 }