func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0]) flag.PrintDefaults() fmt.Fprintf(os.Stderr, modifiedUsage) } flag.Parse() if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } if err := pprof.StartCPUProfile(f); err != nil { log.Fatal(err) } defer pprof.StopCPUProfile() } filename, offset, err := parsePos(*pos) if err != nil { fmt.Println(err) os.Exit(1) } ctx := &build.Default if *modified { overlay, err := buildutil.ParseOverlayArchive(os.Stdin) if err != nil { log.Fatalln("invalid archive:", err) } ctx = buildutil.OverlayContext(ctx, overlay) } d, err := Run(ctx, filename, offset) if err != nil { fmt.Println(err) os.Exit(1) } if *jsonOutput { json.NewEncoder(os.Stdout).Encode(d) } else { fmt.Println(d.String()) } }
func TestOverlay(t *testing.T) { ctx := &build.Default ov := map[string][]byte{ "/somewhere/a.go": []byte("file contents"), } names := []string{"/somewhere/a.go", "/somewhere//a.go"} ctx = buildutil.OverlayContext(ctx, ov) for _, name := range names { f, err := buildutil.OpenFile(ctx, name) if err != nil { t.Errorf("unexpected error %v", err) } b, err := ioutil.ReadAll(f) if err != nil { t.Errorf("unexpected error %v", err) } if got, expected := string(b), string(ov["/somewhere/a.go"]); got != expected { t.Errorf("read %q, expected %q", got, expected) } } }
func main() { log.SetPrefix("guru: ") log.SetFlags(0) // Don't print full help unless -help was requested. // Just gently remind users that it's there. flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) } flag.CommandLine.Init(os.Args[0], flag.ContinueOnError) // hack if err := flag.CommandLine.Parse(os.Args[1:]); err != nil { // (err has already been printed) if err == flag.ErrHelp { printHelp() } os.Exit(2) } args := flag.Args() if len(args) != 2 { flag.Usage() os.Exit(2) } mode, posn := args[0], args[1] if mode == "help" { printHelp() os.Exit(2) } // Set up points-to analysis log file. var ptalog io.Writer if *ptalogFlag != "" { if f, err := os.Create(*ptalogFlag); err != nil { log.Fatalf("Failed to create PTA log file: %s", err) } else { buf := bufio.NewWriter(f) ptalog = buf defer func() { if err := buf.Flush(); err != nil { log.Printf("flush: %s", err) } if err := f.Close(); err != nil { log.Printf("close: %s", err) } }() } } // Profiling support. if *cpuprofileFlag != "" { f, err := os.Create(*cpuprofileFlag) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } ctxt := &build.Default // If there were modified files, // read them from the standard input and // overlay them on the build context. if *modifiedFlag { modified, err := buildutil.ParseOverlayArchive(os.Stdin) if err != nil { log.Fatal(err) } // All I/O done by guru needs to consult the modified map. // The ReadFile done by referrers does, // but the loader's cgo preprocessing currently does not. if len(modified) > 0 { ctxt = buildutil.OverlayContext(ctxt, modified) } } var outputMu sync.Mutex output := func(fset *token.FileSet, qr QueryResult) { outputMu.Lock() defer outputMu.Unlock() if *jsonFlag { // JSON output fmt.Printf("%s\n", qr.JSON(fset)) } else { // plain output printf := func(pos interface{}, format string, args ...interface{}) { fprintf(os.Stdout, fset, pos, format, args...) } qr.PrintPlain(printf) } } // Avoid corner case of split(""). var scope []string if *scopeFlag != "" { scope = strings.Split(*scopeFlag, ",") } // Ask the guru. query := Query{ Pos: posn, Build: ctxt, Scope: scope, PTALog: ptalog, Reflection: *reflectFlag, Output: output, } if err := Run(mode, &query); err != nil { log.Fatal(err) } }