a risc-v simulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
vriscv/src/option.c

202 lines
4.2 KiB

/*
* Command-line option parsing
*/
#include "vriscv.h"
#define OPTION_SEPARATOR "-"
uint64_t memory_size = 512 * 1024 * 1024;
char* file_path;
bool gdbstub = false;
bool trace = false;
static void print_usage();
static void print_help();
static void print_version();
static int parse_long_option(char* str, char* argq);
void parse_options(int argc, char** argv)
{
for(int i = 1; i < argc; i++)
{
// Start option parsing for argument 'i'
if(argv[i][0] != *OPTION_SEPARATOR) continue;
// Check for long options
if(argv[i][1] == *OPTION_SEPARATOR)
{
i += parse_long_option(argv[i] + 2, argv[i + 1]);
continue;
}
// Parse short options
int k = 1;
while(argv[i][k])
{
switch(argv[i][k])
{
case 'h':
case '?':
{
print_help();
exit(0);
}
case 'v':
{
print_version();
exit(0);
}
case 'm':
{
// First try to convert next chars into int (ex. -m512)
char* end;
memory_size = strtol(&argv[i][k + 1], &end, 10);
if(*end != '\0' || end == &argv[i][k + 1])
{
if(argv[i][k + 1])
{
fprintf(stderr, "Error: Option -m needs an argument, but you used -m in a group of options without an integer next to it\n");
exit(EXIT_FAILURE);
}
// Try to parse next arg as integer
if(argc <= i + 1)
{
fprintf(stderr, "Error: Option " OPTION_SEPARATOR "m needs an argument\n");
exit(EXIT_FAILURE);
}
memory_size = strtol(argv[i + 1], &end, 10);
if(*end != '\0')
{
fprintf(stderr, "Error: Invalid argument '%s' for option " OPTION_SEPARATOR "m\n", argv[i + 1]);
exit(EXIT_FAILURE);
}
else
{
i++;
k = strlen(argv[i]) - 1;
}
}
else k += (end - &argv[i][k + 1]);
if(memory_size <= 0)
{
fprintf(stderr, "Error: Memory size needs to be > 0\n");
exit(EXIT_FAILURE);
}
if(memory_size > 4096)
{
fprintf(stderr, "Error: Cannot address more than 4 GiB of memory on 32-bits !\n");
exit(EXIT_FAILURE);
}
memory_size *= 1024 * 1024;
break;
}
case 's':
{
gdbstub = true;
break;
}
case 't':
{
trace = true;
break;
}
default:
{
fprintf(stderr, "Error: Unknown short option -%c\n", argv[i][k]);
exit(EXIT_FAILURE);
}
}
k++;
}
}
if(argc <= 1)
{
print_usage();
exit(EXIT_FAILURE);
}
else file_path = argv[argc - 1];
}
static int parse_long_option(char* str, char* argq)
{
if(strcmp(str, "help") == 0)
{
print_help();
exit(0);
}
else if(strcmp(str, "version") == 0)
{
print_version();
exit(0);
}
else if(strcmp(str, "memory") == 0)
{
if(argq == NULL)
{
fprintf(stderr, "Error: No argument given for option " OPTION_SEPARATOR "-memory\n");
exit(EXIT_FAILURE);
}
// Convert argument to integer
char* end;
memory_size = strtol(argq, &end, 10);
if(*end != '\0')
{
fprintf(stderr, "Error: Invalid argument '%s' for option " OPTION_SEPARATOR "-memory\n", argq);
exit(EXIT_FAILURE);
}
if(memory_size > 4096)
{
fprintf(stderr, "Error: Cannot address more than 4 GiB of memory on 32-bits !\n");
exit(EXIT_FAILURE);
}
memory_size *= 1024 * 1024;
return 1;
}
else if(strcmp(str, "gdb-stub") == 0)
{
gdbstub = true;
return 0;
}
else if(strcmp(str, "trace") == 0)
{
trace = true;
return 0;
}
else
{
fprintf(stderr, "Error: Unknown long option " OPTION_SEPARATOR OPTION_SEPARATOR "%s\n", str);
exit(EXIT_FAILURE);
}
}
static void print_usage()
{
printf("Usage: %s [options] <elf-file>\n", CURRENT_NAME);
}
static void print_help()
{
print_usage();
printf("Options:\n");
printf(" " OPTION_SEPARATOR "h, " OPTION_SEPARATOR "?, --help\t\tPrint this help message\n");
printf(" " OPTION_SEPARATOR "v, --version\t\t\tPrint version information\n");
printf(" " OPTION_SEPARATOR "m, --memory\t\t\tSet the simulated memory size, in MiB (max 4096)\n");
printf(" " OPTION_SEPARATOR "t, --trace\t\t\tTrace executed instructions in stdout\n");
printf(" " OPTION_SEPARATOR "s, --gdb-stub\t\tLaunch a gdb stub server (remote gdb debugging)\n");
}
static void print_version()
{
printf("%s (%s) version %s\n", CURRENT_NAME, NAME, VERSION);
}