summaryrefslogtreecommitdiff
path: root/src/lib/flag/flag.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/flag/flag.go')
-rw-r--r--src/lib/flag/flag.go486
1 files changed, 486 insertions, 0 deletions
diff --git a/src/lib/flag/flag.go b/src/lib/flag/flag.go
new file mode 100644
index 000000000..e66238f6d
--- /dev/null
+++ b/src/lib/flag/flag.go
@@ -0,0 +1,486 @@
+// 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 "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.
+ print("ip has value ", *ip, "\n");
+ print("flagvar has value ", flagvar, "\n");
+
+ 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
+ One or two minus signs may be used; they are equivalent.
+
+ 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"
+)
+
+// BUG: atob belongs elsewhere
+func atob(str string) (value bool, ok bool) {
+ switch str {
+ case "1", "t", "T", "true", "TRUE", "True":
+ return true, true;
+ case "0", "f", "F", "false", "FALSE", "False":
+ return false, true
+ }
+ return false, false
+}
+
+type (
+ boolValue struct;
+ intValue struct;
+ int64Value struct;
+ uintValue struct;
+ uint64Value struct;
+ stringValue struct;
+)
+
+// -- 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, ok := atob(s);
+ *b.p = v;
+ return ok
+}
+
+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)
+}
+
+// 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 k, 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 k, 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 tne 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 s, 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 and
+// then calls sys.Exit(1).
+func Usage() {
+ if len(sys.Args) > 0 {
+ fmt.Fprintln(os.Stderr, "Usage of", sys.Args[0] + ":");
+ } else {
+ fmt.Fprintln(os.Stderr, "Usage:");
+ }
+ PrintDefaults();
+ sys.Exit(1);
+}
+
+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(sys.Args) {
+ return "";
+ }
+ return sys.Args[i]
+}
+
+// NArg is the number of arguments remaining after flags have been processed.
+func NArg() int {
+ return len(sys.Args) - flags.first_arg
+}
+
+// Args returns the non-flag command-line arguments.
+func Args() []string {
+ return sys.Args[flags.first_arg:len(sys.Args)];
+}
+
+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()};
+ dummy, alreadythere := flags.formal[name];
+ if alreadythere {
+ print("flag redefined: ", name, "\n");
+ 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;
+}
+
+func (f *allFlags) parseOne(index int) (ok bool, next int)
+{
+ s := sys.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 : len(s)];
+ if len(name) == 0 || name[0] == '-' || name[0] == '=' {
+ print("bad flag syntax: ", s, "\n");
+ Usage();
+ }
+
+ // 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 : len(name)];
+ has_value = true;
+ name = name[0 : i];
+ break;
+ }
+ }
+ flag, alreadythere := flags.actual[name];
+ if alreadythere {
+ print("flag specified twice: -", name, "\n");
+ Usage();
+ }
+ m := flags.formal;
+ flag, alreadythere = m[name]; // BUG
+ if !alreadythere {
+ print("flag provided but not defined: -", name, "\n");
+ Usage();
+ }
+ if f, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
+ if has_value {
+ if !f.set(value) {
+ print("invalid boolean value ", value, " for flag: -", name, "\n");
+ Usage();
+ }
+ } else {
+ f.set("true")
+ }
+ } else {
+ // It must have a value, which might be the next argument.
+ if !has_value && index < len(sys.Args)-1 {
+ // value is the next arg
+ has_value = true;
+ index++;
+ value = sys.Args[index];
+ }
+ if !has_value {
+ print("flag needs an argument: -", name, "\n");
+ Usage();
+ }
+ ok = flag.Value.set(value);
+ if !ok {
+ print("invalid value ", value, " for flag: -", name, "\n");
+ Usage();
+ }
+ }
+ 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(sys.Args); {
+ ok, next := flags.parseOne(i);
+ if next > 0 {
+ flags.first_arg = next;
+ i = next;
+ }
+ if !ok {
+ break
+ }
+ }
+}