Пример #1
0
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())
	}
}
Пример #2
0
func TestParseOverlayArchive(t *testing.T) {
	var tt = []struct {
		in     string
		out    map[string][]byte
		hasErr bool
	}{
		{
			"a.go\n5\n12345",
			map[string][]byte{"a.go": []byte("12345")},
			false,
		},
		{
			"a.go\n5\n1234",
			nil,
			true,
		},
		{
			"a.go\n5\n12345b.go\n4\n1234",
			map[string][]byte{"a.go": []byte("12345"), "b.go": []byte("1234")},
			false,
		},
	}

	for _, test := range tt {
		got, err := buildutil.ParseOverlayArchive(strings.NewReader(test.in))
		if err == nil && test.hasErr {
			t.Errorf("expected error for %q", test.in)
		}
		if err != nil && !test.hasErr {
			t.Errorf("unexpected error %v for %q", err, test.in)
		}
		if !reflect.DeepEqual(got, test.out) {
			t.Errorf("got %#v, want %#v", got, test.out)
		}
	}
}
Пример #3
0
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)
	}
}