mirror of
https://github.com/golang/go
synced 2024-11-26 14:46:47 -07:00
Add a flags package.
R=gri OCL=13399 CL=13399
This commit is contained in:
parent
5a30b5b8a9
commit
ac0dd5ae52
439
src/lib/flag.go
Normal file
439
src/lib/flag.go
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package flag
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* 1) Define flags using flag.String(), Bool(), or Int(). Int flag values have type int64. Example:
|
||||||
|
* import flag "flag"
|
||||||
|
* var i int64
|
||||||
|
* var fi *flag.Flag = flag.Int("flagname", 1234, &i, "help message for flagname")
|
||||||
|
* The pointer may be nil; if non-nil, it points to a cell of the appropriate type to store the
|
||||||
|
* flag's value.
|
||||||
|
*
|
||||||
|
* 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 (getters are SVal, BVal, Ival) or through the associated
|
||||||
|
* cell, if set:
|
||||||
|
* print "fi has value ", fi.IVal(), "\n";
|
||||||
|
* print "i has value ", i, "\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.
|
||||||
|
* A lone -- terminates the parsing of the command line.
|
||||||
|
* Integer flags accept 1234, 0664, 0x1234 and may be negative.
|
||||||
|
* Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export Bool, Int, String
|
||||||
|
export Arg, NArg
|
||||||
|
export Parse
|
||||||
|
//export Flag.BVal BUG: variable exported but not defined: Flag.BVal
|
||||||
|
//export Flag.SVal BUG: variable exported but not defined: Flag.SVal
|
||||||
|
export Flag
|
||||||
|
|
||||||
|
// BUG: ctoi, atoi, atob belong elsewhere
|
||||||
|
func ctoi(c int64) int64 {
|
||||||
|
if '0' <= c && c <= '9' {
|
||||||
|
return c - '0'
|
||||||
|
}
|
||||||
|
if 'a' <= c && c <= 'f' {
|
||||||
|
return c - 'a'
|
||||||
|
}
|
||||||
|
if 'A' <= c && c <= 'F' {
|
||||||
|
return c - 'A'
|
||||||
|
}
|
||||||
|
return 1000 // too large for any base
|
||||||
|
}
|
||||||
|
|
||||||
|
func atoi(s string) (value int64, ok bool) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
if s[0] == '-' {
|
||||||
|
n, t := atoi(s[1:len(s)]);
|
||||||
|
return -n, t
|
||||||
|
}
|
||||||
|
var base int64 = 10;
|
||||||
|
i := 0;
|
||||||
|
if s[0] == '0' {
|
||||||
|
base = 8
|
||||||
|
if len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
|
||||||
|
base = 16;
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var n int64 = 0
|
||||||
|
for ; i < len(s); i++ {
|
||||||
|
k := ctoi(int64(s[i]));
|
||||||
|
if k >= base {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
n = n * base + k
|
||||||
|
}
|
||||||
|
return n, true
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Bool Value
|
||||||
|
type BoolValue struct {
|
||||||
|
val bool;
|
||||||
|
p *bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) AsBool() *BoolValue {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) AsInt() *IntValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) AsString() *StringValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) IsBool() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) IsInt() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) IsString() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) ValidValue(str string) bool {
|
||||||
|
i, ok := atob(str);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BoolValue) Set(val bool) {
|
||||||
|
if b.p != nil {
|
||||||
|
*b.p = val
|
||||||
|
}
|
||||||
|
b.val = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBoolValue(b bool, p *bool) *BoolValue {
|
||||||
|
v := new(BoolValue);
|
||||||
|
v.val = b;
|
||||||
|
v.p = p;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Int Value
|
||||||
|
type IntValue struct {
|
||||||
|
val int64;
|
||||||
|
p *int64;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) AsBool() *BoolValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) AsInt() *IntValue {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) AsString() *StringValue{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) IsBool() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) IsInt() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) IsString() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) ValidValue(str string) bool {
|
||||||
|
k, ok := atoi(str);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IntValue) Set(val int64) {
|
||||||
|
if i.p != nil {
|
||||||
|
*i.p = val
|
||||||
|
}
|
||||||
|
i.val = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func
|
||||||
|
NewIntValue(i int64, p *int64) *IntValue {
|
||||||
|
v := new(IntValue);
|
||||||
|
v.val = i;
|
||||||
|
v.p = p;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- String Value
|
||||||
|
type StringValue struct {
|
||||||
|
val string;
|
||||||
|
p *string;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *StringValue) AsBool() *BoolValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *StringValue) AsInt() *IntValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringValue) AsString() *StringValue{
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringValue) IsBool() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringValue) IsInt() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringValue) IsString() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringValue) ValidValue(str string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StringValue) Set(val string) {
|
||||||
|
if s.p != nil {
|
||||||
|
*s.p = val
|
||||||
|
}
|
||||||
|
s.val = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStringValue(s string, p *string) *StringValue {
|
||||||
|
v := new(StringValue);
|
||||||
|
v.val = s;
|
||||||
|
v.p = p;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Value interface
|
||||||
|
type Value interface {
|
||||||
|
AsBool() *BoolValue;
|
||||||
|
AsInt() *IntValue;
|
||||||
|
AsString() *StringValue;
|
||||||
|
IsBool() bool;
|
||||||
|
IsInt() bool;
|
||||||
|
IsString() bool;
|
||||||
|
ValidValue(str string) bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Flag structure (internal)
|
||||||
|
type Flag struct {
|
||||||
|
name string;
|
||||||
|
usage string;
|
||||||
|
value Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Flags struct {
|
||||||
|
actual *map[string] *Flag;
|
||||||
|
formal *map[string] *Flag;
|
||||||
|
first_arg int;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --Customer's value getters
|
||||||
|
func (f *Flag) BVal() bool {
|
||||||
|
if !f.value.IsBool() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return f.value.AsBool().val;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flag) IVal() int64 {
|
||||||
|
if !f.value.IsInt() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return f.value.AsInt().val;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flag) SVal() string {
|
||||||
|
if !f.value.IsString() {
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
return f.value.AsString().val;
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Flags {
|
||||||
|
f := new(Flags);
|
||||||
|
f.first_arg = 1; // 0 is the program name, 1 is first arg
|
||||||
|
f.actual = new(map[string] *Flag);
|
||||||
|
f.formal = new(map[string] *Flag);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags *Flags = New();
|
||||||
|
|
||||||
|
func Arg(i int) string {
|
||||||
|
i += flags.first_arg;
|
||||||
|
if i < 0 || i >= sys.argc() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return sys.argv(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NArg() int32 {
|
||||||
|
return sys.argc() - flags.first_arg
|
||||||
|
}
|
||||||
|
|
||||||
|
func Add(name string, value Value, usage string) *Flag {
|
||||||
|
f := new(Flag);
|
||||||
|
f.name = name;
|
||||||
|
f.usage = usage;
|
||||||
|
f.value = value;
|
||||||
|
dummy, alreadythere := flags.formal[name];
|
||||||
|
if alreadythere {
|
||||||
|
print "flag redefined: ", name, "\n";
|
||||||
|
panic "flag redefinition"
|
||||||
|
}
|
||||||
|
flags.formal[name] = f;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bool(name string, value bool, p *bool, usage string) *Flag {
|
||||||
|
return Add(name, NewBoolValue(value, p), usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int(name string, value int64, p *int64, usage string) *Flag {
|
||||||
|
return Add(name, NewIntValue(value, p), usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
func String(name, value string, p *string, usage string) *Flag {
|
||||||
|
return Add(name, NewStringValue(value, p), usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flags) ParseOne(index int) (ok bool, next int)
|
||||||
|
{
|
||||||
|
s := sys.argv(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, -1
|
||||||
|
}
|
||||||
|
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"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
m := flags.formal;
|
||||||
|
flag, alreadythere = m[name]; // BUG
|
||||||
|
if !alreadythere {
|
||||||
|
print "flag provided but not defined: -", name, "\n"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
if !has_value && index < sys.argc()-1 && flag.value.ValidValue(sys.argv(index+1)) {
|
||||||
|
// value is the next arg
|
||||||
|
has_value = true;
|
||||||
|
index++;
|
||||||
|
value = sys.argv(index);
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case flag.value.IsBool():
|
||||||
|
if has_value {
|
||||||
|
k, ok := atob(value);
|
||||||
|
if !ok {
|
||||||
|
print "invalid boolean value ", value, " for flag: -", name, "\n"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
flag.value.AsBool().Set(k)
|
||||||
|
} else {
|
||||||
|
flag.value.AsBool().Set(true)
|
||||||
|
}
|
||||||
|
case flag.value.IsInt():
|
||||||
|
if !has_value {
|
||||||
|
print "flag needs an argument: -", name, "\n"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
k, ok := atoi(value);
|
||||||
|
if !ok {
|
||||||
|
print "invalid integer value ", value, " for flag: -", name, "\n"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
flag.value.AsInt().Set(k)
|
||||||
|
case flag.value.IsString():
|
||||||
|
if !has_value {
|
||||||
|
print "flag needs an argument: -", name, "\n"
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
flag.value.AsString().Set(value)
|
||||||
|
}
|
||||||
|
flags.actual[name] = flag;
|
||||||
|
return true, index + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse() {
|
||||||
|
for i := 1; i < sys.argc(); {
|
||||||
|
ok, next := flags.ParseOne(i);
|
||||||
|
if next > 0 {
|
||||||
|
flags.first_arg = next;
|
||||||
|
i = next;
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ package fmt
|
|||||||
export Fmt, New;
|
export Fmt, New;
|
||||||
|
|
||||||
const NByte = 64;
|
const NByte = 64;
|
||||||
const NPows10 = 160; // BUG: why not nelem(pows10);
|
const NPows10 = 160;
|
||||||
|
|
||||||
var ldigits string = "0123456789abcdef"; // BUG: Should be const
|
var ldigits string = "0123456789abcdef"; // BUG: Should be const
|
||||||
var udigits string = "0123456789ABCDEF"; // BUG: Should be const
|
var udigits string = "0123456789ABCDEF"; // BUG: Should be const
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
rm -f *.6
|
rm -f *.6
|
||||||
6g fmt.go
|
for i in flag.go fmt.go container/vector.go
|
||||||
6g container/vector.go
|
do
|
||||||
|
6g $i
|
||||||
|
done
|
||||||
mv *.6 $GOROOT/pkg
|
mv *.6 $GOROOT/pkg
|
||||||
|
Loading…
Reference in New Issue
Block a user