Add support for exporting to tsv, in addtion to csv

Helpful when symbols can contain commas.
diff --git a/README.md b/README.md
index 1f4fa3c..11ed7dd 100644
--- a/README.md
+++ b/README.md
@@ -133,6 +133,7 @@
 Options:
 
   --csv              Output in CSV format instead of human-readable.
+  --tsv              Output in TSV format instead of human-readable.
   -c <file>          Load configuration from <file>.
   -d <sources>       Comma-separated list of sources to scan.
   -C <mode>          How to demangle symbols.  Possible values are:
diff --git a/src/bloaty.cc b/src/bloaty.cc
index 8834c0c..4d4b21d 100644
--- a/src/bloaty.cc
+++ b/src/bloaty.cc
@@ -758,7 +758,7 @@
 
 void RollupOutput::PrintRowToCSV(const RollupRow& row,
                                  std::vector<std::string> parent_labels,
-                                 std::ostream* out) const {
+                                 std::ostream* out, bool tabs) const {
   while (parent_labels.size() < source_names_.size()) {
     // If this label had no data at this level, append an empty string.
     parent_labels.push_back("");
@@ -767,29 +767,31 @@
   parent_labels.push_back(std::to_string(row.vmsize));
   parent_labels.push_back(std::to_string(row.filesize));
 
-  *out << absl::StrJoin(parent_labels, ",") << "\n";
+  std::string sep = tabs ? "\t" : ",";
+  *out << absl::StrJoin(parent_labels, sep) << "\n";
 }
 
 void RollupOutput::PrintTreeToCSV(const RollupRow& row,
                                   std::vector<std::string> parent_labels,
-                                  std::ostream* out) const {
+                                  std::ostream* out, bool tabs) const {
   parent_labels.push_back(row.name);
   if (row.sorted_children.size() > 0) {
     for (const auto& child_row : row.sorted_children) {
-      PrintTreeToCSV(child_row, parent_labels, out);
+      PrintTreeToCSV(child_row, parent_labels, out, tabs);
     }
   } else {
-    PrintRowToCSV(row, parent_labels, out);
+    PrintRowToCSV(row, parent_labels, out, tabs);
   }
 }
 
-void RollupOutput::PrintToCSV(std::ostream* out) const {
+void RollupOutput::PrintToCSV(std::ostream* out, bool tabs) const {
   std::vector<std::string> names(source_names_);
   names.push_back("vmsize");
   names.push_back("filesize");
-  *out << absl::StrJoin(names, ",") << "\n";
+  std::string sep = tabs ? "\t" : ",";
+  *out << absl::StrJoin(names, sep) << "\n";
   for (const auto& child_row : toplevel_row_.sorted_children) {
-    PrintTreeToCSV(child_row, std::vector<std::string>(), out);
+    PrintTreeToCSV(child_row, std::vector<std::string>(), out, tabs);
   }
 }
 
@@ -1631,6 +1633,7 @@
 Options:
 
   --csv              Output in CSV format instead of human-readable.
+  --tsv              Output in TSV format instead of human-readable.
   -c FILE            Load configuration from <file>.
   -d SOURCE,SOURCE   Comma-separated list of sources to scan.
   --debug-file=FILE  Use this file for debug symbols and/or symbol table.
@@ -1780,6 +1783,8 @@
       saw_separator = true;
     } else if (args.TryParseFlag("--csv")) {
       output_options->output_format = OutputFormat::kCSV;
+    } else if (args.TryParseFlag("--tsv")) {
+      output_options->output_format = OutputFormat::kTSV;
     } else if (args.TryParseOption("-c", &option)) {
       std::ifstream input_file(std::string(option), std::ios::in);
       if (!input_file.is_open()) {
diff --git a/src/bloaty.h b/src/bloaty.h
index 8f6f8e3..e202d8a 100644
--- a/src/bloaty.h
+++ b/src/bloaty.h
@@ -442,6 +442,7 @@
 enum class OutputFormat {
   kPrettyPrint,
   kCSV,
+  kTSV,
 };
 
 struct OutputOptions {
@@ -468,6 +469,9 @@
         case bloaty::OutputFormat::kCSV:
           PrintToCSV(out);
           break;
+        case bloaty::OutputFormat::kTSV:
+          PrintToCSV(out, /*tabs=*/true);
+          break;
         default:
           BLOATY_UNREACHABLE();
       }
@@ -500,7 +504,7 @@
   bool diff_mode_ = false;
 
   void PrettyPrint(size_t max_label_len, std::ostream* out) const;
-  void PrintToCSV(std::ostream* out) const;
+  void PrintToCSV(std::ostream* out, bool tabs=false) const;
   size_t CalculateLongestLabel(const RollupRow& row, int indent) const;
   void PrettyPrintRow(const RollupRow& row, size_t indent, size_t longest_row,
                       std::ostream* out) const;
@@ -508,10 +512,10 @@
                        std::ostream* out) const;
   void PrintRowToCSV(const RollupRow& row,
                      std::vector<std::string> parent_labels,
-                     std::ostream* out) const;
+                     std::ostream* out, bool tabs=false) const;
   void PrintTreeToCSV(const RollupRow& row,
                       std::vector<std::string> parent_labels,
-                      std::ostream* out) const;
+                      std::ostream* out, bool tabs=false) const;
 };
 
 bool ParseOptions(bool skip_unknown, int* argc, char** argv[], Options* options,