Reimplement ParseArgs() with getopt()

The command-line interface is intended to be equivalent. For example,
consider this command:

    $ rascsi -ID0 zero.hda -ID1 one.hda

This is no longer two pairs (ID0, zero.hda), (ID1, one.hda), but a
sequence of commands:

* -I: next disk is SCSI (not SASI)
* -D 0: next disk is device 0
* zero.hda: set up disk
* -I: next disk is SCSI (not SASI)
* -D 1: next disk is device 1
* one.hda: set up disk

Since SCSI is [now] the default, this could equivalently be:

    $ rascsi -d 0 zero.hda -d 1 one.hda
This commit is contained in:
Chris Pickel 2020-08-09 07:52:58 +01:00
parent 8b340fde89
commit 46e03a4026
2 changed files with 73 additions and 130 deletions

BIN
src/raspberrypi/foo.hda Normal file

Binary file not shown.

View File

@ -606,6 +606,13 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
return TRUE; return TRUE;
} }
bool has_suffix(const char* string, const char* suffix) {
int string_len = strlen(string);
int suffix_len = strlen(suffix);
return (string_len >= suffix_len)
&& (xstrcasecmp(string + (string_len - suffix_len), suffix) == 0);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Argument Parsing // Argument Parsing
@ -791,158 +798,94 @@ parse_error:
return FALSE; return FALSE;
} }
#else #else
BOOL ParseArgument(int argc, char* argv[]) bool ParseArgument(int argc, char* argv[])
{ {
int i; int id = -1;
int id; bool is_sasi = false;
int un; int max_id = 7;
int type;
char *argID;
char *argPath;
int len;
char *ext;
// If the ID and path are not specified, the processing is interrupted int opt;
if (argc < 3) { while ((opt = getopt(argc, argv, "-IiHhD:d:")) != -1) {
return TRUE; switch (opt) {
} case 'I':
i = 1; case 'i':
argc--; is_sasi = false;
max_id = 7;
id = -1;
continue;
// Start Decoding case 'H':
case 'h':
is_sasi = true;
max_id = 15;
id = -1;
continue;
while (TRUE) { case 'D':
if (argc < 2) { case 'd': {
break; char* end;
} id = strtol(optarg, &end, 10);
if (*end || (id < 0) || (max_id < id)) {
argc -= 2; fprintf(stderr, "%s: invalid %s (0-%d)\n",
optarg, is_sasi ? "HD" : "ID", max_id);
// Get the ID and Path return false;
argID = argv[i++]; }
argPath = argv[i++]; continue;
// Check if the argument is invalid
if (argID[0] != '-') {
FPRT(stderr,
"Error : Invalid argument(-IDn or -HDn) [%s]\n", argID);
goto parse_error;
}
argID++;
if (strlen(argID) == 3 && xstrncasecmp(argID, "id", 2) == 0) {
// ID or ID Format
// Check that the ID number is valid (0-7)
if (argID[2] < '0' || argID[2] > '7') {
FPRT(stderr,
"Error : Invalid argument(IDn n=0-7) [%c]\n", argID[2]);
goto parse_error;
} }
// The ID unit is good default:
id = argID[2] - '0'; return false;
un = 0;
} else if (xstrncasecmp(argID, "hd", 2) == 0) {
// HD or HD format
if (strlen(argID) == 3) { case 1:
// Check that the HD number is valid (0-9) break;
if (argID[2] < '0' || argID[2] > '9') {
FPRT(stderr,
"Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]);
goto parse_error;
}
// ID was confirmed
id = (argID[2] - '0') / UnitNum;
un = (argID[2] - '0') % UnitNum;
} else if (strlen(argID) == 4) {
// Check that the HD number is valid (10-15)
if (argID[2] != '1' || argID[3] < '0' || argID[3] > '5') {
FPRT(stderr,
"Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]);
goto parse_error;
}
// The ID unit is good - create the id and unit number
id = ((argID[3] - '0') + 10) / UnitNum;
un = ((argID[3] - '0') + 10) % UnitNum;
} else {
FPRT(stderr,
"Error : Invalid argument(IDn or HDn) [%s]\n", argID);
goto parse_error;
}
} else {
FPRT(stderr,
"Error : Invalid argument(IDn or HDn) [%s]\n", argID);
goto parse_error;
} }
// Skip if there is already an active device if (id < 0) {
if (disk[id * UnitNum + un] && fprintf(stderr, "%s: ID not specified\n", optarg);
!disk[id * UnitNum + un]->IsNULL()) { return false;
continue; } else if (disk[id] && !disk[id]->IsNULL()) {
fprintf(stderr, "%d: duplicate ID\n", id);
return false;
} }
// Initialize device type char* path = optarg;
type = -1; int type = -1;
if (has_suffix(path, ".hdf")
// Check ethernet and host bridge || has_suffix(path, ".hds")
if (xstrcasecmp(argPath, "bridge") == 0) { || has_suffix(path, ".hdn")
|| has_suffix(path, ".hdi")
|| has_suffix(path, ".hda")
|| has_suffix(path, ".nhd")) {
type = 0;
} else if (has_suffix(path, ".mos")) {
type = 2;
} else if (has_suffix(path, ".iso")) {
type = 3;
} else if (xstrcasecmp(path, "bridge") == 0) {
type = 4; type = 4;
} else { } else {
// Check the path length // Cannot determine the file type
len = strlen(argPath); fprintf(stderr,
if (len < 5) { "%s: unknown file extension\n", path);
FPRT(stderr, return false;
"Error : Invalid argument(File path is short) [%s]\n", }
argPath);
goto parse_error;
}
// Does the file have an extension? int un = 0;
if (argPath[len - 4] != '.') { if (is_sasi) {
FPRT(stderr, un = id % UnitNum;
"Error : Invalid argument(No extension) [%s]\n", argPath); id /= UnitNum;
goto parse_error;
}
// Figure out what the type is
ext = &argPath[len - 3];
if (xstrcasecmp(ext, "hdf") == 0 ||
xstrcasecmp(ext, "hds") == 0 ||
xstrcasecmp(ext, "hdn") == 0 ||
xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 ||
xstrcasecmp(ext, "hda") == 0) {
// HD(SASI/SCSI)
type = 0;
} else if (strcasecmp(ext, "mos") == 0) {
// MO
type = 2;
} else if (strcasecmp(ext, "iso") == 0) {
// CD
type = 3;
} else {
// Cannot determine the file type
FPRT(stderr,
"Error : Invalid argument(file type) [%s]\n", ext);
goto parse_error;
}
} }
// Execute the command // Execute the command
if (!ProcessCmd(stderr, id, un, 0, type, argPath)) { if (!ProcessCmd(stderr, id, un, 0, type, path)) {
goto parse_error; return false;
} }
id = -1;
} }
// Display the device list // Display the device list
ListDevice(stdout); ListDevice(stdout);
return TRUE; return true;
parse_error:
return FALSE;
} }
#endif // BAREMETAL #endif // BAREMETAL