package main import ( "fmt" "os" "flag" "log" "bufio" ) func Fail(err error, format string, v ...any) { err_format := fmt.Sprintf("ERROR: %v; %s", err, format) log.Printf(err_format, v...) os.Exit(1) } type Opts struct { Width int Filenames []string Hex bool Octal bool Format string } func parse_opts() (Opts) { var opts Opts flag.IntVar(&opts.Width, "w", 16, "Width of output grid") flag.BoolVar(&opts.Hex, "x", false, "Output hex bytes") flag.BoolVar(&opts.Octal, "o", false, "Output octal bytes") flag.Parse() if flag.NArg() == 0 { log.Fatal("USAGE: od [files]") os.Exit(1) } if opts.Hex { opts.Format = "%0.2x " } else { opts.Format = "%0.3o " } opts.Filenames = flag.Args() return opts } func main() { opts := parse_opts() for _, filename := range opts.Filenames { reader, err := os.Open(filename) defer reader.Close() if err != nil { Fail(err, "can't open: %s", filename) } buf := bufio.NewReader(reader) count := buf.Size() fmt.Printf("%0.8o ", 0); for index := 0; index < count; index++ { data, err := buf.ReadByte() if err != nil { break } fmt.Printf(opts.Format, data); if (index + 1) % opts.Width == 0 { fmt.Print("\n") fmt.Printf("%0.8o ", index); } } } }