modernc.org/gocc@v0.0.1/main.go (about) 1 // Copyright 2019 The GOCC 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 main // import "modernc.org/gocc" 6 7 //TODO https://todo.sr.ht/~mcf/cc-issues/52 8 //TODO https://todo.sr.ht/~mcf/cc-issues/56 9 //TODO cdecl 10 11 import ( 12 "bufio" 13 "fmt" 14 "io" 15 "io/ioutil" 16 "os" 17 "path/filepath" 18 "runtime" 19 "runtime/debug" 20 "strings" 21 "sync" 22 "unsafe" 23 24 "modernc.org/cc/v3" 25 "modernc.org/fileutil" 26 "modernc.org/opt" 27 qbec "modernc.org/qbe" 28 ) 29 30 const ( 31 version = "0.1.0 pre-alpha" 32 33 builtin = ` 34 #define __DI__ 35 #define __FUNCTION__ __func__ 36 #define __HI__ 37 #define __PRETTY_FUNCTION__ __func__ 38 #define __QI__ 39 #define __SI__ 40 #define __builtin_abort abort 41 #define __builtin_abs abs 42 #define __builtin_alloca alloca 43 #define __builtin_bcopy bcopy 44 #define __builtin_cimag cimag 45 #define __builtin_cimagf cimagf 46 #define __builtin_cimagl cimagl 47 #define __builtin_conj conj 48 #define __builtin_conjf conjf 49 #define __builtin_conjl conjl 50 #define __builtin_constant_p(x) __builtin_constant_p_impl(0, x) 51 #define __builtin_copysign copysign 52 #define __builtin_copysignf copysignf 53 #define __builtin_creal creal 54 #define __builtin_crealf crealf 55 #define __builtin_creall creall 56 #define __builtin_expect(exp, c) exp 57 #define __builtin_fabs fabs 58 #define __builtin_ffs ffs 59 #define __builtin_fprintf fprintf 60 #define __builtin_fprintf_unlocked fprintf 61 #define __builtin_fputc fputc 62 #define __builtin_fputs fputs 63 #define __builtin_fputs_unlocked fputs 64 #define __builtin_free free 65 #define __builtin_fwrite fwrite 66 #define __builtin_index index 67 #define __builtin_labs labs 68 #define __builtin_llabs llabs 69 #define __builtin_malloc malloc 70 #define __builtin_memchr memchr 71 #define __builtin_memcmp memcmp 72 #define __builtin_memcpy memcpy 73 #define __builtin_memmove memmove 74 #define __builtin_mempcpy memcpy 75 #define __builtin_memset memset 76 #define __builtin_offsetof(type, member) ((__SIZE_TYPE__)&(((type*)0)->member)) 77 #define __builtin_prefetch(...) (void)(__VA_ARGS__) 78 #define __builtin_printf printf 79 #define __builtin_printf_unlocked printf 80 #define __builtin_putchar putchar 81 #define __builtin_puts puts 82 #define __builtin_snprintf snprintf 83 #define __builtin_sprintf sprintf 84 #define __builtin_strcat strcat 85 #define __builtin_strchr strchr 86 #define __builtin_strcmp strcmp 87 #define __builtin_strcpy strcpy 88 #define __builtin_strlen strlen 89 #define __builtin_strncat strncat 90 #define __builtin_strncmp strncmp 91 #define __builtin_trap abort 92 #define __builtin_unreachable abort 93 #define __builtin_va_arg(ap, type) (type)__gocc_va_arg(ap) 94 #define __builtin_va_copy(dst, src) dst = src 95 #define __builtin_va_end(ap) __gocc_va_end(ap) 96 #define __builtin_va_start(ap, v) __gocc_va_start(ap) 97 #define __declspec(...) 98 #define __extension__ 99 #define __signed__ signed 100 #define __sync_synchronize(...) 101 #define __word__ 102 #define asm __asm__ 103 #define fputs_unlocked fputs 104 105 #if __SIZEOF_POINTER__ == 8 106 typedef void* __builtin_va_list[3]; 107 #else 108 typedef void* __builtin_va_list[1]; 109 typedef long double __float128; 110 #endif 111 112 #ifndef __GNUC__ 113 #define __attribute(x) 114 #define __attribute__(x) 115 #define alloca(size) __gocc_alloca (size) 116 #endif 117 118 119 #ifdef __PTRDIFF_TYPE__ 120 typedef __PTRDIFF_TYPE__ ptrdiff_t; 121 #endif 122 123 #ifdef __SIZE_TYPE__ 124 typedef __SIZE_TYPE__ size_t; 125 #endif 126 127 #ifdef __WCHAR_TYPE__ 128 typedef __WCHAR_TYPE__ wchar_t; 129 #endif 130 131 #ifdef __UINT16_TYPE__ 132 __UINT16_TYPE__ __builtin_bswap16 (__UINT16_TYPE__ x); 133 #endif 134 135 #ifdef __UINT32_TYPE__ 136 __UINT32_TYPE__ __builtin_bswap32 (__UINT32_TYPE__ x); 137 #endif 138 139 #ifdef __UINT64_TYPE__ 140 __UINT64_TYPE__ __builtin_bswap64 (__UINT64_TYPE__ x); 141 #endif 142 143 #if __SIZEOF_POINTER__ == 4 && !defined(__ILP32__) 144 #define __ILP32__ 1 145 #endif 146 147 typedef struct { char real, imag; } __COMPLEX_CHAR_TYPE__; 148 typedef struct { double real, imag; } __COMPLEX_DOUBLE_TYPE__; 149 typedef struct { float real, imag; } __COMPLEX_FLOAT_TYPE__; 150 typedef struct { int real, imag; } __COMPLEX_INT_TYPE__; 151 typedef struct { long double real, imag; } __COMPLEX_LONG_DOUBLE_TYPE__; 152 typedef struct { long real, imag; } __COMPLEX_LONG_TYPE__; 153 typedef struct { long long real, imag; } __COMPLEX_LONG_LONG_TYPE__; 154 typedef struct { long long unsigned real, imag; } __COMPLEX_LONG_LONG_UNSIGNED_TYPE__; 155 typedef struct { long unsigned real, imag; } __COMPLEX_LONG_UNSIGNED_TYPE__; 156 typedef struct { short real, imag; } __COMPLEX_SHORT_TYPE__; 157 typedef struct { unsigned real, imag; } __COMPLEX_UNSIGNED_TYPE__; 158 typedef struct { unsigned short real, imag; } __COMPLEX_SHORT_UNSIGNED_TYPE__; 159 160 int __builtin_clzll (unsigned long long); //TODO- 161 int __builtin_constant_p_impl(int, ...); 162 int __printf__ ( const char * format, ... ); //TODO- 163 int __scanf__ ( const char *format, ... ); //TODO- 164 void *__gocc_alloca(size_t size); 165 void *__gocc_va_arg(void* ap); 166 void *__gocc_va_end(void* ap); 167 void *__gocc_va_start(void* ap); 168 ` 169 ) 170 171 var ( 172 _ = ioutil.ReadFile 173 174 arch = 8 * unsafe.Sizeof(uintptr(0)) 175 hostConfigOnce32 sync.Once 176 hostConfigOnce64 sync.Once 177 hostPredef32 string 178 hostIncludes32 []string 179 hostSysIncludes32 []string 180 hostPredef64 string 181 hostIncludes64 []string 182 hostSysIncludes64 []string 183 184 isTesting bool 185 traceIL bool 186 ) 187 188 func hostConfig(opts ...string) (hostPredef string, hostIncludes, hostSysIncludes []string, err error) { 189 hostPredef, hostIncludes, hostSysIncludes, err = cc.HostConfig("", opts...) 190 if err != nil { 191 return "", nil, nil, err 192 } 193 194 a := strings.Split(hostPredef, "\n") 195 w := 0 196 for _, v0 := range a { 197 v := strings.TrimSpace(strings.ToLower(v0)) 198 if !strings.HasPrefix(v, "#define __gnu") && !strings.HasPrefix(v, "#define __gcc") { 199 a[w] = v0 200 w++ 201 } 202 } 203 hostPredef = strings.Join(a[:w], "\n") 204 return hostPredef, hostIncludes, hostSysIncludes, err 205 } 206 207 func internalError() int { return internalErrorf("") } 208 func internalErrorf(s string, args ...interface{}) int { panic(fmt.Errorf(s, args...)) } 209 210 type task struct { 211 args []string 212 ast *cc.AST 213 cc.Config 214 includePaths []string 215 inputs []int 216 intType cc.Type 217 predefined string 218 ptrType cc.Type 219 qbeArgs []string 220 stderr io.Writer 221 stdout io.Writer 222 sysIncludePaths []string 223 temps []string 224 testSources []cc.Source // testing //TODO- 225 wr io.Writer 226 227 opts struct { 228 D []string // -D 229 I []string // -I 230 U []string // -U 231 o string // -o 232 qbecPkgName string // -qbec-pkgname 233 qbecStaticPrefix string // -qbec-static-prefix 234 qbecVolatile map[cc.StringID]struct{} // -qbec-volatile 235 rpath string // -rpath 236 soname string // -soname 237 std string // -std 238 239 C bool // -C 240 E bool // -E 241 c bool // -c 242 fPIC bool // -fPIC 243 fpic bool // -fpic 244 goccAllocatedDeclarators bool // -gocc-allocated-declarators 245 goccEmitDefintions bool // -gocc-emit-definitions 246 goccPedantic bool // -gocc-pedantic 247 goccTrc bool 248 m32 bool // -m32 249 m64 bool // -m64 250 noWholeArchive bool // --no-whole-archive 251 shared bool // -shared 252 wholeArchive bool // --whole-archive 253 } 254 255 doNotCache bool 256 doNotCacheMain bool 257 genQBE bool // -o foo.qbe 258 } 259 260 var ( 261 accept = []string{".c", ".h"} 262 ) 263 264 // args are like os.Args, len always > 0. 265 func newTask(args []string) (t *task, err error) { 266 if dmesgs { 267 dmesg("newTask %q", args) 268 } 269 wd, err := os.Getwd() 270 if err != nil { 271 return nil, err 272 } 273 274 t = &task{ 275 args: args, 276 } 277 t.Config.PragmaHandler = t.pragmaHandler 278 t.Config.WorkingDir = wd 279 280 p := opt.NewSet() 281 p.Opt("C", func(opt string) error { t.opts.C = true; return nil }) 282 p.Opt("E", func(opt string) error { t.opts.E = true; return nil }) 283 p.Opt("c", func(opt string) error { t.opts.c = true; t.qbeArgs = append(t.qbeArgs, opt); return nil }) 284 p.Opt("fPIC", func(opt string) error { t.opts.fPIC = true; t.qbeArgs = append(t.qbeArgs, opt); return nil }) 285 p.Opt("fpic", func(opt string) error { t.opts.fpic = true; t.qbeArgs = append(t.qbeArgs, opt); return nil }) 286 p.Opt("m32", func(opt string) error { t.opts.m32 = true; t.qbeArgs = append(t.qbeArgs, opt); return nil }) 287 p.Opt("m64", func(opt string) error { t.opts.m64 = true; t.qbeArgs = append(t.qbeArgs, opt); return nil }) 288 p.Opt("shared", func(opt string) error { t.opts.shared = true; t.qbeArgs = append(t.qbeArgs, opt); return nil }) 289 p.Arg("D", true, func(opt, arg string) error { 290 t.opts.D = append(t.opts.D, arg) 291 t.qbeArgs = append(t.qbeArgs, opt+arg) //TODO-? 292 return nil 293 }) 294 p.Arg("qbec-crt", false, func(opt, arg string) error { 295 t.qbeArgs = append(t.qbeArgs, opt, arg) 296 return nil 297 }) 298 p.Arg("qbec-import", false, func(opt, arg string) error { 299 t.qbeArgs = append(t.qbeArgs, opt, arg) 300 return nil 301 }) 302 p.Arg("qbec-dot-import", false, func(opt, arg string) error { 303 t.qbeArgs = append(t.qbeArgs, opt, arg) 304 return nil 305 }) 306 p.Arg("qbec-pkgname", false, func(opt, arg string) error { 307 t.opts.qbecPkgName = arg //TODO- 308 t.qbeArgs = append(t.qbeArgs, opt, arg) 309 return nil 310 }) 311 p.Arg("qbec-static-prefix", false, func(opt, arg string) error { 312 t.opts.qbecStaticPrefix = arg //TODO- 313 t.qbeArgs = append(t.qbeArgs, opt, arg) 314 return nil 315 }) 316 p.Arg("qbec-volatile", false, func(opt, arg string) error { 317 a := strings.Split(arg, ",") 318 if t.opts.qbecVolatile == nil { 319 t.opts.qbecVolatile = map[cc.StringID]struct{}{} 320 } 321 for _, v := range a { 322 t.opts.qbecVolatile[cc.String(strings.TrimSpace(v))] = struct{}{} 323 } 324 return nil 325 }) 326 p.Arg("I", true, func(opt, arg string) error { t.opts.I = append(t.opts.I, arg); return nil }) 327 p.Arg("U", true, func(opt, arg string) error { 328 t.opts.U = append(t.opts.U, arg) 329 t.qbeArgs = append(t.qbeArgs, opt+arg) //TODO-? 330 return nil 331 }) 332 p.Arg("o", false, func(opt, arg string) error { 333 if t.opts.o != "" { 334 return fmt.Errorf("multiple -o options present") 335 } 336 337 t.opts.o = arg 338 switch filepath.Ext(arg) { 339 case ".qbe": 340 t.genQBE = true 341 default: 342 t.qbeArgs = append(t.qbeArgs, opt, arg) 343 } 344 return nil 345 }) 346 p.Arg("rpath", false, func(opt, arg string) error { 347 t.opts.rpath = arg 348 t.qbeArgs = append(t.qbeArgs, "-Wl,-rpath", fmt.Sprintf("-Wl,%s", arg)) 349 return nil 350 }) 351 p.Arg("std", false, func(opt, arg string) error { 352 t.opts.std = arg 353 t.qbeArgs = append(t.qbeArgs, fmt.Sprintf("-std=%v", arg)) 354 return nil 355 }) 356 p.Arg("soname", false, func(opt, arg string) error { 357 t.opts.soname = arg 358 t.qbeArgs = append(t.qbeArgs, "-Wl,-soname", fmt.Sprintf("-Wl,%s", arg)) 359 return nil 360 }) 361 p.Opt("-whole-archive", func(opt string) error { 362 t.opts.wholeArchive = true 363 t.qbeArgs = append(t.qbeArgs, "-Wl,--whole-archive") 364 return nil 365 }) 366 p.Opt("-no-whole-archive", func(opt string) error { 367 t.opts.noWholeArchive = true 368 t.qbeArgs = append(t.qbeArgs, "-Wl,--no-whole-archive") 369 return nil 370 }) 371 p.Opt("gocc-long-double-is-double", func(opt string) error { t.Config.LongDoubleIsDouble = true; return nil }) 372 p.Opt("gocc-emit-definitions", func(opt string) error { t.opts.goccEmitDefintions = true; return nil }) 373 p.Opt("gocc-pedantic", func(opt string) error { t.opts.goccPedantic = true; return nil }) 374 p.Opt("gocc-allocated-declarators", func(opt string) error { t.opts.goccAllocatedDeclarators = true; return nil }) 375 p.Opt("gocc-trc", func(opt string) error { t.opts.goccTrc = true; return nil }) 376 if err := p.Parse(args[1:], func(name string) error { 377 t.qbeArgs = append(t.qbeArgs, name) 378 if strings.HasPrefix(name, "-") { 379 return nil 380 } 381 382 ext := filepath.Ext(name) 383 for _, a := range accept { 384 if ext == a { 385 t.inputs = append(t.inputs, len(t.qbeArgs)-1) 386 return nil 387 } 388 } 389 390 return nil 391 }); err != nil { 392 return nil, err 393 } 394 395 if t.opts.c && t.opts.o == "" && len(t.inputs) != 0 { 396 base := filepath.Base(t.qbeArgs[t.inputs[0]]) 397 ext := filepath.Ext(base) 398 base = base[:len(base)-len(ext)] 399 base += ".o" 400 t.qbeArgs = append(t.qbeArgs, "-o", base) 401 } 402 403 if s := t.opts.o; filepath.Ext(s) == ".go" && t.opts.qbecPkgName == "" && t.opts.qbecStaticPrefix == "" { 404 s = filepath.Base(s) 405 s = s[:len(s)-len(".go")] 406 s = strings.ReplaceAll(s, "-", "") 407 s = strings.ReplaceAll(s, ".", "") 408 s = strings.ReplaceAll(s, "_", "") 409 if !strings.HasPrefix(s, "s") { 410 s = "s" + s 411 } 412 t.qbeArgs = append(t.qbeArgs, "-qbec-static-prefix", s+"_") 413 } 414 415 return t, nil 416 } 417 418 func (t *task) pragmaHandler(p cc.Pragma, toks []cc.Token) { 419 if len(toks) == 0 { 420 return 421 } 422 switch s := toks[0].Value.String(); s { 423 case "push_macro", "pop_macro": 424 toks = toks[1:] 425 if len(toks) == 3 && toks[0].Rune == '(' && toks[1].Rune == cc.STRINGLITERAL && toks[2].Rune == ')' { 426 nm := toks[1].String() 427 if len(nm) < 3 { 428 todo(nil) //TODO report error 429 } 430 nm = nm[1 : len(nm)-1] 431 switch s { 432 case "push_macro": 433 p.PushMacro(nm) 434 case "pop_macro": 435 p.PopMacro(nm) 436 default: 437 panic("internal error") //TODOOK 438 } 439 break 440 } 441 442 todo(nil) //TODO report error 443 } 444 } 445 446 func (t *task) w(s string, args ...interface{}) { 447 //fmt.Printf(s, args...) //TODO- 448 if _, err := fmt.Fprintf(t.wr, s, args...); err != nil { 449 panic(err) // Handled in main 450 } 451 } 452 453 // The "real" main, possibly executed by the server process, if available, ie. 454 // in a different process than main is executing in. 455 func (t *task) main(stdout, stderr io.Writer) (exitCode int) { 456 if dmesgs { 457 dmesg("main entered: %v", os.Args) 458 459 defer func() { 460 dmesg("main exiting: %v", exitCode) 461 }() 462 } 463 t.stdout = stdout 464 t.stderr = stderr 465 466 var hostPredef string 467 var hostIncludes, hostSysIncludes []string 468 var err error 469 switch { 470 case t.opts.m32 && arch != 32: 471 hostConfigOnce32.Do(func() { hostPredef32, hostIncludes32, hostSysIncludes32, err = hostConfig("-m32") }) 472 hostPredef = hostPredef32 473 hostIncludes = hostIncludes32 474 hostSysIncludes = hostSysIncludes32 475 case t.opts.m64 && arch != 64: 476 hostConfigOnce32.Do(func() { hostPredef64, hostIncludes64, hostSysIncludes64, err = hostConfig("-m64") }) 477 hostPredef = hostPredef64 478 hostIncludes = hostIncludes64 479 hostSysIncludes = hostSysIncludes64 480 default: 481 hostConfigOnce64.Do(func() { hostPredef64, hostIncludes64, hostSysIncludes64, err = hostConfig() }) 482 hostPredef = hostPredef64 483 hostIncludes = hostIncludes64 484 hostSysIncludes = hostSysIncludes64 485 } 486 if err != nil { 487 fmt.Fprintln(stderr, err) 488 return 1 489 } 490 491 // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html 492 // 493 // Headers whose names are enclosed in double-quotes ( "" ) shall be 494 // searched for first in the directory of the file with the #include 495 // line, then in directories named in -I options, and last in the usual 496 // places 497 t.includePaths = append([]string{"@"}, t.opts.I...) 498 t.includePaths = append(t.includePaths, hostIncludes...) 499 t.includePaths = append(t.includePaths, hostSysIncludes...) 500 t.includePaths = append(t.includePaths, filepath.FromSlash("/usr/include")) //TODO nix only 501 // For headers whose names are enclosed in angle brackets ( "<>" ), the 502 // header shall be searched for only in directories named in -I options 503 // and then in the usual places. 504 t.sysIncludePaths = append(t.opts.I, hostSysIncludes...) 505 506 // if dmesgs { 507 // dmesg("includePaths:\n%v", strings.Join(t.includePaths, "\n")) 508 // dmesg("sysIncludePaths:\n%v", strings.Join(t.sysIncludePaths, "\n")) 509 // } 510 511 t.predefined = hostPredef 512 arch := runtime.GOARCH 513 switch { 514 case t.opts.m32: 515 switch arch { 516 case "386": 517 // nop 518 case "amd64": 519 arch = "386" 520 default: 521 fmt.Fprintf(stderr, "-m32 not supported on arch %s", arch) 522 return 1 523 } 524 } 525 526 t.Config.ABI, err = cc.NewABI(runtime.GOOS, arch) 527 if err != nil { 528 fmt.Fprintln(stderr, err) 529 return 1 530 } 531 532 var sources []cc.Source 533 if t.predefined != "" { 534 sources = append(sources, cc.Source{Name: "<predefined>", Value: t.predefined}) 535 } 536 sources = append(sources, cc.Source{Name: "<built-in>", Value: builtin}) 537 sources = append(sources, t.testSources...) 538 539 if len(t.opts.D) != 0 { 540 var a []string 541 for _, v := range t.opts.D { 542 if i := strings.IndexByte(v, '='); i > 0 { 543 a = append(a, fmt.Sprintf("#define %s %s", v[:i], v[i+1:])) 544 continue 545 } 546 547 a = append(a, fmt.Sprintf("#define %s 1", v)) 548 } 549 a = append(a, "\n") 550 sources = append(sources, cc.Source{Name: "<defines>", Value: strings.Join(a, "\n")}) 551 } 552 553 if len(t.opts.U) != 0 { 554 var a []string 555 for _, v := range t.opts.U { 556 a = append(a, fmt.Sprintf("#undef %s", v)) 557 } 558 a = append(a, "\n") 559 sources = append(sources, cc.Source{Name: "<undefines>", Value: strings.Join(a, "\n")}) 560 } 561 562 if t.opts.E { 563 t.Config.PreprocessOnly = true 564 if t.opts.C { 565 t.Config.PreserveWhiteSpace = true 566 } 567 for _, i := range t.inputs { 568 sources = append(sources, cc.Source{Name: t.qbeArgs[i]}) 569 } 570 w := bufio.NewWriter(stdout) 571 572 defer w.Flush() 573 574 if err := cc.Preprocess(&t.Config, t.includePaths, t.sysIncludePaths, sources, w); err != nil { 575 fmt.Fprintln(t.stdout, err) 576 return 1 577 } 578 579 return 0 580 } 581 582 defer func() { 583 for _, v := range t.temps { 584 os.Remove(v) 585 } 586 }() 587 588 var f *os.File 589 var w *bufio.Writer 590 for _, i := range t.inputs { 591 nm := t.qbeArgs[i] 592 switch { 593 case t.genQBE: 594 if w == nil { 595 var err error 596 if f, err = os.Create(t.opts.o); err != nil { 597 fmt.Fprintln(stderr, err) 598 return 1 599 } 600 601 w = bufio.NewWriter(f) 602 603 defer func() { 604 if err := w.Flush(); err != nil { 605 fmt.Fprintln(stderr, err) 606 exitCode = 1 607 } 608 if err := f.Close(); err != nil { 609 fmt.Fprintln(stderr, err) 610 exitCode = 1 611 } 612 }() 613 } 614 615 if err := t.compile1(sources, nm, w); err != nil { 616 fmt.Fprintln(stderr, err) 617 return 1 618 } 619 default: 620 temp, err := fileutil.TempFile("", "gocc-", ".qbe") 621 if err != nil { 622 fmt.Fprintf(stderr, "cannot create temp file: %v\n", err) 623 return 1 624 } 625 626 t.temps = append(t.temps, temp.Name()) 627 w := bufio.NewWriter(temp) 628 629 if err := t.compile1(sources, nm, w); err != nil { 630 fmt.Fprintln(stderr, err) 631 return 1 632 } 633 634 t.qbeArgs[i] = temp.Name() 635 if err := w.Flush(); err != nil { 636 fmt.Fprintln(stderr, err) 637 return 1 638 } 639 640 if err := temp.Close(); err != nil { 641 fmt.Fprintln(stderr, err) 642 return 1 643 } 644 } 645 } 646 if t.genQBE { 647 return 0 648 } 649 650 return qbec.Compile(append([]string{"qbec"}, t.qbeArgs...), t.stdout, t.stderr, nil) 651 } 652 653 func (t *task) compile1(sources []cc.Source, fn string, w io.Writer) (err error) { 654 doNotCache := t.doNotCacheMain && filepath.Base(fn) == "main.c" || t.doNotCache 655 sources = append(sources, cc.Source{Name: fn, DoNotCache: doNotCache}) 656 if t.opts.goccPedantic { 657 t.Config.RejectCaseRange = true 658 t.Config.RejectElseExtraTokens = true 659 t.Config.RejectEmptyCompositeLiterals = true 660 t.Config.RejectEmptyDeclarations = true 661 t.Config.RejectEmptyInitializerList = true 662 t.Config.RejectEmptyStructs = true 663 t.Config.RejectEndifExtraTokens = true 664 t.Config.RejectFinalBackslash = true 665 t.Config.RejectIfdefExtraTokens = true 666 t.Config.RejectIfndefExtraTokens = true 667 t.Config.RejectInvalidVariadicMacros = true 668 t.Config.RejectLabelValues = true 669 t.Config.RejectLateBinding = true 670 t.Config.RejectLineExtraTokens = true 671 t.Config.RejectMissingConditionalExpr = true 672 t.Config.RejectMissingDeclarationSpecifiers = true 673 t.Config.RejectMissingFinalNewline = true 674 t.Config.RejectMissingFinalStructFieldSemicolon = true 675 t.Config.RejectNestedFunctionDefinitions = true 676 t.Config.RejectParamSemicolon = true 677 t.Config.RejectStatementExpressions = true 678 t.Config.RejectTypeof = true 679 t.Config.RejectUndefExtraTokens = true 680 } 681 if t.opts.goccTrc { 682 t.Config.InjectTracingCode = true 683 } 684 if t.ast, err = cc.Translate(&t.Config, t.includePaths, t.sysIncludePaths, sources); err != nil { 685 return err 686 } 687 688 t.intType = t.Config.ABI.Type(cc.Int) 689 t.ptrType = t.Config.ABI.Type(cc.Ptr) 690 691 // if dmesgs { 692 // dmesg("%v sources for %s", len(sources), fn) 693 // for i, v := range sources { 694 // dmesg("#%v: Name %s:", i+1, v.Name) 695 // switch { 696 // case v.Value != "": 697 // dmesg("Value:\n%s", v.Value) 698 // default: 699 // switch filepath.Ext(v.Name) { 700 // case ".c", ".h": 701 // b, err := ioutil.ReadFile(v.Name) 702 // switch { 703 // case err != nil: 704 // dmesg("error: %s", err) 705 // default: 706 // dmesg("Value:\n%s", b) 707 // } 708 // } 709 // } 710 // } 711 // } 712 713 t.wr = w 714 q := newQBE(t) 715 716 defer func() { 717 if e := recover(); e != nil && err == nil { 718 err = fmt.Errorf("%v\n%s", e, debug.Stack()) 719 } 720 }() 721 722 q.gen() 723 724 if len(q.externalAsm) != 0 && err == nil { 725 err = fmt.Errorf("%v: assembler in C not supported", q.pos(q.externalAsm[0])) 726 } 727 return err 728 } 729 730 func main() { 731 if dmesgs { 732 dmesg("main entered %v", os.Args) 733 } 734 t, err := newTask(os.Args) 735 if err != nil { 736 fmt.Fprintln(os.Stderr, err) 737 if dmesgs { 738 dmesg("%v:\nmain exiting: 1", err) 739 } 740 os.Exit(1) 741 } 742 743 rc := t.main(os.Stdout, os.Stderr) 744 if dmesgs { 745 dmesg("main exiting: %v", rc) 746 } 747 os.Exit(rc) 748 }