mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 07:19:26 +00:00
SCP: Updated to current.
This commit is contained in:
parent
93945da4ef
commit
54fd54c4db
6
makefile
6
makefile
@ -182,7 +182,11 @@ find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip ${INCPATH}),$
|
||||
ifneq (3,${SIM_MAJOR})
|
||||
ifneq (0,$(TESTS))
|
||||
find_test = RegisterSanityCheck $(abspath $(wildcard $(1)/tests/$(2)_test.ini)) </dev/null
|
||||
TESTING_FEATURES = - Per simulator tests will be run
|
||||
ifneq (,${TEST_ARG})
|
||||
TESTING_FEATURES = - Per simulator tests will be run with argument: ${TEST_ARG}
|
||||
else
|
||||
TESTING_FEATURES = - Per simulator tests will be run
|
||||
endif
|
||||
else
|
||||
TESTING_FEATURES = - Per simulator tests will be skipped
|
||||
endif
|
||||
|
||||
151
scp.c
151
scp.c
@ -4277,6 +4277,75 @@ if (cmdp && (cmdp->action == &return_cmd) && (0 != *cptr)) { /* return command w
|
||||
return stat | SCPE_NOMESSAGE; /* suppress message since we've already done that here */
|
||||
}
|
||||
|
||||
|
||||
/* sim_call_argv - call a routine with C style argc, argv parsed arguments
|
||||
|
||||
Inputs:
|
||||
|
||||
main_like_routine = the routine that is to be called with parsed arguments
|
||||
cptr = the command argument string to be broken down into argc, argv
|
||||
|
||||
When the main_like_routine is called, argc and argv are populated.
|
||||
|
||||
argc is the number of tokens parsed from the input string plus 1
|
||||
argv is an array of parsed tokens where argv[0] is the unparsed input string
|
||||
|
||||
*/
|
||||
|
||||
|
||||
t_stat sim_call_argv (int (*main_like_routine)(int argc, char *argv[]), const char *cptr)
|
||||
{
|
||||
int argc = 1;
|
||||
char **argv = (char **)calloc ((1 + argc), sizeof (*argv));
|
||||
size_t cptr_len = strlen (cptr);
|
||||
char *argline = (char *)malloc (2 + 2 * cptr_len);
|
||||
char *cp, quote;
|
||||
t_stat result = SCPE_OK;
|
||||
|
||||
if ((argv == NULL) || (argline == NULL)) {
|
||||
free (argv);
|
||||
free (argline);
|
||||
return SCPE_MEM;
|
||||
}
|
||||
if (cptr == NULL) {
|
||||
free (argv);
|
||||
free (argline);
|
||||
return SCPE_ARG;
|
||||
}
|
||||
strcpy (argline, cptr);
|
||||
cp = argline + cptr_len + 1;
|
||||
strcpy (cp, cptr);
|
||||
argv[0] = argline; /* argv[0] points to unparsed arguments */
|
||||
argv[argc + 1] = NULL; /* make sure the argument list always ends with a NULL */
|
||||
while (*cp) {
|
||||
while (sim_isspace (*cp)) /* skip blanks */
|
||||
cp++;
|
||||
if (*cp == '\0') /* all done? */
|
||||
break;
|
||||
if (*cp == '\'' || *cp == '"') /* quoted string? */
|
||||
quote = *cp++;
|
||||
else
|
||||
quote = 0;
|
||||
++argc;
|
||||
argv = (char **)realloc (argv, (1 + argc) * sizeof (*argv));
|
||||
if (argv == NULL) {
|
||||
result = SCPE_MEM;
|
||||
break;
|
||||
}
|
||||
argv[argc - 1] = cp; /* save start */
|
||||
argv[argc] = NULL; /* make sure the argument list always ends with a NULL */
|
||||
while (*cp && (quote ? (*cp != quote) : !sim_isspace (*cp)))
|
||||
cp++;
|
||||
if (*cp) /* term at quote/spc */
|
||||
*cp++ = '\0';
|
||||
}
|
||||
if (argv != NULL)
|
||||
result = (t_stat)main_like_routine (argc, argv);
|
||||
free (argline);
|
||||
free (argv);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments
|
||||
and other enviroment variables
|
||||
|
||||
@ -11903,8 +11972,12 @@ do {
|
||||
(bare_reason != SCPE_STOP) &&
|
||||
(bare_reason != SCPE_STEP) &&
|
||||
(bare_reason != SCPE_RUNTIME) &&
|
||||
(bare_reason != SCPE_EXIT))
|
||||
sim_messagef (reason, "\nUnexpected internal error while processing event for %s which returned %d - %s\n", sim_uname (uptr), reason, sim_error_text (reason));
|
||||
(bare_reason != SCPE_EXIT)) {
|
||||
if (bare_reason == SCPE_UNATT)
|
||||
sim_messagef (reason, "\nUnexpected I/O error while processing event for %s - %s\n", sim_uname (uptr), sim_error_text (reason));
|
||||
else
|
||||
sim_messagef (reason, "\nUnexpected internal error while processing event for %s which returned %d - %s\n", sim_uname (uptr), reason, sim_error_text (reason));
|
||||
}
|
||||
} while ((reason == SCPE_OK) &&
|
||||
((sim_interval + sim_interval_catchup) <= 0) &&
|
||||
(sim_clock_queue != QUEUE_LIST_END) &&
|
||||
@ -13873,10 +13946,13 @@ va_list arglist;
|
||||
t_bool inhibit_message = (!sim_show_message || (stat & SCPE_NOMESSAGE));
|
||||
char msg_prefix[32] = "";
|
||||
size_t prefix_len;
|
||||
t_bool newline_prefix = (*fmt == '\n');
|
||||
|
||||
if ((stat == SCPE_OK) && (sim_quiet || (sim_switches & SWMASK ('Q'))))
|
||||
return stat;
|
||||
sprintf (msg_prefix, "%%SIM-%s: ", (stat == SCPE_OK) ? "INFO" : "ERROR");
|
||||
if (newline_prefix)
|
||||
++fmt;
|
||||
sprintf (msg_prefix, "%s%%SIM-%s: ", newline_prefix ? (sim_is_running ? "\r\n" : "\n") : "", (stat == SCPE_OK) ? "INFO" : "ERROR");
|
||||
prefix_len = strlen (msg_prefix);
|
||||
while (1) { /* format passed string, args */
|
||||
va_start (arglist, fmt);
|
||||
@ -16250,6 +16326,73 @@ if (sim_switches & SWMASK ('T'))
|
||||
return result;
|
||||
}
|
||||
|
||||
struct arg_test_result {
|
||||
int expected_argc;
|
||||
const char *expected_argv[12];
|
||||
};
|
||||
static struct parse_arg_function_test {
|
||||
const char *input;
|
||||
struct arg_test_result result;
|
||||
} parse_arg_function_tests[] = {
|
||||
{"1 2 3 4",
|
||||
{5, {"", "1", "2", "3", "4", NULL}}},
|
||||
{"'1 2 3 4'",
|
||||
{2, {"", "1 2 3 4", NULL}}},
|
||||
{"1 \"2\" 3 4",
|
||||
{5, {"", "1", "2", "3", "4", NULL}}},
|
||||
{NULL}
|
||||
};
|
||||
static int arg_test_index;
|
||||
|
||||
static int arg_check (int argc, char **argv)
|
||||
{
|
||||
struct parse_arg_function_test *t = &parse_arg_function_tests[arg_test_index];
|
||||
struct arg_test_result *r = &t->result;
|
||||
int i;
|
||||
|
||||
sim_printf ("Arg test for input: %s\n", t->input);
|
||||
if (r->expected_argc != argc) {
|
||||
sim_printf ("Unexpected argc. Expected: %d, Got: %d\n", r->expected_argc, argc);
|
||||
return -1;
|
||||
}
|
||||
if (0 != strcmp (argv[0], t->input)) {
|
||||
sim_printf ("Unexpected argv[%d]. Expected: '%s', Got: '%s'\n", 0, t->input, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
for (i = 1; i >= 0;i++) {
|
||||
if ((argv[i] == NULL) && (r->expected_argv[i] != NULL)) {
|
||||
sim_printf ("Unexpected argv[%d]. Expected: '%s', Got: NULL\n", i, r->expected_argv[i]);
|
||||
return -1;
|
||||
}
|
||||
if ((argv[i] != NULL) && (r->expected_argv[i] == NULL)) {
|
||||
sim_printf ("Unexpected argv[%d]. Expected: NULL, Got: '%s'\n", i, argv[i]);
|
||||
return -1;
|
||||
}
|
||||
if (argv[i] == NULL)
|
||||
break;
|
||||
if (strcmp (r->expected_argv[i], argv[i])) {
|
||||
sim_printf ("Unexpected argv[%d]. Expected: '%s', Got: '%s'\n", i, r->expected_argv[i], argv[i]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sim_printf ("Good Result\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static t_stat test_arg_parsing (void)
|
||||
{
|
||||
t_stat result = SCPE_OK;
|
||||
|
||||
if (sim_switches & SWMASK ('T'))
|
||||
sim_messagef (SCPE_OK, "test_arg_parsing - starting\n");
|
||||
for (arg_test_index = 0; parse_arg_function_tests[arg_test_index].input && (result == SCPE_OK); arg_test_index++) {
|
||||
result = sim_call_argv (&arg_check, parse_arg_function_tests[arg_test_index].input);
|
||||
}
|
||||
if (sim_switches & SWMASK ('T'))
|
||||
sim_messagef (SCPE_OK, "test_arg_parsing - done\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
static t_stat sim_scp_svc (UNIT *uptr)
|
||||
{
|
||||
sim_printf ("Unit %s fired at %.0f\n", sim_uname (uptr), sim_gtime ());
|
||||
@ -16392,6 +16535,8 @@ if ((strcmp (gbuf, "ALL") == 0) || (strcmp (gbuf, "SCP") == 0)) {
|
||||
return sim_messagef (SCPE_IERR, "SCP register validation test failed\n");
|
||||
if (test_scp_parsing () != SCPE_OK)
|
||||
return sim_messagef (SCPE_IERR, "SCP parsing test failed\n");
|
||||
if (test_arg_parsing () != SCPE_OK)
|
||||
return sim_messagef (SCPE_IERR, "SCP argument parsing test failed\n");
|
||||
if (test_scp_event_sequencing () != SCPE_OK)
|
||||
return sim_messagef (SCPE_IERR, "SCP event sequencing test failed\n");
|
||||
}
|
||||
|
||||
1
scp.h
1
scp.h
@ -250,6 +250,7 @@ t_stat sim_cancel_step (void);
|
||||
const char *sim_get_tool_path (const char *tool);
|
||||
void sim_printf (const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
void sim_perror (const char *msg);
|
||||
t_stat sim_call_argv (int (*main_like)(int argc, char *argv[]), const char *cptr);
|
||||
t_stat sim_messagef (t_stat stat, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
void sim_data_trace(DEVICE *dptr, UNIT *uptr, const uint8 *data, const char *position, size_t len, const char *txt, uint32 reason);
|
||||
void sim_debug_bits_hdr (uint32 dbits, DEVICE* dptr, const char *header,
|
||||
|
||||
31
sim_imd.c
31
sim_imd.c
@ -90,12 +90,12 @@ static t_stat commentParse(DISK_INFO *myDisk, uint8 comment[], uint32 buffLen)
|
||||
|
||||
/* rewind to the beginning of the file. */
|
||||
rewind(myDisk->file);
|
||||
cData = fgetc(myDisk->file);
|
||||
cData = (uint8)fgetc(myDisk->file);
|
||||
while ((!feof(myDisk->file)) && (cData != 0x1a)) {
|
||||
if ((comment != NULL) && (commentLen < buffLen)) {
|
||||
comment[commentLen++] = cData;
|
||||
}
|
||||
cData = fgetc(myDisk->file);
|
||||
cData = (uint8)fgetc(myDisk->file);
|
||||
}
|
||||
if (comment != NULL) {
|
||||
if (commentLen == buffLen)
|
||||
@ -251,7 +251,7 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
||||
/* sim_debug(myDisk->debugmask, myDisk->device, "Uncompressed Data\n"); */
|
||||
if (sectorMap[i]-start_sect < MAX_SPT) {
|
||||
myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file);
|
||||
sim_fseek(myDisk->file, sectorSize, SEEK_CUR);
|
||||
(void)sim_fseek(myDisk->file, sectorSize, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
sim_printf("SIM_IMD: ERROR: Illegal sector offset %d\n", sectorMap[i]-start_sect);
|
||||
@ -266,7 +266,7 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
||||
myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file);
|
||||
myDisk->flags |= FD_FLAG_WRITELOCK; /* Write-protect the disk if any sectors are compressed. */
|
||||
if (1) {
|
||||
uint8 cdata = fgetc(myDisk->file);
|
||||
uint8 cdata = (uint8)fgetc(myDisk->file);
|
||||
|
||||
sim_debug(myDisk->debugmask, myDisk->device, "Compressed Data = 0x%02x", cdata);
|
||||
}
|
||||
@ -344,7 +344,7 @@ t_stat diskCreate(FILE *fileref, const char *ctlr_comment)
|
||||
|
||||
if(sim_fsize(fileref) != 0) {
|
||||
sim_printf("SIM_IMD: Disk image already has data, do you want to overwrite it? ");
|
||||
answer = getchar();
|
||||
answer = (uint8)getchar();
|
||||
|
||||
if((answer != 'y') && (answer != 'Y')) {
|
||||
return (SCPE_OPENERR);
|
||||
@ -380,7 +380,8 @@ t_stat diskCreate(FILE *fileref, const char *ctlr_comment)
|
||||
rewind(fileref);
|
||||
|
||||
/* Erase the contents of the IMD file in case we are overwriting an existing image. */
|
||||
if (sim_set_fsize(fileref, (t_addr)ftell (fileref)) == -1) {
|
||||
if (sim_set_fsize(fileref, 0) == -1) {
|
||||
free(comment);
|
||||
sim_printf("SIM_IMD: Error overwriting disk image.\n");
|
||||
return(SCPE_OPENERR);
|
||||
}
|
||||
@ -512,9 +513,9 @@ t_stat sectRead(DISK_INFO *myDisk,
|
||||
|
||||
sim_debug(myDisk->debugmask, myDisk->device, "Reading C:%d/H:%d/S:%d, len=%d, offset=0x%08x\n", Cyl, Head, Sector, buflen, sectorFileOffset);
|
||||
|
||||
sim_fseek(myDisk->file, sectorFileOffset-1, SEEK_SET);
|
||||
(void)sim_fseek(myDisk->file, sectorFileOffset-1, SEEK_SET);
|
||||
|
||||
sectRecordType = fgetc(myDisk->file);
|
||||
sectRecordType = (uint8)fgetc(myDisk->file);
|
||||
switch(sectRecordType) {
|
||||
case SECT_RECORD_UNAVAILABLE: /* Data could not be read from the original media */
|
||||
*flags |= IMD_DISK_IO_ERROR_GENERAL;
|
||||
@ -522,6 +523,7 @@ t_stat sectRead(DISK_INFO *myDisk,
|
||||
case SECT_RECORD_NORM_ERR: /* Normal Data with read error */
|
||||
case SECT_RECORD_NORM_DAM_ERR: /* Normal Data with deleted address mark with read error */
|
||||
*flags |= IMD_DISK_IO_ERROR_CRC;
|
||||
/* fall through */
|
||||
case SECT_RECORD_NORM: /* Normal Data */
|
||||
case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */
|
||||
|
||||
@ -534,6 +536,7 @@ t_stat sectRead(DISK_INFO *myDisk,
|
||||
case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */
|
||||
case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */
|
||||
*flags |= IMD_DISK_IO_ERROR_CRC;
|
||||
/* fall through */
|
||||
case SECT_RECORD_NORM_COMP: /* Compressed Normal Data */
|
||||
case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */
|
||||
/* sim_debug(myDisk->debugmask, myDisk->device, "Compressed Data\n"); */
|
||||
@ -611,7 +614,7 @@ t_stat sectWrite(DISK_INFO *myDisk,
|
||||
|
||||
sectorFileOffset = myDisk->track[Cyl][Head].sectorOffsetMap[Sector-start_sect];
|
||||
|
||||
sim_fseek(myDisk->file, sectorFileOffset-1, SEEK_SET);
|
||||
(void)sim_fseek(myDisk->file, sectorFileOffset-1, SEEK_SET);
|
||||
|
||||
if (*flags & IMD_DISK_IO_ERROR_GENERAL) {
|
||||
sectRecordType = SECT_RECORD_UNAVAILABLE;
|
||||
@ -668,6 +671,7 @@ t_stat trackWrite(DISK_INFO *myDisk,
|
||||
FILE *fileref;
|
||||
IMD_HEADER track_header = { 0 };
|
||||
uint8 *sectorData;
|
||||
t_addr comment;
|
||||
unsigned long i;
|
||||
unsigned long dataLen;
|
||||
uint8 sectsize = 0;
|
||||
@ -697,7 +701,8 @@ t_stat trackWrite(DISK_INFO *myDisk,
|
||||
commentParse(myDisk, NULL, 0);
|
||||
|
||||
/* Truncate the IMD file after the comment field. */
|
||||
if (sim_set_fsize(fileref, (t_addr)ftell (fileref)) == -1) {
|
||||
if (((comment = (t_addr)ftell (fileref)) == (t_addr)-1) ||
|
||||
(sim_set_fsize(fileref, comment) == -1)) {
|
||||
sim_printf("Disk truncation failed.\n");
|
||||
*flags |= IMD_DISK_IO_ERROR_GENERAL;
|
||||
return(SCPE_IOERR);
|
||||
@ -730,7 +735,7 @@ t_stat trackWrite(DISK_INFO *myDisk,
|
||||
track_header.sectsize = sectsize;
|
||||
|
||||
/* Forward to end of the file, write track header and sector map. */
|
||||
sim_fseek(myDisk->file, 0, SEEK_END);
|
||||
(void)sim_fseek(myDisk->file, 0, SEEK_END);
|
||||
sim_fwrite(&track_header, 1, sizeof(IMD_HEADER), fileref);
|
||||
sim_fwrite(sectorMap, 1, numSectors, fileref);
|
||||
|
||||
@ -767,7 +772,7 @@ t_stat assignDiskType(UNIT *uptr) {
|
||||
char header[4];
|
||||
t_offset pos = sim_ftell(uptr->fileref);
|
||||
|
||||
sim_fseek(uptr->fileref, (t_addr)0, SEEK_SET);
|
||||
rewind(uptr->fileref);
|
||||
if (fgets(header, 4, uptr->fileref) == NULL)
|
||||
uptr->u3 = IMAGE_TYPE_DSK;
|
||||
else if (strncmp(header, "IMD", 3) == 0)
|
||||
@ -779,6 +784,6 @@ t_stat assignDiskType(UNIT *uptr) {
|
||||
}
|
||||
else
|
||||
uptr->u3 = IMAGE_TYPE_DSK;
|
||||
sim_fseeko(uptr->fileref, pos, SEEK_SET);
|
||||
(void)sim_fseeko(uptr->fileref, pos, SEEK_SET);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1326,7 +1326,7 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se
|
||||
tmxr_debug_connect_line (lp, msg);
|
||||
free (sockname);
|
||||
free (peername);
|
||||
++mp->sessions; /* count the new session */
|
||||
++lp->sessions; /* count the new session */
|
||||
|
||||
if (lp->acl) { /* Restrict connection with ACL rules? */
|
||||
if (sim_addr_acl_check (address, lp->acl) != 0) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user