func generateTagRootsLeaves(prof *profile.Profile, cfg config, ui plugin.UI) {
	tagRootLabelKeys := dropEmptyStrings(strings.Split(cfg.TagRoot, ","))
	tagLeafLabelKeys := dropEmptyStrings(strings.Split(cfg.TagLeaf, ","))
	rootm, leafm := addLabelNodes(prof, tagRootLabelKeys, tagLeafLabelKeys, cfg.Unit)
	warnNoMatches(cfg.TagRoot == "" || rootm, "TagRoot", ui)
	warnNoMatches(cfg.TagLeaf == "" || leafm, "TagLeaf", ui)
}
generateTagRootsLeaves generates extra nodes from the tagroot and tagleaf options.
package driver
import (
	"bytes"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"github.com/google/pprof/internal/plugin"
	"github.com/google/pprof/internal/report"
	"github.com/google/pprof/profile"
)
func PProf(eo *plugin.Options) error {
	defer cleanupTempFiles()
	o := setDefaults(eo)
	src, cmd, err := parseFlags(o)
	if err != nil {
		return err
	}
	p, err := fetchProfiles(src, o)
	if err != nil {
		return err
	}
	if cmd != nil {
		return generateReport(p, cmd, currentConfig(), o)
	}
	if src.HTTPHostport != "" {
		return serveWebInterface(src.HTTPHostport, p, o, src.HTTPDisableBrowser)
	}
	return interactive(p, o)
}
func generateRawReport(p *profile.Profile, cmd []string, cfg config, o *plugin.Options) (*command, *report.Report, error) {
	p = p.Copy()  
	numLabelUnits := identifyNumLabelUnits(p, o.UI)
	c := pprofCommands[cmd[0]]
	if c == nil {
		panic("unexpected nil command")
	}
	cfg = applyCommandOverrides(cmd[0], c.format, cfg)
	generateTagRootsLeaves(p, cfg, o.UI)
	relative := cfg.RelativePercentages
	if relative {
		if err := applyFocus(p, numLabelUnits, cfg, o.UI); err != nil {
			return nil, nil, err
		}
	}
	ropt, err := reportOptions(p, numLabelUnits, cfg)
	if err != nil {
		return nil, nil, err
	}
	ropt.OutputFormat = c.format
	if len(cmd) == 2 {
		s, err := regexp.Compile(cmd[1])
		if err != nil {
			return nil, nil, fmt.Errorf("parsing argument regexp %s: %v", cmd[1], err)
		}
		ropt.Symbol = s
	}
	rpt := report.New(p, ropt)
	if !relative {
		if err := applyFocus(p, numLabelUnits, cfg, o.UI); err != nil {
			return nil, nil, err
		}
	}
	if err := aggregate(p, cfg); err != nil {
		return nil, nil, err
	}
	return c, rpt, nil
}
func generateReport(p *profile.Profile, cmd []string, cfg config, o *plugin.Options) error {
	c, rpt, err := generateRawReport(p, cmd, cfg, o)
	if err != nil {
		return err
	}
	dst := new(bytes.Buffer)
	if err := report.Generate(dst, rpt, o.Obj); err != nil {
		return err
	}
	src := dst
	if c.postProcess != nil {
		dst = new(bytes.Buffer)
		if err := c.postProcess(src, dst, o.UI); err != nil {
			return err
		}
		src = dst
	}
	output := cfg.Output
	if output == "" {
		if c.visualizer != nil {
			return c.visualizer(src, os.Stdout, o.UI)
		}
		_, err := src.WriteTo(os.Stdout)
		return err
	}
	o.UI.PrintErr("Generating report in ", output)
	out, err := o.Writer.Open(output)
	if err != nil {
		return err
	}
	if _, err := src.WriteTo(out); err != nil {
		out.Close()
		return err
	}
	return out.Close()
}
func applyCommandOverrides(cmd string, outputFormat int, cfg config) config {
	trim := cfg.Trim
	switch cmd {
	case "disasm":
		trim = false
		cfg.Granularity = "addresses"
		cfg.NoInlines = true
	case "weblist":
		trim = false
		cfg.Granularity = "addresses"
		cfg.NoInlines = false  
	case "peek":
		trim = false
	case "list":
		trim = false
		cfg.Granularity = "lines"
	case "text", "top", "topproto":
		if cfg.NodeCount == -1 {
			cfg.NodeCount = 0
		}
	default:
		if cfg.NodeCount == -1 {
			cfg.NodeCount = 80
		}
	}
	switch outputFormat {
	case report.Proto, report.Raw, report.Callgrind:
		trim = false
		cfg.Granularity = "addresses"
		cfg.NoInlines = false
	}
	if !trim {
		cfg.NodeCount = 0
		cfg.NodeFraction = 0
		cfg.EdgeFraction = 0
	}
	return cfg
}