Add dumbindent.Options (tabs vs spaces)
diff --git a/cmd/dumbindent/main.go b/cmd/dumbindent/main.go
index b171d5c..3aa985f 100644
--- a/cmd/dumbindent/main.go
+++ b/cmd/dumbindent/main.go
@@ -42,8 +42,6 @@
 // user    0m0.005s
 // sys     0m0.005s
 // ----
-//
-// There are no configuration options (e.g. tabs versus spaces).
 package main
 
 import (
@@ -64,6 +62,9 @@
 var (
 	lFlag = flag.Bool("l", false, "list files whose formatting differs from dumbindent's")
 	wFlag = flag.Bool("w", false, "write result to (source) file instead of stdout")
+
+	spacesFlag = flag.Int("spaces", 2, "the number of spaces per indent")
+	tabsFlag   = flag.Bool("tabs", false, "indent with a tab instead of spaces")
 )
 
 func usage() {
@@ -142,7 +143,10 @@
 		return err
 	}
 
-	dst := dumbindent.FormatBytes(nil, src)
+	dst := dumbindent.FormatBytes(nil, src, &dumbindent.Options{
+		Spaces: *spacesFlag,
+		Tabs:   *tabsFlag,
+	})
 
 	if r != nil {
 		if _, err := os.Stdout.Write(dst); err != nil {
diff --git a/internal/cgen/cgen.go b/internal/cgen/cgen.go
index b06f000..c5204ba 100644
--- a/internal/cgen/cgen.go
+++ b/internal/cgen/cgen.go
@@ -181,7 +181,7 @@
 			return unformatted, nil
 		}
 
-		return dumbindent.FormatBytes(nil, unformatted), nil
+		return dumbindent.FormatBytes(nil, unformatted, nil), nil
 	})
 }
 
diff --git a/lib/dumbindent/dumbindent.go b/lib/dumbindent/dumbindent.go
index 5b3fd36..647dbb2 100644
--- a/lib/dumbindent/dumbindent.go
+++ b/lib/dumbindent/dumbindent.go
@@ -25,8 +25,6 @@
 //
 // See `cmd/dumbindent/main.go` in this repository for an example where
 // `dumbindent` was 80 times faster than `clang-format`.
-//
-// There are no configuration options (e.g. tabs versus spaces).
 package dumbindent
 
 import (
@@ -37,8 +35,10 @@
 var (
 	backTick  = []byte("`")
 	externC   = []byte("extern \"C\"")
-	spaces    = []byte("                                ")
 	starSlash = []byte("*/")
+
+	spaces = []byte("                                ")
+	tabs   = []byte("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")
 )
 
 // hangingBytes is a look-up table for updating the hanging variable.
@@ -47,13 +47,28 @@
 	'\\': true,
 }
 
+// Options are formatting options.
+type Options struct {
+	// Spaces, if positive, is the number of spaces per indentation level. A
+	// non-positive value means to use the default: 2 spaces per indent.
+	//
+	// This field is ignored when Tabs is true.
+	Spaces int
+
+	// Tabs is whether to indent with tabs instead of spaces. If true, it's one
+	// '\t' tab character per indent and the Spaces field is ignored.
+	Tabs bool
+}
+
 // FormatBytes formats the C (or C-like) program in src, appending the result
 // to dst, and returns that longer slice.
 //
 // It is valid to pass a dst slice (such as nil) whose unused capacity
 // (cap(dst) - len(dst)) is too short to hold the formatted program. In this
 // case, a new slice will be allocated and returned.
-func FormatBytes(dst []byte, src []byte) []byte {
+//
+// Passing a nil opts means to use the default options.
+func FormatBytes(dst []byte, src []byte, opts *Options) []byte {
 	src = trimLeadingWhiteSpaceAndNewLines(src)
 	if len(src) == 0 {
 		return dst
@@ -61,6 +76,17 @@
 		dst = make([]byte, 0, len(src)+(len(src)/2))
 	}
 
+	indentBytes := spaces
+	indentCount := 2
+	if opts != nil {
+		if opts.Tabs {
+			indentBytes = tabs
+			indentCount = 1
+		} else if opts.Spaces > 0 {
+			indentCount = opts.Spaces
+		}
+	}
+
 	nBraces := 0       // The number of unbalanced '{'s.
 	nParens := 0       // The number of unbalanced '('s.
 	openBrace := false // Whether the previous non-blank line ends with '{'.
@@ -118,17 +144,17 @@
 		// "clang-format -style=Chromium" indentation style.
 		indent := 0
 		if nBraces > 0 {
-			indent += 2 * nBraces
+			indent += indentCount * nBraces
 		}
 		if (nParens > 0) || hanging {
-			indent += 4
+			indent += indentCount * 2
 		}
 		for indent > 0 {
 			n := indent
-			if n > len(spaces) {
-				n = len(spaces)
+			if n > len(indentBytes) {
+				n = len(indentBytes)
 			}
-			dst = append(dst, spaces[:n]...)
+			dst = append(dst, indentBytes[:n]...)
 			indent -= n
 		}
 
diff --git a/lib/dumbindent/dumbindent_test.go b/lib/dumbindent/dumbindent_test.go
index b54a64c..df75128 100644
--- a/lib/dumbindent/dumbindent_test.go
+++ b/lib/dumbindent/dumbindent_test.go
@@ -78,12 +78,21 @@
 	}}
 
 	for i, tc := range testCases {
-		if got := string(FormatBytes(nil, []byte(tc.src))); got != tc.want {
+		if got := string(FormatBytes(nil, []byte(tc.src), nil)); got != tc.want {
 			tt.Fatalf("i=%d, src=%q:\ngot  %q\nwant %q", i, tc.src, got, tc.want)
 		}
 	}
 }
 
+func TestTabs(tt *testing.T) {
+	const src = "a {\nb\n}\n"
+	got := string(FormatBytes(nil, []byte(src), &Options{Tabs: true}))
+	want := "a {\n\tb\n}\n"
+	if got != want {
+		tt.Fatalf("\ngot  %q\nwant %q", got, want)
+	}
+}
+
 func ExampleFormatBytes() {
 	const src = `
 // Blah blah blah.
@@ -95,7 +104,7 @@
 }
 `
 
-	os.Stdout.Write(FormatBytes(nil, []byte(src)))
+	os.Stdout.Write(FormatBytes(nil, []byte(src), nil))
 
 	// Output:
 	// // Blah blah blah.