modernc.org/cc@v1.0.1/cc.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 //go:generate go run generate.go 6 //go:generate golex -o trigraphs.go trigraphs.l 7 //go:generate golex -o scanner.go scanner.l 8 //go:generate stringer -type Kind 9 //go:generate stringer -type Linkage 10 //go:generate stringer -type Namespace 11 //go:generate stringer -type Scope 12 //go:generate go run generate.go -2 13 14 // Package cc is a C99 compiler front end. 15 // 16 // Changelog 17 // 18 // 2020-07-13 This package is no longer maintained. Please see the v3 version at 19 // 20 // https://modernc.org/cc/v3 21 // 22 // Links 23 // 24 // Referenced from elsewhere: 25 // 26 // [0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 27 // [1]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1406.pdf 28 // [2]: https://github.com/rsc/c2go/blob/fc8cbfad5a47373828c81c7a56cccab8b221d310/cc/cc.y 29 // [3]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html 30 package cc // import "modernc.org/cc" 31 32 import ( 33 "bufio" 34 "bytes" 35 "fmt" 36 "go/token" 37 "os" 38 "os/exec" 39 "runtime" 40 "strings" 41 42 "modernc.org/golex/lex" 43 "modernc.org/mathutil" 44 "modernc.org/strutil" 45 "modernc.org/xc" 46 ) 47 48 const ( 49 fakeTime = "__TESTING_TIME__" 50 51 gccPredefine = ` 52 #define __PRETTY_FUNCTION__ __func__ 53 #define __asm asm 54 #define __attribute(x) 55 #define __attribute__(x) 56 #define __builtin___memcpy_chk(x, y, z, t) __BUILTIN___MEMCPY_CHK() 57 #define __builtin___memset_chk(x, y, z, ...) __BUILTIN___MEMSET_CHK() 58 #define __builtin_alloca(x) __BUILTIN_ALLOCA() 59 #define __builtin_classify_type(x) __BUILTIN_CLASSIFY_TYPE() 60 #define __builtin_constant_p(exp) __BUILTIN_CONSTANT_P() 61 #define __builtin_isgreater(x, y) __BUILTIN_ISGREATER() 62 #define __builtin_isless(x, y) __BUILTIN_ISLESS() 63 #define __builtin_isunordered(x, y) __BUILTIN_ISUNORDERED() 64 #define __builtin_longjmp(x, y) __BUILTIN_LONGJMP() 65 #define __builtin_malloc(x) __BUILTIN_MALLOC() 66 #define __builtin_memmove(x, y, z) __BUILTIN_MEMMOVE() 67 #define __builtin_mempcpy(x, y, z) __BUILTIN_MEMPCPY() 68 #define __builtin_mul_overflow(a, b, c) __BUILTIN_MUL_OVERFLOW() 69 #define __builtin_offsetof(type, member) ((%[1]v)(&((type *)0)->member)) 70 #define __builtin_signbit(x) __BUILTIN_SIGNBIT() 71 #define __builtin_va_arg(ap, type) ( *( type* )ap ) 72 #define __builtin_va_end(x) 73 #define __builtin_va_list void* 74 #define __builtin_va_start(x, y) 75 #define __complex _Complex 76 #define __complex__ _Complex 77 #define __const 78 #define __extension__ 79 #define __imag__ 80 #define __inline inline 81 #define __real(x) __REAL() 82 #define __real__ 83 #define __restrict 84 #define __sync_fetch_and_add(x, y, ...) __SYNC_FETCH_AND_ADD() 85 #define __sync_val_compare_and_swap(x, y, z, ...) __SYNC_VAL_COMPARE_AND_SWAP() 86 #define __typeof typeof 87 #define __volatile volatile 88 %[1]v __builtin_object_size (void*, int); 89 %[1]v __builtin_strlen(char*); 90 %[1]v __builtin_strspn(char*, char*); 91 _Bool __BUILTIN_MUL_OVERFLOW(); 92 char* __builtin___stpcpy_chk(char*, char*, %[1]v); 93 char* __builtin_stpcpy(char*, char*); 94 char* __builtin_strchr(char*, int); 95 char* __builtin_strcpy(char*, char*); 96 char* __builtin_strdup(char*); 97 char* __builtin_strncpy(char*, char*, %[1]v); 98 double _Complex __builtin_cpow(double _Complex, _Complex double); 99 double __REAL(); 100 double __builtin_copysign(double, double); 101 double __builtin_copysignl(long double, long double); 102 double __builtin_inff(); 103 double __builtin_modf(double, double*); 104 double __builtin_modfl(long double, long double*); 105 double __builtin_nanf(char *); 106 float _Complex __builtin_conjf(float _Complex); 107 float __builtin_ceilf(float); 108 float __builtin_copysignf(float, float); 109 float __builtin_modff(float, float*); 110 int __BUILTIN_CLASSIFY_TYPE(); 111 int __BUILTIN_CONSTANT_P(); 112 int __BUILTIN_ISGREATER(); 113 int __BUILTIN_ISLESS(); 114 int __BUILTIN_ISUNORDERED(); 115 int __BUILTIN_SIGNBIT(); 116 int __builtin___snprintf_chk (char*, %[1]v, int, %[1]v, char*, ...); 117 int __builtin___sprintf_chk (char*, int, %[1]v, char*, ...); 118 int __builtin___vsnprintf_chk (char*, %[1]v, int, %[1]v, char*, void*); 119 int __builtin___vsprintf_chk (char*, int, %[1]v, char*, void*); 120 int __builtin_abs(int); 121 int __builtin_clrsb(int); 122 int __builtin_clrsbl(long); 123 int __builtin_clrsbll(long long); 124 int __builtin_clz(unsigned int); 125 int __builtin_clzl(unsigned long); 126 int __builtin_clzll(unsigned long long); 127 int __builtin_constant_p (exp); 128 int __builtin_ctz(unsigned int x); 129 int __builtin_ctzl(unsigned long); 130 int __builtin_ctzll(unsigned long long); 131 int __builtin_ffs(int); 132 int __builtin_ffsl(long); 133 int __builtin_ffsll(long long); 134 int __builtin_isinf(double); 135 int __builtin_isinff(float); 136 int __builtin_isinfl(long double); 137 int __builtin_memcmp(void*, void*, %[1]v); 138 int __builtin_parity (unsigned); 139 int __builtin_parityl(unsigned long); 140 int __builtin_parityll (unsigned long long); 141 int __builtin_popcount (unsigned int x); 142 int __builtin_popcountl (unsigned long); 143 int __builtin_popcountll (unsigned long long); 144 int __builtin_printf(char*, ...); 145 int __builtin_puts(char*); 146 int __builtin_setjmp(void*); 147 int __builtin_strcmp(char*, char*); 148 int __builtin_strncmp(char*, char*, %[1]v); 149 long __builtin_expect(long, long); 150 long long strlen (char*); 151 unsigned __builtin_bswap32 (unsigned x); 152 unsigned long long __builtin_bswap64 (unsigned long long x); 153 unsigned short __builtin_bswap16 (unsigned short x); 154 void __BUILTIN_LONGJMP(); 155 void __SYNC_FETCH_AND_ADD(); 156 void __SYNC_VAL_COMPARE_AND_SWAP(); 157 void __builtin_abort(void); 158 void __builtin_bcopy(void*, void*, %[1]v); 159 void __builtin_bzero(void*, %[1]v); 160 void __builtin_prefetch (void*, ...); 161 void __builtin_stack_restore(void*); 162 void __builtin_trap (void); 163 void __builtin_unreachable (void); 164 void __builtin_unwind_init(); 165 void __builtin_va_arg_pack (); 166 void __builtin_va_copy(void*, void*); 167 void* __BUILTIN_ALLOCA(); 168 void* __BUILTIN_MALLOC(); 169 void* __BUILTIN_MEMMOVE(); 170 void* __BUILTIN_MEMPCPY(); 171 void* __BUILTIN___MEMCPY_CHK(); 172 void* __BUILTIN___MEMSET_CHK(); 173 void* __builtin_alloca(int); 174 void* __builtin_apply (void (*)(), void*, %[1]v); 175 void* __builtin_apply_args(); 176 void* __builtin_extract_return_addr(void *); 177 void* __builtin_frame_address(unsigned int); 178 void* __builtin_memcpy(void*, void*, long long); 179 void* __builtin_memset(void*, int, long long); 180 void* __builtin_return_address (unsigned int); 181 void* __builtin_stack_save(); 182 void* memcpy(void*, void*, long long); 183 void* memset(void*, int, long long); 184 ` 185 ) 186 187 // ImportPath returns the import path of this package or an error, if any. 188 func ImportPath() (string, error) { return strutil.ImportPath() } 189 190 // HostConfig executes HostCppConfig with the cpp argument set to "cpp". For 191 // more info please see the documentation of HostCppConfig. 192 func HostConfig(opts ...string) (predefined string, includePaths, sysIncludePaths []string, err error) { 193 return HostCppConfig("cpp", opts...) 194 } 195 196 // HostCppConfig returns the system C preprocessor configuration, or an error, 197 // if any. The configuration is obtained by running the cpp command. For the 198 // predefined macros list the '-dM' options is added. For the include paths 199 // lists, the option '-v' is added and the output is parsed to extract the 200 // "..." include and <...> include paths. To add any other options to cpp, list 201 // them in opts. 202 // 203 // The function relies on a POSIX compatible C preprocessor installed. 204 // Execution of HostConfig is not free, so caching the results is recommended 205 // whenever possible. 206 func HostCppConfig(cpp string, opts ...string) (predefined string, includePaths, sysIncludePaths []string, err error) { 207 args := append(append([]string{"-dM"}, opts...), os.DevNull) 208 // cross-compile e.g. win64 -> win32 209 if runtime.GOARCH == "386" { 210 args = append(args, "-m32") 211 } 212 pre, err := exec.Command(cpp, args...).Output() 213 if err != nil { 214 return "", nil, nil, err 215 } 216 217 args = append(append([]string{"-v"}, opts...), os.DevNull) 218 out, err := exec.Command(cpp, args...).CombinedOutput() 219 if err != nil { 220 return "", nil, nil, err 221 } 222 223 sep := "\n" 224 if runtime.GOOS == "windows" { 225 sep = "\r\n" 226 } 227 228 a := strings.Split(string(out), sep) 229 for i := 0; i < len(a); { 230 switch a[i] { 231 case "#include \"...\" search starts here:": 232 loop: 233 for i = i + 1; i < len(a); { 234 switch v := a[i]; { 235 case strings.HasPrefix(v, "#") || v == "End of search list.": 236 break loop 237 default: 238 includePaths = append(includePaths, strings.TrimSpace(v)) 239 i++ 240 } 241 } 242 case "#include <...> search starts here:": 243 for i = i + 1; i < len(a); { 244 switch v := a[i]; { 245 case strings.HasPrefix(v, "#") || v == "End of search list.": 246 return string(pre), includePaths, sysIncludePaths, nil 247 default: 248 sysIncludePaths = append(sysIncludePaths, strings.TrimSpace(v)) 249 i++ 250 } 251 } 252 default: 253 i++ 254 } 255 } 256 return "", nil, nil, fmt.Errorf("failed parsing %s -v output", cpp) 257 } 258 259 type tweaks struct { 260 allowCompatibleTypedefRedefinitions bool // typedef int foo; typedef int foo; 261 comments map[token.Pos]int // 262 devTest bool // 263 disablePredefinedLineMacro bool // __LINE__ will not expand. 264 enableAlignof bool // 265 enableAlternateKeywords bool // __asm__ etc. 266 enableAnonymousStructFields bool // 267 enableAsm bool // 268 enableBuiltinClassifyType bool // __builtin_classify_type(expr) 269 enableBuiltinConstantP bool // __builtin_constant_p(expr) 270 enableComputedGotos bool // var = &&label; goto *var; 271 enableDefineOmitCommaBeforeDDD bool // #define foo(a, b...) 272 enableDlrInIdentifiers bool // foo$bar 273 enableEmptyDeclarations bool // ; // C++11 274 enableEmptyDefine bool // #define 275 enableEmptyStructs bool // struct foo {}; 276 enableImaginarySuffix bool // 4.2i 277 enableImplicitFuncDef bool // int f() { return g(); } int g() { return 42; } 278 enableImplicitIntType bool // eg. 'static i;' is the same as 'static int i;'. 279 enableIncludeNext bool // 280 enableLegacyDesignators bool // { a: 42 } 281 enableNonConstStaticInitExpressions bool // static int *p = &i; 282 enableNoreturn bool // 283 enableOmitConditionalOperand bool // x ? : y == x ? x : y 284 enableOmitFuncArgTypes bool // f(a) becomes the same as int f(int a). 285 enableOmitFuncRetType bool // f() becomes the same as int f(). 286 enableParenCompoundStmt bool // ({...}), see [3] 287 enableStaticAssert bool // _Static_assert 288 enableTrigraphs bool // ??=define foo(bar) 289 enableTypeof bool // 290 enableUndefExtraTokens bool // #undef foo(bar) 291 enableUnsignedEnums bool // If no enum member is negative, enum type will be unsigned. 292 enableWarnings bool // #warning 293 enableWideBitFieldTypes bool // long long v : 2; 294 enableWideEnumValues bool // enum { v = X } for X wider than 32bits 295 gccEmu bool // 296 mode99c bool // 297 preprocessOnly bool // 298 } 299 300 func (t *tweaks) doGccEmu() *tweaks { 301 t.allowCompatibleTypedefRedefinitions = true 302 t.enableAlignof = true 303 t.enableAlternateKeywords = true 304 t.enableAnonymousStructFields = true 305 t.enableAsm = true 306 t.enableDefineOmitCommaBeforeDDD = true 307 t.enableDlrInIdentifiers = true 308 t.enableEmptyDefine = true 309 t.enableEmptyStructs = true 310 t.enableIncludeNext = true 311 t.enableNonConstStaticInitExpressions = true 312 t.enableNoreturn = true 313 t.enableOmitFuncRetType = true 314 t.enableStaticAssert = true 315 t.enableTypeof = true 316 t.enableUndefExtraTokens = true 317 t.enableWarnings = false 318 return t 319 } 320 321 func exampleAST(rule int, src string) interface{} { 322 report := xc.NewReport() 323 report.IgnoreErrors = true 324 r := bytes.NewBufferString(src) 325 r0, _, _ := r.ReadRune() 326 lx, err := newLexer( 327 fmt.Sprintf("example%v.c", rule), 328 len(src)+1, // Plus final injected NL 329 r, 330 report, 331 (&tweaks{gccEmu: true}).doGccEmu(), 332 ) 333 lx.Unget(lex.NewChar(token.Pos(lx.File.Base()), r0)) 334 lx.model = &Model{ // 64 bit 335 Items: map[Kind]ModelItem{ 336 Ptr: {8, 8, 8, nil}, 337 Void: {0, 1, 1, nil}, 338 Char: {1, 1, 1, nil}, 339 SChar: {1, 1, 1, nil}, 340 UChar: {1, 1, 1, nil}, 341 Short: {2, 2, 2, nil}, 342 UShort: {2, 2, 2, nil}, 343 Int: {4, 4, 4, nil}, 344 UInt: {4, 4, 4, nil}, 345 Long: {8, 8, 8, nil}, 346 ULong: {8, 8, 8, nil}, 347 LongLong: {8, 8, 8, nil}, 348 ULongLong: {8, 8, 8, nil}, 349 Float: {4, 4, 4, nil}, 350 Double: {8, 8, 8, nil}, 351 LongDouble: {8, 8, 8, nil}, 352 Bool: {1, 1, 1, nil}, 353 FloatComplex: {8, 8, 8, nil}, 354 DoubleComplex: {16, 16, 16, nil}, 355 LongDoubleComplex: {16, 16, 16, nil}, 356 }, 357 tweaks: &tweaks{}, 358 } 359 360 lx.model.initialize(lx) 361 if err != nil { 362 panic(err) 363 } 364 365 lx.exampleRule = rule 366 yyParse(lx) 367 return lx.example 368 } 369 370 func ppParseString(fn, src string, report *xc.Report, tweaks *tweaks) (*PreprocessingFile, error) { 371 sz := len(src) 372 lx, err := newLexer(fn, sz+1, bytes.NewBufferString(src), report, tweaks) 373 if err != nil { 374 return nil, err 375 } 376 377 lx.Unget(lex.NewChar(token.Pos(lx.File.Base()), PREPROCESSING_FILE)) 378 yyParse(lx) 379 return lx.preprocessingFile, nil 380 } 381 382 func ppParse(fn string, report *xc.Report, tweaks *tweaks) (*PreprocessingFile, error) { 383 o := xc.Files.Once(fn, func() interface{} { 384 f, err := os.Open(fn) 385 if err != nil { 386 return err 387 } 388 389 defer f.Close() 390 391 fi, err := os.Stat(fn) 392 if err != nil { 393 return nil 394 } 395 396 sz := fi.Size() 397 if sz > mathutil.MaxInt-1 { 398 return fmt.Errorf("%s: file size too big: %v", fn, sz) 399 } 400 401 lx, err := newLexer(fn, int(sz)+1, bufio.NewReader(f), report, tweaks) 402 if err != nil { 403 return err 404 } 405 406 lx.Unget(lex.NewChar(token.Pos(lx.File.Base()), PREPROCESSING_FILE)) 407 if yyParse(lx) != 0 { 408 return report.Errors(true) 409 } 410 411 return lx.preprocessingFile 412 }) 413 switch r := o.Value(); x := r.(type) { 414 case error: 415 return nil, x 416 case *PreprocessingFile: 417 return x, nil 418 default: 419 panic("internal error") 420 } 421 } 422 423 // Opt is a configuration/setup function that can be passed to the Parser 424 // function. 425 type Opt func(*lexer) 426 427 // KeepComments makes the parser keep comments. 428 func KeepComments() Opt { 429 return func(l *lexer) { l.tweaks.comments = map[token.Pos]int{} } 430 } 431 432 // EnableBuiltinClassifyType makes the parser handle specially 433 // 434 // __builtin_constant_p(expr) 435 // 436 // See https://gcc.gnu.org/onlinedocs/gccint/Varargs.html 437 func EnableBuiltinClassifyType() Opt { 438 return func(l *lexer) { l.tweaks.enableBuiltinClassifyType = true } 439 } 440 441 // Mode99c turns on support for the 99c compiler. 442 func Mode99c() Opt { 443 return func(l *lexer) { l.tweaks.mode99c = true } 444 } 445 446 // EnableBuiltinConstantP makes the parser handle specially 447 // 448 // __builtin_constant_p(expr) 449 // 450 // See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 451 func EnableBuiltinConstantP() Opt { 452 return func(l *lexer) { l.tweaks.enableBuiltinConstantP = true } 453 } 454 455 // EnableImplicitIntType makes the parser accept non standard omitting type 456 // specifier. For example 457 // 458 // static i; 459 // 460 // becomes the same as 461 // 462 // static int i; 463 // 464 func EnableImplicitIntType() Opt { 465 return func(l *lexer) { l.tweaks.enableImplicitIntType = true } 466 } 467 468 // EnableOmitConditionalOperand makes the parser accept non standard 469 // 470 // x ? : y 471 // 472 // See https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Conditionals.html#Conditionals 473 func EnableOmitConditionalOperand() Opt { 474 return func(l *lexer) { l.tweaks.enableOmitConditionalOperand = true } 475 } 476 477 // EnableComputedGotos makes the parser accept non standard 478 // 479 // variable = &&label; 480 // goto *variable; 481 // 482 // See https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Labels-as-Values.html 483 func EnableComputedGotos() Opt { 484 return func(l *lexer) { l.tweaks.enableComputedGotos = true } 485 } 486 487 // EnableUnsignedEnums makes the parser handle choose unsigned int as the type 488 // of an enumeration with no negative members. 489 func EnableUnsignedEnums() Opt { 490 return func(l *lexer) { l.tweaks.enableUnsignedEnums = true } 491 } 492 493 // EnableLegacyDesignators makes the parser accept legacy designators 494 // 495 // { a: 42 } // Obsolete since GCC 2.5, standard is { .a=42 } 496 // 497 // See https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html 498 func EnableLegacyDesignators() Opt { 499 return func(l *lexer) { l.tweaks.enableLegacyDesignators = true } 500 } 501 502 // AllowCompatibleTypedefRedefinitions makes the parser accept compatible 503 // typedef redefinitions. 504 // 505 // typedef int foo; 506 // typedef int foo; // ok with this option. 507 // typedef long int foo; // never ok. 508 // 509 func AllowCompatibleTypedefRedefinitions() Opt { 510 return func(l *lexer) { l.tweaks.allowCompatibleTypedefRedefinitions = true } 511 } 512 513 // EnableParenthesizedCompoundStatemen makes the parser accept non standard 514 // 515 // ({ ... }) 516 // 517 // as an expression. See [3]. 518 func EnableParenthesizedCompoundStatemen() Opt { 519 return func(l *lexer) { l.tweaks.enableParenCompoundStmt = true } 520 } 521 522 // EnableImaginarySuffix makes the parser accept non standard 523 // 524 // 4.2i, 5.6j etc 525 // 526 // See https://gcc.gnu.org/onlinedocs/gcc/Complex.html 527 func EnableImaginarySuffix() Opt { 528 return func(l *lexer) { l.tweaks.enableImaginarySuffix = true } 529 } 530 531 // EnableNonConstStaticInitExpressions makes the parser accept non standard 532 // 533 // static int i = f(); 534 // 535 // [0], 6.7.8/4: All the expressions in an initializer for an object that has 536 // static storage duration shall be constant expressions or string literals. 537 func EnableNonConstStaticInitExpressions() Opt { 538 return func(l *lexer) { l.tweaks.enableNonConstStaticInitExpressions = true } 539 } 540 541 // EnableAnonymousStructFields makes the parser accept non standard 542 // 543 // struct { 544 // int i; 545 // struct { 546 // int j; 547 // }; 548 // int k; 549 // }; 550 func EnableAnonymousStructFields() Opt { 551 return func(l *lexer) { l.tweaks.enableAnonymousStructFields = true } 552 } 553 554 // EnableOmitFuncRetType makes the parser accept non standard 555 // 556 // f() // Same as int f(). 557 func EnableOmitFuncRetType() Opt { 558 return func(l *lexer) { l.tweaks.enableOmitFuncRetType = true } 559 } 560 561 // EnableOmitFuncArgTypes makes the parser accept non standard 562 // 563 // f(a) // Same as int f(int a). 564 func EnableOmitFuncArgTypes() Opt { 565 return func(l *lexer) { l.tweaks.enableOmitFuncArgTypes = true } 566 } 567 568 // EnableEmptyDeclarations makes the parser accept non standard 569 // 570 // ; // C++11 empty declaration 571 func EnableEmptyDeclarations() Opt { 572 return func(l *lexer) { l.tweaks.enableEmptyDeclarations = true } 573 } 574 575 // EnableIncludeNext makes the parser accept non standard 576 // 577 // #include_next "foo.h" 578 func EnableIncludeNext() Opt { 579 return func(l *lexer) { l.tweaks.enableIncludeNext = true } 580 } 581 582 // EnableDefineOmitCommaBeforeDDD makes the parser accept non standard 583 // 584 // #define foo(a, b...) // Note the missing comma after identifier list. 585 func EnableDefineOmitCommaBeforeDDD() Opt { 586 return func(l *lexer) { l.tweaks.enableDefineOmitCommaBeforeDDD = true } 587 } 588 589 // EnableAlternateKeywords makes the parser accept, for example, non standard 590 // 591 // __asm__ 592 // 593 // as an equvalent of keyowrd asm (which first hast be permitted by EnableAsm). 594 func EnableAlternateKeywords() Opt { 595 return func(l *lexer) { l.tweaks.enableAlternateKeywords = true } 596 } 597 598 // EnableDlrInIdentifiers makes the parser accept non standard 599 // 600 // int foo$bar 601 func EnableDlrInIdentifiers() Opt { 602 return func(l *lexer) { l.tweaks.enableDlrInIdentifiers = true } 603 } 604 605 // EnableEmptyDefine makes the parser accept non standard 606 // 607 // #define 608 func EnableEmptyDefine() Opt { 609 return func(l *lexer) { l.tweaks.enableEmptyDefine = true } 610 } 611 612 // EnableImplicitFuncDef makes the parser accept non standard 613 // 614 // int f() { 615 // return g(); // g is undefined, but assumed to be returning int. 616 // } 617 func EnableImplicitFuncDef() Opt { 618 return func(l *lexer) { l.tweaks.enableImplicitFuncDef = true } 619 } 620 621 // EnableEmptyStructs makes the parser accept non standard 622 // 623 // struct foo {}; 624 func EnableEmptyStructs() Opt { 625 return func(l *lexer) { l.tweaks.enableEmptyStructs = true } 626 } 627 628 // EnableUndefExtraTokens makes the parser accept non standard 629 // 630 // #undef foo(bar) 631 func EnableUndefExtraTokens() Opt { 632 return func(l *lexer) { l.tweaks.enableUndefExtraTokens = true } 633 } 634 635 // EnableWideEnumValues makes the parser accept non standard 636 // 637 // enum { v = X }; for X wider than 32 bits. 638 func EnableWideEnumValues() Opt { 639 return func(l *lexer) { l.tweaks.enableWideEnumValues = true } 640 } 641 642 // EnableWideBitFieldTypes makes the parser accept non standard bitfield 643 // types (i.e, long long and unsigned long long). 644 // 645 // unsigned long long bits : 2; 646 func EnableWideBitFieldTypes() Opt { 647 return func(l *lexer) { l.tweaks.enableWideBitFieldTypes = true } 648 } 649 650 // SysIncludePaths option configures where to search for system include files 651 // (eg. <name.h>). Multiple SysIncludePaths options may be used, the resulting 652 // search path list is produced by appending the option arguments in order of 653 // appearance. 654 func SysIncludePaths(paths []string) Opt { 655 return func(l *lexer) { 656 var err error 657 if l.sysIncludePaths, err = dedupAbsPaths(append(l.sysIncludePaths, fromSlashes(paths)...)); err != nil { 658 l.report.Err(0, "synIncludepaths option: %v", err) 659 } 660 l.sysIncludePaths = l.sysIncludePaths[:len(l.sysIncludePaths):len(l.sysIncludePaths)] 661 } 662 } 663 664 // IncludePaths option configures where to search for include files (eg. 665 // "name.h"). Multiple IncludePaths options may be used, the resulting search 666 // path list is produced by appending the option arguments in order of 667 // appearance. 668 func IncludePaths(paths []string) Opt { 669 return func(l *lexer) { 670 var err error 671 if l.includePaths, err = dedupAbsPaths(append(l.includePaths, fromSlashes(paths)...)); err != nil { 672 l.report.Err(0, "includepaths option: %v", err) 673 } 674 l.includePaths = l.includePaths[:len(l.includePaths):len(l.includePaths)] 675 } 676 } 677 678 // YyDebug sets the parser debug level. 679 func YyDebug(n int) Opt { 680 return func(*lexer) { yyDebug = n } 681 } 682 683 // Cpp registers a preprocessor hook function which is called for every line, 684 // or group of lines the preprocessor produces before it is consumed by the 685 // parser. The token slice must not be modified by the hook. 686 func Cpp(f func([]xc.Token)) Opt { 687 return func(lx *lexer) { lx.cpp = f } 688 } 689 690 // ErrLimit limits the number of calls to the error reporting methods. After 691 // the limit is reached, all errors are reported using log.Print and then 692 // log.Fatal() is called with a message about too many errors. To disable 693 // error limit, set ErrLimit to value less or equal zero. Default value is 10. 694 func ErrLimit(n int) Opt { 695 return func(lx *lexer) { lx.report.ErrLimit = n } 696 } 697 698 // Trigraphs enables processing of trigraphs. 699 func Trigraphs() Opt { return func(lx *lexer) { lx.tweaks.enableTrigraphs = true } } 700 701 // EnableAsm enables recognizing the reserved word asm. 702 func EnableAsm() Opt { return func(lx *lexer) { lx.tweaks.enableAsm = true } } 703 704 // EnableNoreturn enables recognizing the reserved word _Noreturn. 705 func EnableNoreturn() Opt { return func(lx *lexer) { lx.tweaks.enableNoreturn = true } } 706 707 // EnableTypeOf enables recognizing the reserved word typeof. 708 func EnableTypeOf() Opt { return func(lx *lexer) { lx.tweaks.enableTypeof = true } } 709 710 // EnableAlignOf enables recognizing the reserved word _Alignof. 711 func EnableAlignOf() Opt { return func(lx *lexer) { lx.tweaks.enableAlignof = true } } 712 713 // EnableStaticAssert enables recognizing the reserved word _Static_assert. 714 func EnableStaticAssert() Opt { return func(lx *lexer) { lx.tweaks.enableStaticAssert = true } } 715 716 // CrashOnError is an debugging option. 717 func CrashOnError() Opt { return func(lx *lexer) { lx.report.PanicOnError = true } } 718 719 func disableWarnings() Opt { return func(lx *lexer) { lx.tweaks.enableWarnings = false } } 720 func gccEmu() Opt { return func(lx *lexer) { lx.tweaks.gccEmu = true } } 721 func getTweaks(dst *tweaks) Opt { return func(lx *lexer) { *dst = *lx.tweaks } } 722 func nopOpt() Opt { return func(*lexer) {} } 723 func preprocessOnly() Opt { return func(lx *lexer) { lx.tweaks.preprocessOnly = true } } 724 725 func devTest() Opt { 726 return func(lx *lexer) { lx.tweaks.devTest = true } 727 } 728 729 func disablePredefinedLineMacro() Opt { 730 return func(lx *lexer) { lx.tweaks.disablePredefinedLineMacro = true } 731 } 732 733 // Parse defines any macros in predefine. Then Parse preprocesses and parses 734 // the translation unit consisting of files in paths. The m communicates the 735 // scalar types model and opts allow to amend parser behavior. m cannot be 736 // reused and passed to Parse again. 737 func Parse(predefine string, paths []string, m *Model, opts ...Opt) (*TranslationUnit, error) { 738 if m == nil { 739 return nil, fmt.Errorf("invalid nil model passed") 740 } 741 742 if m.initialized { 743 return nil, fmt.Errorf("invalid reused model passed") 744 } 745 746 fromSlashes(paths) 747 report := xc.NewReport() 748 lx0 := &lexer{tweaks: &tweaks{enableWarnings: true}, report: report} 749 for _, opt := range opts { 750 opt(lx0) 751 } 752 m.tweaks = lx0.tweaks 753 if err := report.Errors(true); err != nil { 754 return nil, err 755 } 756 757 if lx0.tweaks.devTest { 758 predefine += fmt.Sprintf(` 759 #define __DATE__ %q 760 #define __TIME__ %q 761 `, xc.Dict.S(idTDate), fakeTime) 762 } 763 764 if t := lx0.tweaks; t.gccEmu { 765 t.doGccEmu() 766 } 767 768 m.initialize(lx0) 769 if err := m.sanityCheck(); err != nil { 770 report.Err(0, "%s", err.Error()) 771 return nil, report.Errors(true) 772 } 773 774 if lx0.tweaks.gccEmu { 775 dts := debugTypeStrings 776 debugTypeStrings = false 777 predefine += fmt.Sprintf(gccPredefine, m.getSizeType(lx0)) 778 debugTypeStrings = dts 779 } 780 tweaks := lx0.tweaks 781 predefined, err := ppParseString("<predefine>", predefine, report, tweaks) 782 if err != nil { 783 return nil, err 784 } 785 786 ch := make(chan []xc.Token, 1000) 787 macros := newMacros() 788 stop := make(chan int, 1) 789 go func() { 790 defer close(ch) 791 792 newPP(ch, lx0.includePaths, lx0.sysIncludePaths, macros, false, m, report, tweaks).preprocessingFile(predefined) 793 for _, path := range paths { 794 select { 795 case <-stop: 796 return 797 default: 798 } 799 pf, err := ppParse(path, report, tweaks) 800 if err != nil { 801 report.Err(0, err.Error()) 802 return 803 } 804 805 newPP(ch, lx0.includePaths, lx0.sysIncludePaths, macros, true, m, report, tweaks).preprocessingFile(pf) 806 } 807 }() 808 809 if err := report.Errors(true); err != nil { // Do not parse if preprocessing already failed. 810 go func() { 811 for range ch { // Drain. 812 } 813 }() 814 stop <- 1 815 return nil, err 816 } 817 818 lx := newSimpleLexer(lx0.cpp, report, tweaks) 819 lx.ch = ch 820 lx.state = lsTranslationUnit0 821 lx.model = m 822 if lx.tweaks.preprocessOnly { 823 var lval yySymType 824 for lval.Token.Rune != lex.RuneEOF { 825 lx.Lex(&lval) 826 } 827 return nil, report.Errors(true) 828 } 829 830 yyParse(lx) 831 stop <- 1 832 for range ch { // Drain. 833 } 834 if tu := lx.translationUnit; tu != nil { 835 tu.Macros = macros.macros() 836 tu.Model = m 837 tu.Comments = lx0.tweaks.comments 838 if c := tu.Comments; c != nil { 839 for _, v := range tu.Declarations.Identifiers { 840 switch x := v.Node.(type) { 841 case *DirectDeclarator: 842 pos0 := x.Declarator.Pos() 843 if !pos0.IsValid() { 844 pos0 = x.Pos() 845 } 846 if !pos0.IsValid() { 847 break 848 } 849 850 if comment(lx0.tweaks, x, x.Declarator) != 0 { 851 break 852 } 853 854 for p := x.prev; p != nil; { 855 y := p.Node.(*DirectDeclarator) 856 if n := comment(lx0.tweaks, y, y.Declarator); n != 0 { 857 pos := y.DirectDeclarator.Pos() 858 if !pos.IsValid() { 859 pos = y.Pos() 860 } 861 c[pos0] = n 862 break 863 } 864 p2 := p.Node.(*DirectDeclarator).prev 865 if p2 == p { 866 break 867 } 868 869 p = p2 870 } 871 default: 872 panic(fmt.Errorf("%T", x)) 873 } 874 } 875 } 876 } 877 return lx.translationUnit, report.Errors(true) 878 }