| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| /* | |
| The flag package implements command-line flag parsing. | |
| Usage: | |
| 1) Define flags using flag.String(), Bool(), Int(), etc. Example: | |
| import "flag" | |
| var ip *int = flag.Int("flagname", 1234, "help message for flagname") | |
| If you like, you can bind the flag to a variable using the Var() functions. | |
| var flagvar int | |
| func init() { | |
| flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") | |
| } | |
| 2) After all flags are defined, call | |
| flag.Parse() | |
| to parse the command line into the defined flags. | |
| 3) Flags may then be used directly. If you're using the flags themselves, | |
| they are all pointers; if you bind to variables, they're values. | |
| fmt.Println("ip has value ", *ip); | |
| fmt.Println("flagvar has value ", flagvar); | |
| 4) After parsing, flag.Arg(i) is the i'th argument after the flags. | |
| Args are indexed from 0 up to flag.NArg(). | |
| Command line flag syntax: | |
| -flag | |
| -flag=x | |
| -flag x // non-boolean flags only | |
| One or two minus signs may be used; they are equivalent. | |
| The last form is not permitted for boolean flags because the | |
| meaning of the command | |
| cmd -x * | |
| will change if there is a file called 0, false, etc. You must | |
| use the -flag=false form to turn off a boolean flag. | |
| Flag parsing stops just before the first non-flag argument | |
| ("-" is a non-flag argument) or after the terminator "--". | |
| Integer flags accept 1234, 0664, 0x1234 and may be negative. | |
| Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. | |
| */ | |
| package flag | |
| import ( | |
| "fmt" | |
| "os" | |
| "strconv" | |
| ) | |
| // -- Bool Value | |
| type boolValue struct { | |
| p *bool | |
| } | |
| func newBoolValue(val bool, p *bool) *boolValue { | |
| *p = val | |
| return &boolValue{p} | |
| } | |
| func (b *boolValue) set(s string) bool { | |
| v, err := strconv.Atob(s) | |
| *b.p = v | |
| return err == nil | |
| } | |
| func (b *boolValue) String() string { return fmt.Sprintf("%v", *b.p) } | |
| // -- Int Value | |
| type intValue struct { | |
| p *int | |
| } | |
| func newIntValue(val int, p *int) *intValue { | |
| *p = val | |
| return &intValue{p} | |
| } | |
| func (i *intValue) set(s string) bool { | |
| v, err := strconv.Atoi(s) | |
| *i.p = int(v) | |
| return err == nil | |
| } | |
| func (i *intValue) String() string { return fmt.Sprintf("%v", *i.p) } | |
| // -- Int64 Value | |
| type int64Value struct { | |
| p *int64 | |
| } | |
| func newInt64Value(val int64, p *int64) *int64Value { | |
| *p = val | |
| return &int64Value{p} | |
| } | |
| func (i *int64Value) set(s string) bool { | |
| v, err := strconv.Atoi64(s) | |
| *i.p = v | |
| return err == nil | |
| } | |
| func (i *int64Value) String() string { return fmt.Sprintf("%v", *i.p) } | |
| // -- Uint Value | |
| type uintValue struct { | |
| p *uint | |
| } | |
| func newUintValue(val uint, p *uint) *uintValue { | |
| *p = val | |
| return &uintValue{p} | |
| } | |
| func (i *uintValue) set(s string) bool { | |
| v, err := strconv.Atoui(s) | |
| *i.p = uint(v) | |
| return err == nil | |
| } | |
| func (i *uintValue) String() string { return fmt.Sprintf("%v", *i.p) } | |
| // -- uint64 Value | |
| type uint64Value struct { | |
| p *uint64 | |
| } | |
| func newUint64Value(val uint64, p *uint64) *uint64Value { | |
| *p = val | |
| return &uint64Value{p} | |
| } | |
| func (i *uint64Value) set(s string) bool { | |
| v, err := strconv.Atoui64(s) | |
| *i.p = uint64(v) | |
| return err == nil | |
| } | |
| func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i.p) } | |
| // -- string Value | |
| type stringValue struct { | |
| p *string | |
| } | |
| func newStringValue(val string, p *string) *stringValue { | |
| *p = val | |
| return &stringValue{p} | |
| } | |
| func (s *stringValue) set(val string) bool { | |
| *s.p = val | |
| return true | |
| } | |
| func (s *stringValue) String() string { return fmt.Sprintf("%s", *s.p) } | |
| // -- Float Value | |
| type floatValue struct { | |
| p *float | |
| } | |
| func newFloatValue(val float, p *float) *floatValue { | |
| *p = val | |
| return &floatValue{p} | |
| } | |
| func (f *floatValue) set(s string) bool { | |
| v, err := strconv.Atof(s) | |
| *f.p = v | |
| return err == nil | |
| } | |
| func (f *floatValue) String() string { return fmt.Sprintf("%v", *f.p) } | |
| // -- Float64 Value | |
| type float64Value struct { | |
| p *float64 | |
| } | |
| func newFloat64Value(val float64, p *float64) *float64Value { | |
| *p = val | |
| return &float64Value{p} | |
| } | |
| func (f *float64Value) set(s string) bool { | |
| v, err := strconv.Atof64(s) | |
| *f.p = v | |
| return err == nil | |
| } | |
| func (f *float64Value) String() string { return fmt.Sprintf("%v", *f.p) } | |
| // FlagValue is the interface to the dynamic value stored in a flag. | |
| // (The default value is represented as a string.) | |
| type FlagValue interface { | |
| String() string | |
| set(string) bool | |
| } | |
| // A Flag represents the state of a flag. | |
| type Flag struct { | |
| Name string // name as it appears on command line | |
| Usage string // help message | |
| Value FlagValue // value as set | |
| DefValue string // default value (as text); for usage message | |
| } | |
| type allFlags struct { | |
| actual map[string]*Flag | |
| formal map[string]*Flag | |
| first_arg int // 0 is the program name, 1 is first arg | |
| } | |
| var flags *allFlags = &allFlags{make(map[string]*Flag), make(map[string]*Flag), 1} | |
| // VisitAll visits the flags, calling fn for each. It visits all flags, even those not set. | |
| func VisitAll(fn func(*Flag)) { | |
| for _, f := range flags.formal { | |
| fn(f) | |
| } | |
| } | |
| // Visit visits the flags, calling fn for each. It visits only those flags that have been set. | |
| func Visit(fn func(*Flag)) { | |
| for _, f := range flags.actual { | |
| fn(f) | |
| } | |
| } | |
| // Lookup returns the Flag structure of the named flag, returning nil if none exists. | |
| func Lookup(name string) *Flag { | |
| f, ok := flags.formal[name] | |
| if !ok { | |
| return nil | |
| } | |
| return f | |
| } | |
| // Set sets the value of the named flag. It returns true if the set succeeded; false if | |
| // there is no such flag defined. | |
| func Set(name, value string) bool { | |
| f, ok := flags.formal[name] | |
| if !ok { | |
| return false | |
| } | |
| ok = f.Value.set(value) | |
| if !ok { | |
| return false | |
| } | |
| flags.actual[name] = f | |
| return true | |
| } | |
| // PrintDefaults prints to standard error the default values of all defined flags. | |
| func PrintDefaults() { | |
| VisitAll(func(f *Flag) { | |
| format := " -%s=%s: %s\n" | |
| if _, ok := f.Value.(*stringValue); ok { | |
| // put quotes on the value | |
| format = " -%s=%q: %s\n" | |
| } | |
| fmt.Fprintf(os.Stderr, format, f.Name, f.DefValue, f.Usage) | |
| }) | |
| } | |
| // Usage prints to standard error a default usage message documenting all defined flags. | |
| // The function is a variable that may be changed to point to a custom function. | |
| var Usage = func() { | |
| fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) | |
| PrintDefaults() | |
| } | |
| func NFlag() int { return len(flags.actual) } | |
| // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument | |
| // after flags have been processed. | |
| func Arg(i int) string { | |
| i += flags.first_arg | |
| if i < 0 || i >= len(os.Args) { | |
| return "" | |
| } | |
| return os.Args[i] | |
| } | |
| // NArg is the number of arguments remaining after flags have been processed. | |
| func NArg() int { return len(os.Args) - flags.first_arg } | |
| // Args returns the non-flag command-line arguments. | |
| func Args() []string { return os.Args[flags.first_arg:] } | |
| func add(name string, value FlagValue, usage string) { | |
| // Remember the default value as a string; it won't change. | |
| f := &Flag{name, usage, value, value.String()} | |
| _, alreadythere := flags.formal[name] | |
| if alreadythere { | |
| fmt.Fprintln(os.Stderr, "flag redefined:", name) | |
| panic("flag redefinition") // Happens only if flags are declared with identical names | |
| } | |
| flags.formal[name] = f | |
| } | |
| // BoolVar defines a bool flag with specified name, default value, and usage string. | |
| // The argument p points to a bool variable in which to store the value of the flag. | |
| func BoolVar(p *bool, name string, value bool, usage string) { | |
| add(name, newBoolValue(value, p), usage) | |
| } | |
| // Bool defines a bool flag with specified name, default value, and usage string. | |
| // The return value is the address of a bool variable that stores the value of the flag. | |
| func Bool(name string, value bool, usage string) *bool { | |
| p := new(bool) | |
| BoolVar(p, name, value, usage) | |
| return p | |
| } | |
| // IntVar defines an int flag with specified name, default value, and usage string. | |
| // The argument p points to an int variable in which to store the value of the flag. | |
| func IntVar(p *int, name string, value int, usage string) { | |
| add(name, newIntValue(value, p), usage) | |
| } | |
| // Int defines an int flag with specified name, default value, and usage string. | |
| // The return value is the address of an int variable that stores the value of the flag. | |
| func Int(name string, value int, usage string) *int { | |
| p := new(int) | |
| IntVar(p, name, value, usage) | |
| return p | |
| } | |
| // Int64Var defines an int64 flag with specified name, default value, and usage string. | |
| // The argument p points to an int64 variable in which to store the value of the flag. | |
| func Int64Var(p *int64, name string, value int64, usage string) { | |
| add(name, newInt64Value(value, p), usage) | |
| } | |
| // Int64 defines an int64 flag with specified name, default value, and usage string. | |
| // The return value is the address of an int64 variable that stores the value of the flag. | |
| func Int64(name string, value int64, usage string) *int64 { | |
| p := new(int64) | |
| Int64Var(p, name, value, usage) | |
| return p | |
| } | |
| // UintVar defines a uint flag with specified name, default value, and usage string. | |
| // The argument p points to a uint variable in which to store the value of the flag. | |
| func UintVar(p *uint, name string, value uint, usage string) { | |
| add(name, newUintValue(value, p), usage) | |
| } | |
| // Uint defines a uint flag with specified name, default value, and usage string. | |
| // The return value is the address of a uint variable that stores the value of the flag. | |
| func Uint(name string, value uint, usage string) *uint { | |
| p := new(uint) | |
| UintVar(p, name, value, usage) | |
| return p | |
| } | |
| // Uint64Var defines a uint64 flag with specified name, default value, and usage string. | |
| // The argument p points to a uint64 variable in which to store the value of the flag. | |
| func Uint64Var(p *uint64, name string, value uint64, usage string) { | |
| add(name, newUint64Value(value, p), usage) | |
| } | |
| // Uint64 defines a uint64 flag with specified name, default value, and usage string. | |
| // The return value is the address of a uint64 variable that stores the value of the flag. | |
| func Uint64(name string, value uint64, usage string) *uint64 { | |
| p := new(uint64) | |
| Uint64Var(p, name, value, usage) | |
| return p | |
| } | |
| // StringVar defines a string flag with specified name, default value, and usage string. | |
| // The argument p points to a string variable in which to store the value of the flag. | |
| func StringVar(p *string, name, value string, usage string) { | |
| add(name, newStringValue(value, p), usage) | |
| } | |
| // String defines a string flag with specified name, default value, and usage string. | |
| // The return value is the address of a string variable that stores the value of the flag. | |
| func String(name, value string, usage string) *string { | |
| p := new(string) | |
| StringVar(p, name, value, usage) | |
| return p | |
| } | |
| // FloatVar defines a float flag with specified name, default value, and usage string. | |
| // The argument p points to a float variable in which to store the value of the flag. | |
| func FloatVar(p *float, name string, value float, usage string) { | |
| add(name, newFloatValue(value, p), usage) | |
| } | |
| // Float defines a float flag with specified name, default value, and usage string. | |
| // The return value is the address of a float variable that stores the value of the flag. | |
| func Float(name string, value float, usage string) *float { | |
| p := new(float) | |
| FloatVar(p, name, value, usage) | |
| return p | |
| } | |
| // Float64Var defines a float64 flag with specified name, default value, and usage string. | |
| // The argument p points to a float64 variable in which to store the value of the flag. | |
| func Float64Var(p *float64, name string, value float64, usage string) { | |
| add(name, newFloat64Value(value, p), usage) | |
| } | |
| // Float64 defines a float64 flag with specified name, default value, and usage string. | |
| // The return value is the address of a float64 variable that stores the value of the flag. | |
| func Float64(name string, value float64, usage string) *float64 { | |
| p := new(float64) | |
| Float64Var(p, name, value, usage) | |
| return p | |
| } | |
| func (f *allFlags) parseOne(index int) (ok bool, next int) { | |
| s := os.Args[index] | |
| f.first_arg = index // until proven otherwise | |
| if len(s) == 0 { | |
| return false, -1 | |
| } | |
| if s[0] != '-' { | |
| return false, -1 | |
| } | |
| num_minuses := 1 | |
| if len(s) == 1 { | |
| return false, index | |
| } | |
| if s[1] == '-' { | |
| num_minuses++ | |
| if len(s) == 2 { // "--" terminates the flags | |
| return false, index + 1 | |
| } | |
| } | |
| name := s[num_minuses:] | |
| if len(name) == 0 || name[0] == '-' || name[0] == '=' { | |
| fmt.Fprintln(os.Stderr, "bad flag syntax:", s) | |
| Usage() | |
| os.Exit(2) | |
| } | |
| // it's a flag. does it have an argument? | |
| has_value := false | |
| value := "" | |
| for i := 1; i < len(name); i++ { // equals cannot be first | |
| if name[i] == '=' { | |
| value = name[i+1:] | |
| has_value = true | |
| name = name[0:i] | |
| break | |
| } | |
| } | |
| flag, alreadythere := flags.actual[name] | |
| if alreadythere { | |
| fmt.Fprintf(os.Stderr, "flag specified twice: -%s\n", name) | |
| Usage() | |
| os.Exit(2) | |
| } | |
| m := flags.formal | |
| flag, alreadythere = m[name] // BUG | |
| if !alreadythere { | |
| fmt.Fprintf(os.Stderr, "flag provided but not defined: -%s\n", name) | |
| Usage() | |
| os.Exit(2) | |
| } | |
| if f, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg | |
| if has_value { | |
| if !f.set(value) { | |
| fmt.Fprintf(os.Stderr, "invalid boolean value %t for flag: -%s\n", value, name) | |
| Usage() | |
| os.Exit(2) | |
| } | |
| } else { | |
| f.set("true") | |
| } | |
| } else { | |
| // It must have a value, which might be the next argument. | |
| if !has_value && index < len(os.Args)-1 { | |
| // value is the next arg | |
| has_value = true | |
| index++ | |
| value = os.Args[index] | |
| } | |
| if !has_value { | |
| fmt.Fprintf(os.Stderr, "flag needs an argument: -%s\n", name) | |
| Usage() | |
| os.Exit(2) | |
| } | |
| ok = flag.Value.set(value) | |
| if !ok { | |
| fmt.Fprintf(os.Stderr, "invalid value %s for flag: -%s\n", value, name) | |
| Usage() | |
| os.Exit(2) | |
| } | |
| } | |
| flags.actual[name] = flag | |
| return true, index + 1 | |
| } | |
| // Parse parses the command-line flags. Must be called after all flags are defined | |
| // and before any are accessed by the program. | |
| func Parse() { | |
| for i := 1; i < len(os.Args); { | |
| ok, next := flags.parseOne(i) | |
| if next > 0 { | |
| flags.first_arg = next | |
| i = next | |
| } | |
| if !ok { | |
| break | |
| } | |
| } | |
| } |