func read(path string) (*fsm.Adapter, *partition.Partition) {
	// Read file and construct FSM
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	a := fsm.NewAdapter(fsm.DotParser{})
	a.Scan(bufio.NewScanner(f))
	m := a.FSM()
	states, inputs, outputs := m.States(), m.Inputs(), m.Outputs()

	// Construct transition (f) and output (g) functions
	fs := make([]func(int) int, 0, inputs)
	gs := make([]func(int) int, 0, inputs)
	for input := 0; input < inputs; input++ {
		f, _ := m.TransitionFunction(input)
		fs = append(fs, f)
		g, _ := m.OutputFunction(input)
		gs = append(gs, g)
	}

	// Construct the partition
	p := partition.New(states, outputs, gs...)
	p.Refine(0, fs...)

	// Print results
	var not string
	if p.Size() != states {
		not = "not "
	}
	fmt.Printf("FSM %s is %sminimal.\n", path, not)

	return a, p
}
func main() {
	fnopt := flag.String("f", "", "C source code")
	flag.Parse()
	fn := *fnopt

	// Read dot file
	if fn == "" {
		fn = "/dev/stdin"
	}
	f, err := os.Open(fn)
	if err != nil {
		panic(err)
	}

	// Construct fsm
	a := fsm.NewAdapter(fsm.DotParser{})
	a.Scan(bufio.NewScanner(f))
	m := a.FSM()
	states, inputs := m.States(), m.Inputs()

	// Print state, input and output sets in header
	fmt.Println("// states:", a.States())
	fmt.Println("// inputs:", a.Inputs())
	fmt.Println("// outputs:", a.Outputs())

	// Print program header header for c file
	fmt.Println(header)

	// Print switch function for each input
	for state := 0; state < states; state++ {
		fmt.Printf("int step_state_%d(int input) {\n\tswitch (input) {", state)
		for input := 0; input < inputs; input++ {
			output, target, err := m.Transition(state, input)
			if err != nil {
				panic(err)
			}
			fmt.Printf("\n\t\tcase %d:\n\t\t\tcurrent_state = %d;\n\t\t\treturn %d;", input, target, output)
		}
		fmt.Println(epilogue)
	}

	// Print switch for each state
	fmt.Println("int step(int input) {\n\tswitch (current_state) {")
	for state := 0; state < states; state++ {
		fmt.Printf("\t\tcase %d:\n\t\t\treturn step_state_%d(input);\n", state, state)
	}
	fmt.Println(epilogue)

	// Print footer
	fmt.Println(footer)
}