TAPE: Cleanup and various fixes

- Use tape->block_size uniformly for FIXED record length/block size
- Change tape_classify_file_contents() so the max_record_size for text
  files does not include the line endings (fixes FIXED -B 80 failure when
  reading 80- character card-images, fixes invalid ANSI HDR2 Record
  Length for ANSI-VMS, ANSI-RSX11, and ANSI-VAR -B 512 when
  reading 508-character lines)
- Distinguish RMS Record Size from ANSI Record Length: RMS Record
  Size does not include the ANSI 'D' Record Format Record Control Word
  (RCW); ANSI Record Length does
- Verify the ANSI Record Length is legal for text files
- Verify that the ANSI -B block size is large enough
- Write ANSI Record Length in HDR2 label, write RMS Record Size in
  HDR3 label; whether they are the same or not depends on the ANSI
  Record Format
- Pad ANSI short binary records with zeros (ANSI 'F' records must
  all be the HDR2 Record Length)
This commit is contained in:
Larry Baker 2020-10-19 17:19:48 -07:00 committed by Mark Pizzolato
parent 0c3a9d4d56
commit 117157e088

View file

@ -773,18 +773,26 @@ switch (MT_GET_FMT (uptr)) {
break;
}
tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
if (!lf_line_endings && !crlf_line_endings) { /* binary file? */
if (!lf_line_endings && !crlf_line_endings) { /* binary file? */
if (uptr->recsize == 0) {
r = sim_messagef (SCPE_ARG, "Binary file %s must specify a record size with -B\n", cptr);
fclose (f);
break;
}
block = (uint8 *)malloc (uptr->recsize);
block = (uint8 *)malloc (tape->block_size);
tape->block_size = uptr->recsize;
while (!feof (f) && !error) {
size_t data_read = fread (block, 1, tape->block_size, f);
if (data_read == tape->block_size)
error = memory_tape_add_block (tape, block, tape->block_size);
else {
if (data_read != 0) {
r = sim_messagef (SCPE_ARG, "Read %u bytes of data when expecting %u bytes\n", (uint32)data_read, (uint32)tape->block_size);
error = TRUE;
}
}
if (data_read > 0)
error = memory_tape_add_block (tape, block, data_read);
error = memory_tape_add_block (tape, block, tape->block_size);
}
}
else { /* text file */
@ -796,22 +804,22 @@ switch (MT_GET_FMT (uptr)) {
break;
}
tape->block_size = uptr->recsize;
block = (uint8 *)calloc (1, uptr->recsize + 3);
block = (uint8 *)calloc (1, tape->block_size + 3);
while (!feof (f) && !error) {
if (fgets ((char *)block, uptr->recsize + 3, f)) {
if (fgets ((char *)block, tape->block_size + 3, f)) {
size_t len = strlen ((char *)block);
while ((len > 0) &&
((block[len - 1] == '\r') || (block[len - 1] == '\n')))
--len;
memset (block + len, ' ', uptr->recsize - len);
memset (block + len, ' ', tape->block_size - len);
if (sim_switches & SWMASK ('C')) {
uint32 i;
for (i = 0; i < uptr->recsize; i++)
for (i = 0; i < tape->block_size; i++)
block[i] = ascii2ebcdic[block[i]];
}
error = memory_tape_add_block (tape, block, uptr->recsize);
error = memory_tape_add_block (tape, block, tape->block_size);
}
else
error = ferror (f);
@ -4418,6 +4426,8 @@ static void memory_free_tape (void *vtape)
uint32 i;
MEMORY_TAPE *tape = (MEMORY_TAPE *)vtape;
if (tape == NULL)
return;
for (i = 0; i < tape->record_count; i++) {
free (tape->records[i]);
tape->records[i] = NULL;
@ -4663,14 +4673,14 @@ while (EOF != (chr = fgetc (f))) {
if (last_cr == (pos - 1)) {
++crlf_lines;
line_size = (pos - (line_start - 2));
line_size = pos - line_start - 1;
}
else {
++lf_lines;
line_size = (pos - (line_start - 1));
line_size = pos - line_start;
}
if ((line_size + 4) > (long)(*max_record_size + 4))
*max_record_size = line_size + 4;
if (line_size > (long)(*max_record_size))
*max_record_size = line_size;
line_start = pos + 1;
last_lf = pos;
}
@ -4717,9 +4727,8 @@ static int ansi_add_file_to_tape (MEMORY_TAPE *tape, const char *filename)
FILE *f;
struct ansi_tape_parameters *ansi = &ansi_args[tape->ansi_type];
uint8 *block = NULL;
size_t max_record_size;
t_bool lf_line_endings;
t_bool crlf_line_endings;
size_t rms_record_size, max_record_size;
t_bool lf_line_endings, crlf_line_endings;
char file_sequence[5];
int block_count = 0;
char block_count_string[17];
@ -4733,15 +4742,49 @@ f = tape_open_and_check_file (filename);
if (f == NULL)
return TRUE;
tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings);
tape_classify_file_contents (f, &rms_record_size, &lf_line_endings, &crlf_line_endings);
if (!lf_line_endings && !crlf_line_endings) { /* Binary File? */
max_record_size = rms_record_size;
}
else { /* Text file */
if (ansi->fixed_text) {
/* ANSI-RT11 and ANSI-RSTS text files are unformatted, i.e., a stream of bytes */
max_record_size = rms_record_size = 512;
/* max_record_size must fit */
ASSURE((tape->block_size == 512)); /* ANSI-RT11 and ANSI-RSTS are forced to use -B 512, above */
}
else {
/* All other ANSI formats use D Record Format */
/* Add the 4-character ANSI RCW and the length of the line endings to rms_record_size */
max_record_size = 4 + rms_record_size +
(crlf_line_endings ? 2 - ansi->skip_crlf_line_endings :
1 - ansi->skip_lf_line_endings);
/* max_record_size must fit in the 4-character ANSI RCW */
if (max_record_size > 9999) {
size_t max_allowed = 9999 - 4 -
(crlf_line_endings ? 2 - ansi->skip_crlf_line_endings :
1 - ansi->skip_lf_line_endings);
sim_messagef (SCPE_ARG, "Text file: %s has lines longer (%d) than %s format allows (%d)\n",
filename, (int)rms_record_size, ansi->name, (int)max_allowed);
fclose (f);
return TRUE;
}
}
}
/* max_record_size must be no greater than the block size */
if (max_record_size > tape->block_size) {
sim_messagef (SCPE_ARG, "%s file: %s requires a minimum block size of %d\n",
(lf_line_endings || crlf_line_endings) ? "Text" : "Binary", filename, (int)max_record_size);
fclose (f);
return TRUE;
}
ansi_make_HDR1 (&hdr1, &tape->vol1, &hdr4, filename, tape->ansi_type);
sprintf (file_sequence, "%04d", 1 + tape->file_count);
memcpy (hdr1.file_sequence, file_sequence, sizeof (hdr1.file_sequence));
if (ansi->fixed_text)
max_record_size = 512;
ansi_make_HDR2 (&hdr2, !lf_line_endings && !crlf_line_endings, tape->block_size, max_record_size, tape->ansi_type);
if (!(ansi->nohdr3)) { /* Need HDR3? */
char size[5];
if (!lf_line_endings && !crlf_line_endings) /* Binary File? */
memcpy (&hdr3, ansi->hdr3_fixed, sizeof (hdr3));
else { /* Text file */
@ -4750,6 +4793,8 @@ if (!(ansi->nohdr3)) { /* Need HDR3? */
else
memcpy (&hdr3, ansi->hdr3_crlf_line_endings, sizeof (hdr3));
}
sprintf (size, "%04x", (uint16)rms_record_size);
memcpy (hdr3.rms_attributes, size, 4);
}
memory_tape_add_block (tape, (uint8 *)&hdr1, sizeof (hdr1));
if (!(ansi->nohdr2))
@ -4769,8 +4814,18 @@ while (!feof (f) && !error) {
crlf_line_endings ? ansi->skip_crlf_line_endings : ansi->skip_lf_line_endings,
ansi->fixed_text);
else /* Binary file */
else { /* Binary file */
size_t runt;
data_read = fread (block, 1, tape->block_size, f);
runt = data_read % max_record_size; /* data_read (=0) % 0 == 0 */
/* Pad short records with zeros */
if (runt > 0) {
size_t nPad = max_record_size - runt;
memset (block + data_read, 0, nPad);
data_read += nPad;
}
}
if (data_read > 0) {
error = memory_tape_add_block (tape, block, data_read);
if (!error)