Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / command_opts.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: command_opts.cc
// 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.
**
*************************************************************************/
#include "command_opts.h"
#include "ui.h"
Option::Result Option::parse(const std::string& cmd_line_arg,
const char* val_str)
{
Option::Result result = NOT_FOUND;
if (cmd_line_arg.substr(1) == name)
{
if (seen && repeatable == NOT_REPEATABLE)
{
error_msg = "Duplicate instance of option -" + name;
return PARSE_ERROR;
}
on_off = ON;
if (takes_argument())
{
if (val_str == NULL)
{
error_msg = "Missing argument for option -" + name;
return PARSE_ERROR;
}
if (parse_value(val_str) != VALUE_FOUND)
return PARSE_ERROR;
result = VALUE_FOUND;
}
else
result = ON_OFF_FOUND;
seen = true;
for (std::list <ExclusiveOptions*>::iterator excl_opt_iter =
excl_opts.begin();
excl_opt_iter != excl_opts.end();
++excl_opt_iter)
{
ExclusiveOptions* excl_opt = *excl_opt_iter;
if (!excl_opt->update(*this))
{
error_msg = excl_opt->get_error_msg();
return PARSE_ERROR;
}
}
}
return result;
}
bool ExclusiveOptions::update(Option& found_opt)
{
for (std::map<std::string,Option*>::iterator opt_iter = options.begin();
opt_iter != options.end();
++opt_iter)
{
Option* opt = opt_iter->second;
if (opt == &found_opt)
continue;
if (compatible == INCOMPATIBLE && opt->is_on())
{
error_msg = "Incompatible options -" + opt->get_name() + " and -" +
found_opt.get_name() + " set";
return false;
}
opt->on_off = Option::OFF;
}
return true;
}
bool CommandOptions::parse(int argc,
const char** argv,
std::vector<std::string>& positional_args)
{
error_msg = "";
int ndx;
for (ndx = 0; ndx < argc; ++ndx)
{
if (argv[ndx][0] != '-')
break;
if (argv[ndx][1] == '-' && argv[ndx][2] == '\0')
{
++ndx;
break;
}
const char* val_arg = (ndx != argc - 1) ? argv[ndx+1] : NULL;
for (std::map<std::string,Option*>::iterator opt_iter = options.begin();
opt_iter != options.end();
++opt_iter)
{
Option* opt = opt_iter->second;
Option::Result result = opt->parse(argv[ndx], val_arg);
switch (result)
{
case Option::VALUE_FOUND:
++ndx;
/*FALLTHROUGH*/
case Option::ON_OFF_FOUND:
goto found_option;
case Option::NOT_FOUND:
break;
case Option::PARSE_ERROR:
error_msg = opt->get_error_msg();
return false;
default:
ui->fatal("Internal error -- bad result code: %d\n",
result);
exit(-1);
break;
}
}
error_msg = "Illegal option: ";
error_msg += argv[ndx];
return false;
found_option:
;
}
positional_args.clear();
for (; ndx < argc; ++ndx)
positional_args.push_back(argv[ndx]);
return true;
}
#ifdef COMMAND_OPTS_TEST
#include <stdio.h>
#include <strings.h>
#include <sstream>
int command_opts_test_max_cpu_ndx = 15;
int& CpuSet::max_cpu_ndx = command_opts_test_max_cpu_ndx;
class CommandOptionsTestCase
{
public:
virtual ~CommandOptionsTestCase() {}
void print_args()
{
for (int i = 0; i < argc; ++i)
ui->output("%s ", argv[i]);
ui->output("\n");
}
virtual bool run_test()
{
cmd_options.add(verbose);
cmd_options.add(cpu_opt);
cmd_options.add(file_opt);
cmd_options.add(pa_opt).add(va_opt);
excl_opts.add(pa_opt).add(va_opt);
bool result = cmd_options.parse(argc, argv, pos_args);
if (!result)
{
ui->error("parse failed\n");
print_results();
return false;
}
else if (!verify_test())
{
ui->error("verify failed\n");
print_results();
return false;
}
else
return true;
}
virtual void print_results()
{
ui->error("command line: ");
print_args();
cmd_options.print();
int pos_ndx = 0;
for (std::vector<std::string>::iterator pos_arg_iter = pos_args.begin();
pos_arg_iter != pos_args.end();
++pos_arg_iter)
ui->output("Arg[%d]: %s\n", pos_ndx++, pos_arg_iter->c_str());
}
virtual bool verify_test() = 0;
protected:
CommandOptionsTestCase(std::string args,
CpuOption::Singleton singleton = CpuOption::SINGLETON)
:
argc(0),
verbose("verbose"),
cpu_opt(CpuSet(5), singleton),
file_opt("file", "a.out"),
pa_opt("pa"),
va_opt("va")
{
std::istringstream args_stream(args);
std::string buf;
while (args_stream >> buf)
argv[argc++] = strdup(buf.c_str());
}
int argc;
const char *argv[20];
CommandOptions cmd_options;
Option verbose;
CpuOption cpu_opt;
StringOption file_opt;
Option pa_opt;
Option va_opt;
ExclusiveOptions excl_opts;
std::vector<std::string> pos_args;
};
class CommandOptionsTestCase1 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase1() :
CommandOptionsTestCase("-cpu 0")
{}
virtual ~CommandOptionsTestCase1() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(0);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
return
cpu_opt.is_on() &&
file_opt.is_off() &&
pa_opt.is_off() &&
va_opt.is_off() &&
verbose.is_off();
}
};
class CommandOptionsTestCase2 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase2() :
CommandOptionsTestCase("-cpu 0", CpuOption::MULTITUDE)
{}
virtual ~CommandOptionsTestCase2() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(0);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
return
cpu_opt.is_on() &&
file_opt.is_off() &&
pa_opt.is_off() &&
va_opt.is_off() &&
verbose.is_off();
}
};
class CommandOptionsTestCase3 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase3() :
CommandOptionsTestCase("-cpu 0,2", CpuOption::MULTITUDE)
{}
virtual ~CommandOptionsTestCase3() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(0);
expected_cpu_set.insert(2);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
return
cpu_opt.is_on() &&
file_opt.is_off() &&
pa_opt.is_off() &&
va_opt.is_off() &&
verbose.is_off();
}
};
class CommandOptionsTestCase4 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase4() :
CommandOptionsTestCase("-pa")
{}
virtual ~CommandOptionsTestCase4() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(5);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
return
cpu_opt.is_off() &&
file_opt.is_off() &&
pa_opt.is_on() &&
va_opt.is_off() &&
verbose.is_off();
}
};
class CommandOptionsTestCase5 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase5() :
CommandOptionsTestCase("-pa -va")
{}
virtual ~CommandOptionsTestCase5() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(5);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
return
cpu_opt.is_off() &&
file_opt.is_off() &&
pa_opt.is_off() &&
va_opt.is_on() &&
verbose.is_off();
}
};
class CommandOptionsTestCase6 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase6()
:
CommandOptionsTestCase("-unsigned 0x1234"),
unsigned_opt("unsigned", 10)
{
cmd_options.add(unsigned_opt);
}
virtual ~CommandOptionsTestCase6() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(5);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
if (unsigned_opt.get_value() != 0x1234)
return false;
return
cpu_opt.is_off() &&
file_opt.is_off() &&
pa_opt.is_off() &&
va_opt.is_off() &&
verbose.is_off() &&
unsigned_opt.is_on();
}
UnsignedOption unsigned_opt;
};
class CommandOptionsTestCase7 : public CommandOptionsTestCase
{
public:
CommandOptionsTestCase7()
:
CommandOptionsTestCase("-signed -0x1234"),
signed_opt("signed", 10)
{
cmd_options.add(signed_opt);
}
virtual ~CommandOptionsTestCase7() {}
virtual bool verify_test()
{
CpuSet expected_cpu_set(5);
if (cpu_opt.get_value() != expected_cpu_set)
return false;
if (file_opt.get_value() != "a.out")
return false;
if (signed_opt.get_value() != -0x1234)
return false;
return
cpu_opt.is_off() &&
file_opt.is_off() &&
pa_opt.is_off() &&
va_opt.is_off() &&
verbose.is_off() &&
signed_opt.is_on();
}
SignedOption signed_opt;
};
int
main(int ac, const char *argv[])
{
CommandOptionsTestCase1().run_test();
CommandOptionsTestCase2().run_test();
CommandOptionsTestCase3().run_test();
CommandOptionsTestCase4().run_test();
CommandOptionsTestCase5().run_test();
CommandOptionsTestCase6().run_test();
CommandOptionsTestCase7().run_test();
}
#endif /* COMMAND_OPTS_TEST */