Source file src/flag/flag.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6  Package flag implements command-line flag parsing.
     7  
     8  # Usage
     9  
    10  Define flags using [flag.String], [Bool], [Int], etc.
    11  
    12  This declares an integer flag, -n, stored in the pointer nFlag, with type *int:
    13  
    14  	import "flag"
    15  	var nFlag = flag.Int("n", 1234, "help message for flag n")
    16  
    17  If you like, you can bind the flag to a variable using the Var() functions.
    18  
    19  	var flagvar int
    20  	func init() {
    21  		flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
    22  	}
    23  
    24  Or you can create custom flags that satisfy the Value interface (with
    25  pointer receivers) and couple them to flag parsing by
    26  
    27  	flag.Var(&flagVal, "name", "help message for flagname")
    28  
    29  For such flags, the default value is just the initial value of the variable.
    30  
    31  After all flags are defined, call
    32  
    33  	flag.Parse()
    34  
    35  to parse the command line into the defined flags.
    36  
    37  Flags may then be used directly. If you're using the flags themselves,
    38  they are all pointers; if you bind to variables, they're values.
    39  
    40  	fmt.Println("ip has value ", *ip)
    41  	fmt.Println("flagvar has value ", flagvar)
    42  
    43  After parsing, the arguments following the flags are available as the
    44  slice [flag.Args] or individually as [flag.Arg](i).
    45  The arguments are indexed from 0 through [flag.NArg]-1.
    46  
    47  # Command line flag syntax
    48  
    49  The following forms are permitted:
    50  
    51  	-flag
    52  	--flag   // double dashes are also permitted
    53  	-flag=x
    54  	-flag x  // non-boolean flags only
    55  
    56  One or two dashes may be used; they are equivalent.
    57  The last form is not permitted for boolean flags because the
    58  meaning of the command
    59  
    60  	cmd -x *
    61  
    62  where * is a Unix shell wildcard, will change if there is a file
    63  called 0, false, etc. You must use the -flag=false form to turn
    64  off a boolean flag.
    65  
    66  Flag parsing stops just before the first non-flag argument
    67  ("-" is a non-flag argument) or after the terminator "--".
    68  
    69  Integer flags accept 1234, 0664, 0x1234 and may be negative.
    70  Boolean flags may be:
    71  
    72  	1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
    73  
    74  Duration flags accept any input valid for time.ParseDuration.
    75  
    76  The default set of command-line flags is controlled by
    77  top-level functions.  The [FlagSet] type allows one to define
    78  independent sets of flags, such as to implement subcommands
    79  in a command-line interface. The methods of [FlagSet] are
    80  analogous to the top-level functions for the command-line
    81  flag set.
    82  */
    83  package flag
    84  
    85  import (
    86  	"encoding"
    87  	"errors"
    88  	"fmt"
    89  	"io"
    90  	"iter"
    91  	"os"
    92  	"reflect"
    93  	"runtime"
    94  	"slices"
    95  	"strconv"
    96  	"strings"
    97  	"time"
    98  )
    99  
   100  // ErrHelp is the error returned if the -help or -h flag is invoked
   101  // but no such flag is defined.
   102  var ErrHelp = errors.New("flag: help requested")
   103  
   104  // errParse is returned by Set if a flag's value fails to parse, such as with an invalid integer for Int.
   105  // It then gets wrapped through failf to provide more information.
   106  var errParse = errors.New("parse error")
   107  
   108  // errRange is returned by Set if a flag's value is out of range.
   109  // It then gets wrapped through failf to provide more information.
   110  var errRange = errors.New("value out of range")
   111  
   112  func numError(err error) error {
   113  	ne, ok := err.(*strconv.NumError)
   114  	if !ok {
   115  		return err
   116  	}
   117  	if ne.Err == strconv.ErrSyntax {
   118  		return errParse
   119  	}
   120  	if ne.Err == strconv.ErrRange {
   121  		return errRange
   122  	}
   123  	return err
   124  }
   125  
   126  // -- bool Value
   127  type boolValue bool
   128  
   129  func newBoolValue(val bool, p *bool) *boolValue {
   130  	*p = val
   131  	return (*boolValue)(p)
   132  }
   133  
   134  func (b *boolValue) Set(s string) error {
   135  	v, err := strconv.ParseBool(s)
   136  	if err != nil {
   137  		err = errParse
   138  	}
   139  	*b = boolValue(v)
   140  	return err
   141  }
   142  
   143  func (b *boolValue) Get() any { return bool(*b) }
   144  
   145  func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
   146  
   147  func (b *boolValue) IsBoolFlag() bool { return true }
   148  
   149  // optional interface to indicate boolean flags that can be
   150  // supplied without "=value" text
   151  type boolFlag interface {
   152  	Value
   153  	IsBoolFlag() bool
   154  }
   155  
   156  // -- int Value
   157  type intValue int
   158  
   159  func newIntValue(val int, p *int) *intValue {
   160  	*p = val
   161  	return (*intValue)(p)
   162  }
   163  
   164  func (i *intValue) Set(s string) error {
   165  	v, err := strconv.ParseInt(s, 0, strconv.IntSize)
   166  	if err != nil {
   167  		err = numError(err)
   168  	}
   169  	*i = intValue(v)
   170  	return err
   171  }
   172  
   173  func (i *intValue) Get() any { return int(*i) }
   174  
   175  func (i *intValue) String() string { return strconv.Itoa(int(*i)) }
   176  
   177  // -- int64 Value
   178  type int64Value int64
   179  
   180  func newInt64Value(val int64, p *int64) *int64Value {
   181  	*p = val
   182  	return (*int64Value)(p)
   183  }
   184  
   185  func (i *int64Value) Set(s string) error {
   186  	v, err := strconv.ParseInt(s, 0, 64)
   187  	if err != nil {
   188  		err = numError(err)
   189  	}
   190  	*i = int64Value(v)
   191  	return err
   192  }
   193  
   194  func (i *int64Value) Get() any { return int64(*i) }
   195  
   196  func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }
   197  
   198  // -- uint Value
   199  type uintValue uint
   200  
   201  func newUintValue(val uint, p *uint) *uintValue {
   202  	*p = val
   203  	return (*uintValue)(p)
   204  }
   205  
   206  func (i *uintValue) Set(s string) error {
   207  	v, err := strconv.ParseUint(s, 0, strconv.IntSize)
   208  	if err != nil {
   209  		err = numError(err)
   210  	}
   211  	*i = uintValue(v)
   212  	return err
   213  }
   214  
   215  func (i *uintValue) Get() any { return uint(*i) }
   216  
   217  func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }
   218  
   219  // -- uint64 Value
   220  type uint64Value uint64
   221  
   222  func newUint64Value(val uint64, p *uint64) *uint64Value {
   223  	*p = val
   224  	return (*uint64Value)(p)
   225  }
   226  
   227  func (i *uint64Value) Set(s string) error {
   228  	v, err := strconv.ParseUint(s, 0, 64)
   229  	if err != nil {
   230  		err = numError(err)
   231  	}
   232  	*i = uint64Value(v)
   233  	return err
   234  }
   235  
   236  func (i *uint64Value) Get() any { return uint64(*i) }
   237  
   238  func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
   239  
   240  // -- string Value
   241  type stringValue string
   242  
   243  func newStringValue(val string, p *string) *stringValue {
   244  	*p = val
   245  	return (*stringValue)(p)
   246  }
   247  
   248  func (s *stringValue) Set(val string) error {
   249  	*s = stringValue(val)
   250  	return nil
   251  }
   252  
   253  func (s *stringValue) Get() any { return string(*s) }
   254  
   255  func (s *stringValue) String() string { return string(*s) }
   256  
   257  // -- float64 Value
   258  type float64Value float64
   259  
   260  func newFloat64Value(val float64, p *float64) *float64Value {
   261  	*p = val
   262  	return (*float64Value)(p)
   263  }
   264  
   265  func (f *float64Value) Set(s string) error {
   266  	v, err := strconv.ParseFloat(s, 64)
   267  	if err != nil {
   268  		err = numError(err)
   269  	}
   270  	*f = float64Value(v)
   271  	return err
   272  }
   273  
   274  func (f *float64Value) Get() any { return float64(*f) }
   275  
   276  func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
   277  
   278  // -- time.Duration Value
   279  type durationValue time.Duration
   280  
   281  func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
   282  	*p = val
   283  	return (*durationValue)(p)
   284  }
   285  
   286  func (d *durationValue) Set(s string) error {
   287  	v, err := time.ParseDuration(s)
   288  	if err != nil {
   289  		err = errParse
   290  	}
   291  	*d = durationValue(v)
   292  	return err
   293  }
   294  
   295  func (d *durationValue) Get() any { return time.Duration(*d) }
   296  
   297  func (d *durationValue) String() string { return (*time.Duration)(d).String() }
   298  
   299  // -- encoding.TextUnmarshaler Value
   300  type textValue struct{ p encoding.TextUnmarshaler }
   301  
   302  func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
   303  	ptrVal := reflect.ValueOf(p)
   304  	if ptrVal.Kind() != reflect.Ptr {
   305  		panic("variable value type must be a pointer")
   306  	}
   307  	defVal := reflect.ValueOf(val)
   308  	if defVal.Kind() == reflect.Ptr {
   309  		defVal = defVal.Elem()
   310  	}
   311  	if defVal.Type() != ptrVal.Type().Elem() {
   312  		panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
   313  	}
   314  	ptrVal.Elem().Set(defVal)
   315  	return textValue{p}
   316  }
   317  
   318  func (v textValue) Set(s string) error {
   319  	return v.p.UnmarshalText([]byte(s))
   320  }
   321  
   322  func (v textValue) Get() any {
   323  	return v.p
   324  }
   325  
   326  func (v textValue) String() string {
   327  	if m, ok := v.p.(encoding.TextMarshaler); ok {
   328  		if b, err := m.MarshalText(); err == nil {
   329  			return string(b)
   330  		}
   331  	}
   332  	return ""
   333  }
   334  
   335  // -- func Value
   336  type funcValue func(string) error
   337  
   338  func (f funcValue) Set(s string) error { return f(s) }
   339  
   340  func (f funcValue) String() string { return "" }
   341  
   342  // -- boolFunc Value
   343  type boolFuncValue func(string) error
   344  
   345  func (f boolFuncValue) Set(s string) error { return f(s) }
   346  
   347  func (f boolFuncValue) String() string { return "" }
   348  
   349  func (f boolFuncValue) IsBoolFlag() bool { return true }
   350  
   351  // Value is the interface to the dynamic value stored in a flag.
   352  // (The default value is represented as a string.)
   353  //
   354  // If a Value has an IsBoolFlag() bool method returning true,
   355  // the command-line parser makes -name equivalent to -name=true
   356  // rather than using the next command-line argument.
   357  //
   358  // Set is called once, in command line order, for each flag present.
   359  // The flag package may call the [String] method with a zero-valued receiver,
   360  // such as a nil pointer.
   361  type Value interface {
   362  	String() string
   363  	Set(string) error
   364  }
   365  
   366  // Getter is an interface that allows the contents of a [Value] to be retrieved.
   367  // It wraps the [Value] interface, rather than being part of it, because it
   368  // appeared after Go 1 and its compatibility rules. All [Value] types provided
   369  // by this package satisfy the [Getter] interface, except the type used by [Func].
   370  type Getter interface {
   371  	Value
   372  	Get() any
   373  }
   374  
   375  // ErrorHandling defines how [FlagSet.Parse] behaves if the parse fails.
   376  type ErrorHandling int
   377  
   378  // These constants cause [FlagSet.Parse] to behave as described if the parse fails.
   379  const (
   380  	ContinueOnError ErrorHandling = iota // Return a descriptive error.
   381  	ExitOnError                          // Call os.Exit(2) or for -h/-help Exit(0).
   382  	PanicOnError                         // Call panic with a descriptive error.
   383  )
   384  
   385  // A FlagSet represents a set of defined flags. The zero value of a FlagSet
   386  // has no name and has [ContinueOnError] error handling.
   387  //
   388  // [Flag] names must be unique within a FlagSet. An attempt to define a flag whose
   389  // name is already in use will cause a panic.
   390  type FlagSet struct {
   391  	// Usage is the function called when an error occurs while parsing flags.
   392  	// The field is a function (not a method) that may be changed to point to
   393  	// a custom error handler. What happens after Usage is called depends
   394  	// on the ErrorHandling setting; for the command line, this defaults
   395  	// to ExitOnError, which exits the program after calling Usage.
   396  	Usage func()
   397  
   398  	name          string
   399  	parsed        bool
   400  	actual        map[string]*Flag
   401  	formal        map[string]*Flag
   402  	args          []string // arguments after flags
   403  	errorHandling ErrorHandling
   404  	output        io.Writer         // nil means stderr; use Output() accessor
   405  	undef         map[string]string // flags which didn't exist at the time of Set
   406  }
   407  
   408  // A Flag represents the state of a flag.
   409  type Flag struct {
   410  	Name     string // name as it appears on command line
   411  	Usage    string // help message
   412  	Value    Value  // value as set
   413  	DefValue string // default value (as text); for usage message
   414  	IsSet    bool   // true if the Value was explicitly set by [FlagSet.Parse] or [FlagSet.Set]
   415  }
   416  
   417  // sortFlags returns the flags as a slice in lexicographical sorted order.
   418  func sortFlags(flags map[string]*Flag) []*Flag {
   419  	result := make([]*Flag, len(flags))
   420  	i := 0
   421  	for _, f := range flags {
   422  		result[i] = f
   423  		i++
   424  	}
   425  	slices.SortFunc(result, func(a, b *Flag) int {
   426  		return strings.Compare(a.Name, b.Name)
   427  	})
   428  	return result
   429  }
   430  
   431  // Output returns the destination for usage and error messages. [os.Stderr] is returned if
   432  // output was not set or was set to nil.
   433  func (f *FlagSet) Output() io.Writer {
   434  	if f.output == nil {
   435  		return os.Stderr
   436  	}
   437  	return f.output
   438  }
   439  
   440  // Name returns the name of the flag set.
   441  func (f *FlagSet) Name() string {
   442  	return f.name
   443  }
   444  
   445  // ErrorHandling returns the error handling behavior of the flag set.
   446  func (f *FlagSet) ErrorHandling() ErrorHandling {
   447  	return f.errorHandling
   448  }
   449  
   450  // SetOutput sets the destination for usage and error messages.
   451  // If output is nil, [os.Stderr] is used.
   452  func (f *FlagSet) SetOutput(output io.Writer) {
   453  	f.output = output
   454  }
   455  
   456  // VisitAll visits the flags in lexicographical order, calling fn for each.
   457  // It visits all flags, even those not set.
   458  func (f *FlagSet) VisitAll(fn func(*Flag)) {
   459  	for _, flag := range sortFlags(f.formal) {
   460  		fn(flag)
   461  	}
   462  }
   463  
   464  // All yields the flags in lexicographical order.
   465  // It visits all flags, even those not set.
   466  func (f *FlagSet) All() iter.Seq[*Flag] {
   467  	return func(yield func(*Flag) bool) {
   468  		for _, flag := range sortFlags(f.formal) {
   469  			if !yield(flag) {
   470  				break
   471  			}
   472  		}
   473  	}
   474  }
   475  
   476  // All yields all command-line flags, in lexicographical order.
   477  // It visits all flags, even those not set.
   478  func All() iter.Seq[*Flag] {
   479  	return CommandLine.All()
   480  }
   481  
   482  // VisitAll visits the command-line flags in lexicographical order, calling
   483  // fn for each. It visits all flags, even those not set.
   484  func VisitAll(fn func(*Flag)) {
   485  	CommandLine.VisitAll(fn)
   486  }
   487  
   488  // Visit visits the flags in lexicographical order, calling fn for each.
   489  // It visits only those flags that have been set.
   490  func (f *FlagSet) Visit(fn func(*Flag)) {
   491  	for _, flag := range sortFlags(f.actual) {
   492  		fn(flag)
   493  	}
   494  }
   495  
   496  // Visit visits the command-line flags in lexicographical order, calling fn
   497  // for each. It visits only those flags that have been set.
   498  func Visit(fn func(*Flag)) {
   499  	CommandLine.Visit(fn)
   500  }
   501  
   502  // Lookup returns the [Flag] structure of the named flag, returning nil if none exists.
   503  func (f *FlagSet) Lookup(name string) *Flag {
   504  	return f.formal[name]
   505  }
   506  
   507  // Lookup returns the [Flag] structure of the named command-line flag,
   508  // returning nil if none exists.
   509  func Lookup(name string) *Flag {
   510  	return CommandLine.formal[name]
   511  }
   512  
   513  // Set sets the value of the named flag.
   514  func (f *FlagSet) Set(name, value string) error {
   515  	return f.set(name, value)
   516  }
   517  func (f *FlagSet) set(name, value string) error {
   518  	flag, ok := f.formal[name]
   519  	if !ok {
   520  		// Remember that a flag that isn't defined is being set.
   521  		// We return an error in this case, but in addition if
   522  		// subsequently that flag is defined, we want to panic
   523  		// at the definition point.
   524  		// This is a problem which occurs if both the definition
   525  		// and the Set call are in init code and for whatever
   526  		// reason the init code changes evaluation order.
   527  		// See issue 57411.
   528  		_, file, line, ok := runtime.Caller(2)
   529  		if !ok {
   530  			file = "?"
   531  			line = 0
   532  		}
   533  		if f.undef == nil {
   534  			f.undef = map[string]string{}
   535  		}
   536  		f.undef[name] = fmt.Sprintf("%s:%d", file, line)
   537  
   538  		return fmt.Errorf("no such flag -%v", name)
   539  	}
   540  	err := flag.Value.Set(value)
   541  	if err != nil {
   542  		return err
   543  	}
   544  	flag.IsSet = true
   545  	if f.actual == nil {
   546  		f.actual = make(map[string]*Flag)
   547  	}
   548  	f.actual[name] = flag
   549  	return nil
   550  }
   551  
   552  // Set sets the value of the named command-line flag.
   553  func Set(name, value string) error {
   554  	return CommandLine.set(name, value)
   555  }
   556  
   557  // isZeroValue determines whether the string represents the zero
   558  // value for a flag.
   559  func isZeroValue(flag *Flag, value string) (ok bool, err error) {
   560  	// Build a zero value of the flag's Value type, and see if the
   561  	// result of calling its String method equals the value passed in.
   562  	// This works unless the Value type is itself an interface type.
   563  	typ := reflect.TypeOf(flag.Value)
   564  	var z reflect.Value
   565  	if typ.Kind() == reflect.Pointer {
   566  		z = reflect.New(typ.Elem())
   567  	} else {
   568  		z = reflect.Zero(typ)
   569  	}
   570  	// Catch panics calling the String method, which shouldn't prevent the
   571  	// usage message from being printed, but that we should report to the
   572  	// user so that they know to fix their code.
   573  	defer func() {
   574  		if e := recover(); e != nil {
   575  			if typ.Kind() == reflect.Pointer {
   576  				typ = typ.Elem()
   577  			}
   578  			err = fmt.Errorf("panic calling String method on zero %v for flag %s: %v", typ, flag.Name, e)
   579  		}
   580  	}()
   581  	return value == z.Interface().(Value).String(), nil
   582  }
   583  
   584  // UnquoteUsage extracts a back-quoted name from the usage
   585  // string for a flag and returns it and the un-quoted usage.
   586  // Given "a `name` to show" it returns ("name", "a name to show").
   587  // If there are no back quotes, the name is an educated guess of the
   588  // type of the flag's value, or the empty string if the flag is boolean.
   589  func UnquoteUsage(flag *Flag) (name string, usage string) {
   590  	// Look for a back-quoted name, but avoid the strings package.
   591  	usage = flag.Usage
   592  	for i := 0; i < len(usage); i++ {
   593  		if usage[i] == '`' {
   594  			for j := i + 1; j < len(usage); j++ {
   595  				if usage[j] == '`' {
   596  					name = usage[i+1 : j]
   597  					usage = usage[:i] + name + usage[j+1:]
   598  					return name, usage
   599  				}
   600  			}
   601  			break // Only one back quote; use type name.
   602  		}
   603  	}
   604  	// No explicit name, so use type if we can find one.
   605  	name = "value"
   606  	switch fv := flag.Value.(type) {
   607  	case boolFlag:
   608  		if fv.IsBoolFlag() {
   609  			name = ""
   610  		}
   611  	case *durationValue:
   612  		name = "duration"
   613  	case *float64Value:
   614  		name = "float"
   615  	case *intValue, *int64Value:
   616  		name = "int"
   617  	case *stringValue:
   618  		name = "string"
   619  	case *uintValue, *uint64Value:
   620  		name = "uint"
   621  	}
   622  	return
   623  }
   624  
   625  // PrintDefaults prints, to standard error unless configured otherwise, the
   626  // default values of all defined command-line flags in the set. See the
   627  // documentation for the global function PrintDefaults for more information.
   628  func (f *FlagSet) PrintDefaults() {
   629  	var isZeroValueErrs []error
   630  	f.VisitAll(func(flag *Flag) {
   631  		var b strings.Builder
   632  		fmt.Fprintf(&b, "  -%s", flag.Name) // Two spaces before -; see next two comments.
   633  		name, usage := UnquoteUsage(flag)
   634  		if len(name) > 0 {
   635  			b.WriteString(" ")
   636  			b.WriteString(name)
   637  		}
   638  		// Boolean flags of one ASCII letter are so common we
   639  		// treat them specially, putting their usage on the same line.
   640  		if b.Len() <= 4 { // space, space, '-', 'x'.
   641  			b.WriteString("\t")
   642  		} else {
   643  			// Four spaces before the tab triggers good alignment
   644  			// for both 4- and 8-space tab stops.
   645  			b.WriteString("\n    \t")
   646  		}
   647  		b.WriteString(strings.ReplaceAll(usage, "\n", "\n    \t"))
   648  
   649  		// Print the default value only if it differs to the zero value
   650  		// for this flag type.
   651  		if isZero, err := isZeroValue(flag, flag.DefValue); err != nil {
   652  			isZeroValueErrs = append(isZeroValueErrs, err)
   653  		} else if !isZero {
   654  			if _, ok := flag.Value.(*stringValue); ok {
   655  				// put quotes on the value
   656  				fmt.Fprintf(&b, " (default %q)", flag.DefValue)
   657  			} else {
   658  				fmt.Fprintf(&b, " (default %v)", flag.DefValue)
   659  			}
   660  		}
   661  		fmt.Fprint(f.Output(), b.String(), "\n")
   662  	})
   663  	// If calling String on any zero flag.Values triggered a panic, print
   664  	// the messages after the full set of defaults so that the programmer
   665  	// knows to fix the panic.
   666  	if errs := isZeroValueErrs; len(errs) > 0 {
   667  		fmt.Fprintln(f.Output())
   668  		for _, err := range errs {
   669  			fmt.Fprintln(f.Output(), err)
   670  		}
   671  	}
   672  }
   673  
   674  // PrintDefaults prints, to standard error unless configured otherwise,
   675  // a usage message showing the default settings of all defined
   676  // command-line flags.
   677  // For an integer valued flag x, the default output has the form
   678  //
   679  //	-x int
   680  //		usage-message-for-x (default 7)
   681  //
   682  // The usage message will appear on a separate line for anything but
   683  // a bool flag with a one-byte name. For bool flags, the type is
   684  // omitted and if the flag name is one byte the usage message appears
   685  // on the same line. The parenthetical default is omitted if the
   686  // default is the zero value for the type. The listed type, here int,
   687  // can be changed by placing a back-quoted name in the flag's usage
   688  // string; the first such item in the message is taken to be a parameter
   689  // name to show in the message and the back quotes are stripped from
   690  // the message when displayed. For instance, given
   691  //
   692  //	flag.String("I", "", "search `directory` for include files")
   693  //
   694  // the output will be
   695  //
   696  //	-I directory
   697  //		search directory for include files.
   698  //
   699  // To change the destination for flag messages, call [CommandLine].SetOutput.
   700  func PrintDefaults() {
   701  	CommandLine.PrintDefaults()
   702  }
   703  
   704  // defaultUsage is the default function to print a usage message.
   705  func (f *FlagSet) defaultUsage() {
   706  	if f.name == "" {
   707  		fmt.Fprintf(f.Output(), "Usage:\n")
   708  	} else {
   709  		fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
   710  	}
   711  	f.PrintDefaults()
   712  }
   713  
   714  // NOTE: Usage is not just defaultUsage(CommandLine)
   715  // because it serves (via godoc flag Usage) as the example
   716  // for how to write your own usage function.
   717  
   718  // Usage prints a usage message documenting all defined command-line flags
   719  // to [CommandLine]'s output, which by default is [os.Stderr].
   720  // It is called when an error occurs while parsing flags.
   721  // The function is a variable that may be changed to point to a custom function.
   722  // By default it prints a simple header and calls [PrintDefaults]; for details about the
   723  // format of the output and how to control it, see the documentation for [PrintDefaults].
   724  // Custom usage functions may choose to exit the program; by default exiting
   725  // happens anyway as the command line's error handling strategy is set to
   726  // [ExitOnError].
   727  var Usage = func() {
   728  	fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
   729  	PrintDefaults()
   730  }
   731  
   732  // NFlag returns the number of flags that have been set.
   733  func (f *FlagSet) NFlag() int { return len(f.actual) }
   734  
   735  // NFlag returns the number of command-line flags that have been set.
   736  func NFlag() int { return len(CommandLine.actual) }
   737  
   738  // Arg returns the i'th argument. Arg(0) is the first remaining argument
   739  // after flags have been processed. Arg returns an empty string if the
   740  // requested element does not exist.
   741  func (f *FlagSet) Arg(i int) string {
   742  	if i < 0 || i >= len(f.args) {
   743  		return ""
   744  	}
   745  	return f.args[i]
   746  }
   747  
   748  // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
   749  // after flags have been processed. Arg returns an empty string if the
   750  // requested element does not exist.
   751  func Arg(i int) string {
   752  	return CommandLine.Arg(i)
   753  }
   754  
   755  // NArg is the number of arguments remaining after flags have been processed.
   756  func (f *FlagSet) NArg() int { return len(f.args) }
   757  
   758  // NArg is the number of arguments remaining after flags have been processed.
   759  func NArg() int { return len(CommandLine.args) }
   760  
   761  // Args returns the non-flag arguments.
   762  func (f *FlagSet) Args() []string { return f.args }
   763  
   764  // Args returns the non-flag command-line arguments.
   765  func Args() []string { return CommandLine.args }
   766  
   767  // BoolVar defines a bool flag with specified name, default value, and usage string.
   768  // The argument p points to a bool variable in which to store the value of the flag.
   769  func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
   770  	f.Var(newBoolValue(value, p), name, usage)
   771  }
   772  
   773  // BoolVar defines a bool flag with specified name, default value, and usage string.
   774  // The argument p points to a bool variable in which to store the value of the flag.
   775  func BoolVar(p *bool, name string, value bool, usage string) {
   776  	CommandLine.Var(newBoolValue(value, p), name, usage)
   777  }
   778  
   779  // Bool defines a bool flag with specified name, default value, and usage string.
   780  // The return value is the address of a bool variable that stores the value of the flag.
   781  func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
   782  	p := new(bool)
   783  	f.BoolVar(p, name, value, usage)
   784  	return p
   785  }
   786  
   787  // Bool defines a bool flag with specified name, default value, and usage string.
   788  // The return value is the address of a bool variable that stores the value of the flag.
   789  func Bool(name string, value bool, usage string) *bool {
   790  	return CommandLine.Bool(name, value, usage)
   791  }
   792  
   793  // IntVar defines an int flag with specified name, default value, and usage string.
   794  // The argument p points to an int variable in which to store the value of the flag.
   795  func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
   796  	f.Var(newIntValue(value, p), name, usage)
   797  }
   798  
   799  // IntVar defines an int flag with specified name, default value, and usage string.
   800  // The argument p points to an int variable in which to store the value of the flag.
   801  func IntVar(p *int, name string, value int, usage string) {
   802  	CommandLine.Var(newIntValue(value, p), name, usage)
   803  }
   804  
   805  // Int defines an int flag with specified name, default value, and usage string.
   806  // The return value is the address of an int variable that stores the value of the flag.
   807  func (f *FlagSet) Int(name string, value int, usage string) *int {
   808  	p := new(int)
   809  	f.IntVar(p, name, value, usage)
   810  	return p
   811  }
   812  
   813  // Int defines an int flag with specified name, default value, and usage string.
   814  // The return value is the address of an int variable that stores the value of the flag.
   815  func Int(name string, value int, usage string) *int {
   816  	return CommandLine.Int(name, value, usage)
   817  }
   818  
   819  // Int64Var defines an int64 flag with specified name, default value, and usage string.
   820  // The argument p points to an int64 variable in which to store the value of the flag.
   821  func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
   822  	f.Var(newInt64Value(value, p), name, usage)
   823  }
   824  
   825  // Int64Var defines an int64 flag with specified name, default value, and usage string.
   826  // The argument p points to an int64 variable in which to store the value of the flag.
   827  func Int64Var(p *int64, name string, value int64, usage string) {
   828  	CommandLine.Var(newInt64Value(value, p), name, usage)
   829  }
   830  
   831  // Int64 defines an int64 flag with specified name, default value, and usage string.
   832  // The return value is the address of an int64 variable that stores the value of the flag.
   833  func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
   834  	p := new(int64)
   835  	f.Int64Var(p, name, value, usage)
   836  	return p
   837  }
   838  
   839  // Int64 defines an int64 flag with specified name, default value, and usage string.
   840  // The return value is the address of an int64 variable that stores the value of the flag.
   841  func Int64(name string, value int64, usage string) *int64 {
   842  	return CommandLine.Int64(name, value, usage)
   843  }
   844  
   845  // UintVar defines a uint flag with specified name, default value, and usage string.
   846  // The argument p points to a uint variable in which to store the value of the flag.
   847  func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
   848  	f.Var(newUintValue(value, p), name, usage)
   849  }
   850  
   851  // UintVar defines a uint flag with specified name, default value, and usage string.
   852  // The argument p points to a uint variable in which to store the value of the flag.
   853  func UintVar(p *uint, name string, value uint, usage string) {
   854  	CommandLine.Var(newUintValue(value, p), name, usage)
   855  }
   856  
   857  // Uint defines a uint flag with specified name, default value, and usage string.
   858  // The return value is the address of a uint variable that stores the value of the flag.
   859  func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
   860  	p := new(uint)
   861  	f.UintVar(p, name, value, usage)
   862  	return p
   863  }
   864  
   865  // Uint defines a uint flag with specified name, default value, and usage string.
   866  // The return value is the address of a uint variable that stores the value of the flag.
   867  func Uint(name string, value uint, usage string) *uint {
   868  	return CommandLine.Uint(name, value, usage)
   869  }
   870  
   871  // Uint64Var defines a uint64 flag with specified name, default value, and usage string.
   872  // The argument p points to a uint64 variable in which to store the value of the flag.
   873  func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
   874  	f.Var(newUint64Value(value, p), name, usage)
   875  }
   876  
   877  // Uint64Var defines a uint64 flag with specified name, default value, and usage string.
   878  // The argument p points to a uint64 variable in which to store the value of the flag.
   879  func Uint64Var(p *uint64, name string, value uint64, usage string) {
   880  	CommandLine.Var(newUint64Value(value, p), name, usage)
   881  }
   882  
   883  // Uint64 defines a uint64 flag with specified name, default value, and usage string.
   884  // The return value is the address of a uint64 variable that stores the value of the flag.
   885  func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
   886  	p := new(uint64)
   887  	f.Uint64Var(p, name, value, usage)
   888  	return p
   889  }
   890  
   891  // Uint64 defines a uint64 flag with specified name, default value, and usage string.
   892  // The return value is the address of a uint64 variable that stores the value of the flag.
   893  func Uint64(name string, value uint64, usage string) *uint64 {
   894  	return CommandLine.Uint64(name, value, usage)
   895  }
   896  
   897  // StringVar defines a string flag with specified name, default value, and usage string.
   898  // The argument p points to a string variable in which to store the value of the flag.
   899  func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
   900  	f.Var(newStringValue(value, p), name, usage)
   901  }
   902  
   903  // StringVar defines a string flag with specified name, default value, and usage string.
   904  // The argument p points to a string variable in which to store the value of the flag.
   905  func StringVar(p *string, name string, value string, usage string) {
   906  	CommandLine.Var(newStringValue(value, p), name, usage)
   907  }
   908  
   909  // String defines a string flag with specified name, default value, and usage string.
   910  // The return value is the address of a string variable that stores the value of the flag.
   911  func (f *FlagSet) String(name string, value string, usage string) *string {
   912  	p := new(string)
   913  	f.StringVar(p, name, value, usage)
   914  	return p
   915  }
   916  
   917  // String defines a string flag with specified name, default value, and usage string.
   918  // The return value is the address of a string variable that stores the value of the flag.
   919  func String(name string, value string, usage string) *string {
   920  	return CommandLine.String(name, value, usage)
   921  }
   922  
   923  // Float64Var defines a float64 flag with specified name, default value, and usage string.
   924  // The argument p points to a float64 variable in which to store the value of the flag.
   925  func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
   926  	f.Var(newFloat64Value(value, p), name, usage)
   927  }
   928  
   929  // Float64Var defines a float64 flag with specified name, default value, and usage string.
   930  // The argument p points to a float64 variable in which to store the value of the flag.
   931  func Float64Var(p *float64, name string, value float64, usage string) {
   932  	CommandLine.Var(newFloat64Value(value, p), name, usage)
   933  }
   934  
   935  // Float64 defines a float64 flag with specified name, default value, and usage string.
   936  // The return value is the address of a float64 variable that stores the value of the flag.
   937  func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
   938  	p := new(float64)
   939  	f.Float64Var(p, name, value, usage)
   940  	return p
   941  }
   942  
   943  // Float64 defines a float64 flag with specified name, default value, and usage string.
   944  // The return value is the address of a float64 variable that stores the value of the flag.
   945  func Float64(name string, value float64, usage string) *float64 {
   946  	return CommandLine.Float64(name, value, usage)
   947  }
   948  
   949  // DurationVar defines a time.Duration flag with specified name, default value, and usage string.
   950  // The argument p points to a time.Duration variable in which to store the value of the flag.
   951  // The flag accepts a value acceptable to time.ParseDuration.
   952  func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
   953  	f.Var(newDurationValue(value, p), name, usage)
   954  }
   955  
   956  // DurationVar defines a time.Duration flag with specified name, default value, and usage string.
   957  // The argument p points to a time.Duration variable in which to store the value of the flag.
   958  // The flag accepts a value acceptable to time.ParseDuration.
   959  func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
   960  	CommandLine.Var(newDurationValue(value, p), name, usage)
   961  }
   962  
   963  // Duration defines a time.Duration flag with specified name, default value, and usage string.
   964  // The return value is the address of a time.Duration variable that stores the value of the flag.
   965  // The flag accepts a value acceptable to time.ParseDuration.
   966  func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
   967  	p := new(time.Duration)
   968  	f.DurationVar(p, name, value, usage)
   969  	return p
   970  }
   971  
   972  // Duration defines a time.Duration flag with specified name, default value, and usage string.
   973  // The return value is the address of a time.Duration variable that stores the value of the flag.
   974  // The flag accepts a value acceptable to time.ParseDuration.
   975  func Duration(name string, value time.Duration, usage string) *time.Duration {
   976  	return CommandLine.Duration(name, value, usage)
   977  }
   978  
   979  // TextVar defines a flag with a specified name, default value, and usage string.
   980  // The argument p must be a pointer to a variable that will hold the value
   981  // of the flag, and p must implement encoding.TextUnmarshaler.
   982  // If the flag is used, the flag value will be passed to p's UnmarshalText method.
   983  // The type of the default value must be the same as the type of p.
   984  func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
   985  	f.Var(newTextValue(value, p), name, usage)
   986  }
   987  
   988  // TextVar defines a flag with a specified name, default value, and usage string.
   989  // The argument p must be a pointer to a variable that will hold the value
   990  // of the flag, and p must implement encoding.TextUnmarshaler.
   991  // If the flag is used, the flag value will be passed to p's UnmarshalText method.
   992  // The type of the default value must be the same as the type of p.
   993  func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
   994  	CommandLine.Var(newTextValue(value, p), name, usage)
   995  }
   996  
   997  // Func defines a flag with the specified name and usage string.
   998  // Each time the flag is seen, fn is called with the value of the flag.
   999  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
  1000  func (f *FlagSet) Func(name, usage string, fn func(string) error) {
  1001  	f.Var(funcValue(fn), name, usage)
  1002  }
  1003  
  1004  // Func defines a flag with the specified name and usage string.
  1005  // Each time the flag is seen, fn is called with the value of the flag.
  1006  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
  1007  func Func(name, usage string, fn func(string) error) {
  1008  	CommandLine.Func(name, usage, fn)
  1009  }
  1010  
  1011  // BoolFunc defines a flag with the specified name and usage string without requiring values.
  1012  // Each time the flag is seen, fn is called with the value of the flag.
  1013  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
  1014  func (f *FlagSet) BoolFunc(name, usage string, fn func(string) error) {
  1015  	f.Var(boolFuncValue(fn), name, usage)
  1016  }
  1017  
  1018  // BoolFunc defines a flag with the specified name and usage string without requiring values.
  1019  // Each time the flag is seen, fn is called with the value of the flag.
  1020  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
  1021  func BoolFunc(name, usage string, fn func(string) error) {
  1022  	CommandLine.BoolFunc(name, usage, fn)
  1023  }
  1024  
  1025  // Var defines a flag with the specified name and usage string. The type and
  1026  // value of the flag are represented by the first argument, of type [Value], which
  1027  // typically holds a user-defined implementation of [Value]. For instance, the
  1028  // caller could create a flag that turns a comma-separated string into a slice
  1029  // of strings by giving the slice the methods of [Value]; in particular, [Set] would
  1030  // decompose the comma-separated string into the slice.
  1031  func (f *FlagSet) Var(value Value, name string, usage string) {
  1032  	// Flag must not begin "-" or contain "=".
  1033  	if strings.HasPrefix(name, "-") {
  1034  		panic(f.sprintf("flag %q begins with -", name))
  1035  	} else if strings.Contains(name, "=") {
  1036  		panic(f.sprintf("flag %q contains =", name))
  1037  	}
  1038  
  1039  	// Remember the default value as a string; it won't change.
  1040  	flag := &Flag{name, usage, value, value.String(), false}
  1041  	_, alreadythere := f.formal[name]
  1042  	if alreadythere {
  1043  		var msg string
  1044  		if f.name == "" {
  1045  			msg = f.sprintf("flag redefined: %s", name)
  1046  		} else {
  1047  			msg = f.sprintf("%s flag redefined: %s", f.name, name)
  1048  		}
  1049  		panic(msg) // Happens only if flags are declared with identical names
  1050  	}
  1051  	if pos := f.undef[name]; pos != "" {
  1052  		panic(fmt.Sprintf("flag %s set at %s before being defined", name, pos))
  1053  	}
  1054  	if f.formal == nil {
  1055  		f.formal = make(map[string]*Flag)
  1056  	}
  1057  	f.formal[name] = flag
  1058  }
  1059  
  1060  // Var defines a flag with the specified name and usage string. The type and
  1061  // value of the flag are represented by the first argument, of type [Value], which
  1062  // typically holds a user-defined implementation of [Value]. For instance, the
  1063  // caller could create a flag that turns a comma-separated string into a slice
  1064  // of strings by giving the slice the methods of [Value]; in particular, [Set] would
  1065  // decompose the comma-separated string into the slice.
  1066  func Var(value Value, name string, usage string) {
  1067  	CommandLine.Var(value, name, usage)
  1068  }
  1069  
  1070  // sprintf formats the message, prints it to output, and returns it.
  1071  func (f *FlagSet) sprintf(format string, a ...any) string {
  1072  	msg := fmt.Sprintf(format, a...)
  1073  	fmt.Fprintln(f.Output(), msg)
  1074  	return msg
  1075  }
  1076  
  1077  // failf prints to standard error a formatted error and usage message and
  1078  // returns the error.
  1079  func (f *FlagSet) failf(format string, a ...any) error {
  1080  	msg := f.sprintf(format, a...)
  1081  	f.usage()
  1082  	return errors.New(msg)
  1083  }
  1084  
  1085  // usage calls the Usage method for the flag set if one is specified,
  1086  // or the appropriate default usage function otherwise.
  1087  func (f *FlagSet) usage() {
  1088  	if f.Usage == nil {
  1089  		f.defaultUsage()
  1090  	} else {
  1091  		f.Usage()
  1092  	}
  1093  }
  1094  
  1095  // parseOne parses one flag. It reports whether a flag was seen.
  1096  func (f *FlagSet) parseOne() (bool, error) {
  1097  	if len(f.args) == 0 {
  1098  		return false, nil
  1099  	}
  1100  	s := f.args[0]
  1101  	if len(s) < 2 || s[0] != '-' {
  1102  		return false, nil
  1103  	}
  1104  	numMinuses := 1
  1105  	if s[1] == '-' {
  1106  		numMinuses++
  1107  		if len(s) == 2 { // "--" terminates the flags
  1108  			f.args = f.args[1:]
  1109  			return false, nil
  1110  		}
  1111  	}
  1112  	name := s[numMinuses:]
  1113  	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
  1114  		return false, f.failf("bad flag syntax: %s", s)
  1115  	}
  1116  
  1117  	// it's a flag. does it have an argument?
  1118  	f.args = f.args[1:]
  1119  	hasValue := false
  1120  	value := ""
  1121  	for i := 1; i < len(name); i++ { // equals cannot be first
  1122  		if name[i] == '=' {
  1123  			value = name[i+1:]
  1124  			hasValue = true
  1125  			name = name[0:i]
  1126  			break
  1127  		}
  1128  	}
  1129  
  1130  	flag, ok := f.formal[name]
  1131  	if !ok {
  1132  		if name == "help" || name == "h" { // special case for nice help message.
  1133  			f.usage()
  1134  			return false, ErrHelp
  1135  		}
  1136  		return false, f.failf("flag provided but not defined: -%s", name)
  1137  	}
  1138  
  1139  	if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
  1140  		if hasValue {
  1141  			if err := fv.Set(value); err != nil {
  1142  				return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
  1143  			}
  1144  		} else {
  1145  			if err := fv.Set("true"); err != nil {
  1146  				return false, f.failf("invalid boolean flag %s: %v", name, err)
  1147  			}
  1148  		}
  1149  	} else {
  1150  		// It must have a value, which might be the next argument.
  1151  		if !hasValue && len(f.args) > 0 {
  1152  			// value is the next arg
  1153  			hasValue = true
  1154  			value, f.args = f.args[0], f.args[1:]
  1155  		}
  1156  		if !hasValue {
  1157  			return false, f.failf("flag needs an argument: -%s", name)
  1158  		}
  1159  		if err := flag.Value.Set(value); err != nil {
  1160  			return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
  1161  		}
  1162  	}
  1163  	flag.IsSet = true
  1164  	if f.actual == nil {
  1165  		f.actual = make(map[string]*Flag)
  1166  	}
  1167  	f.actual[name] = flag
  1168  	return true, nil
  1169  }
  1170  
  1171  // Parse parses flag definitions from the argument list, which should not
  1172  // include the command name. Must be called after all flags in the [FlagSet]
  1173  // are defined and before flags are accessed by the program.
  1174  // The return value will be [ErrHelp] if -help or -h were set but not defined.
  1175  func (f *FlagSet) Parse(arguments []string) error {
  1176  	f.parsed = true
  1177  	f.args = arguments
  1178  	for {
  1179  		seen, err := f.parseOne()
  1180  		if seen {
  1181  			continue
  1182  		}
  1183  		if err == nil {
  1184  			break
  1185  		}
  1186  		switch f.errorHandling {
  1187  		case ContinueOnError:
  1188  			return err
  1189  		case ExitOnError:
  1190  			if err == ErrHelp {
  1191  				os.Exit(0)
  1192  			}
  1193  			os.Exit(2)
  1194  		case PanicOnError:
  1195  			panic(err)
  1196  		}
  1197  	}
  1198  	return nil
  1199  }
  1200  
  1201  // Parsed reports whether f.Parse has been called.
  1202  func (f *FlagSet) Parsed() bool {
  1203  	return f.parsed
  1204  }
  1205  
  1206  // Parse parses the command-line flags from [os.Args][1:]. Must be called
  1207  // after all flags are defined and before flags are accessed by the program.
  1208  func Parse() {
  1209  	// Ignore errors; CommandLine is set for ExitOnError.
  1210  	CommandLine.Parse(os.Args[1:])
  1211  }
  1212  
  1213  // Parsed reports whether the command-line flags have been parsed.
  1214  func Parsed() bool {
  1215  	return CommandLine.Parsed()
  1216  }
  1217  
  1218  // CommandLine is the default set of command-line flags, parsed from [os.Args].
  1219  // The top-level functions such as [BoolVar], [Arg], and so on are wrappers for the
  1220  // methods of CommandLine.
  1221  var CommandLine *FlagSet
  1222  
  1223  func init() {
  1224  	// It's possible for execl to hand us an empty os.Args.
  1225  	if len(os.Args) == 0 {
  1226  		CommandLine = NewFlagSet("", ExitOnError)
  1227  	} else {
  1228  		CommandLine = NewFlagSet(os.Args[0], ExitOnError)
  1229  	}
  1230  
  1231  	// Override generic FlagSet default Usage with call to global Usage.
  1232  	// Note: This is not CommandLine.Usage = Usage,
  1233  	// because we want any eventual call to use any updated value of Usage,
  1234  	// not the value it has when this line is run.
  1235  	CommandLine.Usage = commandLineUsage
  1236  }
  1237  
  1238  func commandLineUsage() {
  1239  	Usage()
  1240  }
  1241  
  1242  // NewFlagSet returns a new, empty flag set with the specified name and
  1243  // error handling property. If the name is not empty, it will be printed
  1244  // in the default usage message and in error messages.
  1245  func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
  1246  	f := &FlagSet{
  1247  		name:          name,
  1248  		errorHandling: errorHandling,
  1249  	}
  1250  	f.Usage = f.defaultUsage
  1251  	return f
  1252  }
  1253  
  1254  // Init sets the name and error handling property for a flag set.
  1255  // By default, the zero [FlagSet] uses an empty name and the
  1256  // [ContinueOnError] error handling policy.
  1257  func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
  1258  	f.name = name
  1259  	f.errorHandling = errorHandling
  1260  }
  1261  

View as plain text