* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: command_opts.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
/************************************************************************
** Copyright (C) 2007, Sun Microsystems, Inc.
** Sun considers its source code as an unpublished, proprietary
** trade secret and it is available only under strict license provisions.
** This copyright notice is placed here only to protect Sun in the event
** the source is deemed a published work. Disassembly, decompilation,
** or other means of reducing the object code to human readable form
** is prohibited by the license agreement under which this code is
** provided to the user or company in possession of this copy.
*************************************************************************/
// The CommandOptions, Option, ArgumentOption, and ExclusiveOptions
// classes enable configuration based command line option flag
// parsing. Options with and without values are supported, as well as
// groups of exclusive options (similar to GUI's radio buttons).
// An option's initial on-off state may be set, defaulting to off
// (false). By default, an option may appear many times on the
// command line, the last instance taking effect. This behavior can
// be reversed so that an option may appear only once.
// Options with argument values are strictly typed and are initialized
// Mutually exclusive options are described in the ExclusiveOptions
// class. The exclusive options are added to the ExclusiveOptions
// object. If one of the exclusive options appears on the command
// line, one of two behaviors occurs. In this case, by default every
// other exclusive option is turned off. Alternatively, if two
// exclusive options appear, the option parser stops with a fatal
// Options (and any derived class such as ArgumentOption) objects are
// added to a CommandOptions object. The CommandOptions object holds
// all the legal options, described by these option objects, and
// supplies a parse() method that takes an argv[] array and scans it
// for matching options. parse() updates the state in the option
// objects, so that their off-on and arguments values can be queried,
// and sets a stl vector of strings to any remaining positional
// If parse() succeeds, it returns true. If it fails, it returns
// false and a subsequent call to get_error_msg() will return a
// message describing the error.
friend class ExclusiveOptions
;
// Creates a repeatable, initially off option by default
Option(std::string name_
,
Repeatable repeatable_
= REPEATABLE
,
OnOff on_off_default
= OFF
) :
std::string
get_name() const { return name
; }
bool is_on() const { return on_off
== ON
; }
bool is_off() const { return on_off
== OFF
; }
void turn_off() { on_off
= OFF
; }
Result
parse(const std::string
& cmd_line_arg
, const char* val_str
);
virtual std::string
get_error_msg() const
virtual void print(FILE* fp
= stdout
) const
fprintf(fp
, "-%s is %s", get_name().c_str(), is_on() ? "ON" : "OFF");
std::string val_str
= print_value();
fprintf(fp
, " -- value is is %s", val_str
.c_str());
virtual bool takes_argument() const { return false; }
virtual Result
parse_value(const std::string
& val_str
)
fprintf(stderr
, "Internal error: called Option::parse_value()\n");
return Option::PARSE_ERROR
;
virtual std::string
print_value() const
const Repeatable repeatable
;
std::list
<ExclusiveOptions
*> excl_opts
;
class ArgumentOption
: public Option
ArgumentOption(std::string name_
,
Repeatable repeatable_
= REPEATABLE
,
OnOff on_off_default
= OFF
) :
Option(name_
, repeatable_
, on_off_default
),
virtual ~ArgumentOption() {}
T
get_value() const { return value
; }
virtual Result
parse_value(const std::string
& val_str
) = 0;
virtual bool takes_argument() const { return true; }
virtual std::string
print_value() const = 0;
ExclusiveOptions(Compatible compatible_
= COMPATIBLE
) :
virtual ~ExclusiveOptions() {}
ExclusiveOptions
& add(Option
& opt
)
options
[opt
.get_name()] = &opt
;
opt
.excl_opts
.push_back(this);
bool update(Option
& opt
);
std::string
get_error_msg() const
const Compatible compatible
;
std::map
<std::string
,Option
*> options
;
class UnsignedOption
: public ArgumentOption
<uint64_t>
UnsignedOption(std::string name_
,
uint64_t default_value
= 0,
Repeatable repeatable_
= REPEATABLE
,
ArgumentOption(name_
, default_value
, repeatable_
, OFF
),
static bool parse_number(const std::string
& num_str
,
error_msg
= "Leading '-' not allowed with ";
uint64_t parse_value
= strtoull(num_str
.c_str(), &endptr
, base
);
error_msg
= "Illegal numeric argument passed to ";
Result
parse_value(const std::string
& val_str
)
if (parse_number(val_str
, value
, error_msg
, base
))
error_msg
+= "-" + get_name() + "option";
UnsignedOption() : base(0) {}
std::string
print_value() const
sprintf(buf
, "0x%llx", value
);
class SignedOption
: public ArgumentOption
<int64_t>
SignedOption(std::string name_
,
uint64_t default_value
= 0,
Repeatable repeatable_
= REPEATABLE
,
ArgumentOption(name_
, default_value
, repeatable_
, OFF
),
static bool parse_number(const std::string
& num_str
,
int64_t parse_value
= strtoll(num_str
.c_str(), &endptr
, base
);
error_msg
= "Illegal numeric argument passed to ";
Result
parse_value(const std::string
& val_str
)
if (parse_number(val_str
, value
, error_msg
, base
))
error_msg
+= "-" + get_name() + "option";
SignedOption() : base(0) {}
std::string
print_value() const
sprintf(buf
, "%lld", value
);
class StringOption
: public ArgumentOption
<std::string
>
StringOption(std::string name_
,
std::string default_value
= "",
Repeatable repeatable_
= REPEATABLE
) :
ArgumentOption(name_
, default_value
, repeatable_
, OFF
)
Result
parse_value(const std::string
& val_str
)
std::string
print_value() const
typedef std::set
<uint32_t>::iterator iterator
;
typedef std::set
<uint32_t>::const_iterator const_iterator
;
static int get_nr_cpus() { return max_cpu_ndx
+ 1; }
CpuSet(int singleton_ndx
= -1)
const_iterator
begin() const { return cpu_set
.begin(); }
iterator
begin() { return cpu_set
.begin(); }
const_iterator
end() const { return cpu_set
.end(); }
iterator
end() { return cpu_set
.end(); }
for (int ndx
= 0; ndx
< get_nr_cpus(); ++ndx
)
CpuSet
& insert(uint32_t ndx
, bool* out_of_range
= NULL
)
if (out_of_range
!= NULL
)
else if (out_of_range
!= NULL
)
CpuSet
& insert_mask(uint64_t mask
, bool* out_of_range
= NULL
)
bool local_out_of_range
= false;
for (int ndx
= 0; ndx
< 64 && !local_out_of_range
; ++ndx
)
if (mask
& (1ULL << ndx
))
insert(ndx
, &local_out_of_range
);
if (out_of_range
!= NULL
)
*out_of_range
= local_out_of_range
;
iterator
find(uint32_t ndx
, bool* out_of_range
= NULL
)
if (out_of_range
!= NULL
)
*out_of_range
= (ndx
< get_nr_cpus());
return cpu_set
.find(ndx
);
bool find_one(uint32_t ndx
, bool* out_of_range
= NULL
)
if (out_of_range
!= NULL
)
*out_of_range
= (ndx
< get_nr_cpus());
return find(ndx
, out_of_range
) != cpu_set
.end();
bool operator!=(const CpuSet
& rhs
)
return cpu_set
!= rhs
.cpu_set
;
std::string
print() const
for (const_iterator iter
= cpu_set
.begin();
sprintf(buf
, ",%d", *iter
);
return rtn
.empty() ? "" : rtn
.substr(1);
std::set
<uint32_t> cpu_set
;
class CpuOption
: public ArgumentOption
<CpuSet
>
Singleton singleton_
= SINGLETON
)
ArgumentOption("cpu", CpuSet(cpu_ndx
)),
CpuOption(const CpuSet
& default_cpuset
,
Singleton singleton_
= SINGLETON
)
ArgumentOption("cpu", default_cpuset
),
Result
parse_value(const std::string
& val_str
)
if (singleton
== SINGLETON
)
error_msg
= "Only one cpu can be passed to the -" + get_name() +
end
=val_str
.find(",", start
);
std::string tok
= val_str
.substr(start
, (end
-start
));
int pos
= tok
.find("..");
left
= tok
.substr(0, pos
);
if (pos
!= std::string::npos
)
std::string rhs
= tok
.substr(pos
+2);
// further tokenize rhs by ":"
int cpos
= rhs
.find(":");
right
= rhs
.substr(0, cpos
);
if (cpos
!= std::string::npos
)
stride
= rhs
.substr(cpos
+1);
Result rv
= insert_values(left
, right
, stride
);
if (rv
== PARSE_ERROR
) return rv
;
if (end
== std::string::npos
) break;
} /* some or "all" cpus specified? */
std::string
print_value() const
Result
insert_values(std::string leftstr
, std::string rightstr
, std::string stridestr
) {
uint64_t left
, right
, stride
;
UnsignedOption
uso(get_name());
rv
= uso
.parse_value(leftstr
);
if (rv
!= VALUE_FOUND
) return rv
;
rv
= uso
.parse_value(rightstr
);
if (rv
!= VALUE_FOUND
) return rv
;
rv
= uso
.parse_value(stridestr
);
if (rv
!= VALUE_FOUND
) return rv
;
stride
= uso
.get_value();
error_msg
= "stride must be a positive number";
// fprintf(stderr, "insert_values: left=%lld right=%lld stride=%lld\n", left, right, stride);
sprintf(buf
, "upper limit of range (%d) cannot be less than lower limit (%d)",
for (v
=left
; v
<=right
; v
+= stride
) {
bool out_of_bounds
= false;
// fprintf(stderr, "parse_value: trying to insert value %d\n", v);
value
.insert(v
, &out_of_bounds
);
error_msg
= "Cpu number passed to -" + get_name() + " too big";
typedef std::list
<Option
*>::iterator iterator
;
iterator
begin() { return opt_list
.begin(); }
iterator
end() { return opt_list
.end(); }
OptionList
& push_front(Option
* option
)
opt_list
.push_front(option
);
std::list
<Option
*> opt_list
;
class AddressingOptions
: public OptionList
AddressingOptions(AddrType default_addr_type_
)
pa_opt("pa", Option::REPEATABLE
),
ra_opt("ra", Option::REPEATABLE
),
va_opt("va", Option::REPEATABLE
),
context_id("context_id", 0),
partition_id("partition_id", 0),
pa_ra_va_exclusive(ExclusiveOptions::INCOMPATIBLE
),
default_addr_type(default_addr_type_
)
pa_ra_va_exclusive
.add(pa_opt
).add(ra_opt
).add(va_opt
);
push_front(&partition_id
);
UnsignedOption context_id
;
UnsignedOption partition_id
;
Vcpu::TranslateMode
translate_mode()
return Vcpu::TRANSLATE_PA_TO_PA
;
if (partition_id
.is_on())
return Vcpu::TRANSLATE_RA_TO_PA_PID
;
return Vcpu::TRANSLATE_RA_TO_PA
;
// ignore partition_id in this case
return Vcpu::TRANSLATE_VA_TO_PA
;
else if (partition_id
.is_off())
return Vcpu::TRANSLATE_VA_TO_PA_CTX
;
return Vcpu::TRANSLATE_VA_TO_PA_CTX_PID
;
switch (default_addr_type
)
case PA
: return Vcpu::TRANSLATE_PA_TO_PA
;
case RA
: return Vcpu::TRANSLATE_RA_TO_PA
;
case VA
: return Vcpu::TRANSLATE_VA_TO_PA
;
return Vcpu::TRANSLATE_VA_TO_PA
;
ExclusiveOptions pa_ra_va_exclusive
;
AddrType default_addr_type
;
virtual ~CommandOptions() {}
bool parse(const char* cmd_line
,
std::vector
<std::string
>& positional_args
);
std::vector
<std::string
>& positional_args
);
std::string
get_error_msg() const
CommandOptions
& add(Option
& opt
)
options
[opt
.get_name()] = &opt
;
CommandOptions
& add(OptionList
& opt_list
)
for (OptionList::iterator iter
= opt_list
.begin();
void print(FILE* fp
= stdout
) const
for (std::map
<std::string
,Option
*>::const_iterator iter
= options
.begin();
std::map
<std::string
,Option
*> options
;
#endif /* COMMAND_OPTS_H__ */