Bugfix the CP/M FCB parser, and add a test for it.
This commit is contained in:
parent
6531850462
commit
402468f6fd
|
@ -1,71 +1,63 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cpm.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "cpmsys.h"
|
||||
|
||||
static const char* fill(uint8_t* dest, const char* src, int len)
|
||||
{
|
||||
do
|
||||
{
|
||||
char c = toupper(*src);
|
||||
if (!c || (c == '.'))
|
||||
c = ' ';
|
||||
else if (c == '*')
|
||||
c = '?';
|
||||
else
|
||||
src++;
|
||||
*dest++ = c;
|
||||
}
|
||||
while (--len);
|
||||
return src;
|
||||
}
|
||||
|
||||
uint8_t cpm_parse_filename(FCB* fcb, const char* filename)
|
||||
{
|
||||
uint8_t user = cpm_get_user();
|
||||
char c;
|
||||
|
||||
memset(fcb, 0, sizeof(FCB));
|
||||
memset(fcb->f, ' ', sizeof(fcb->f));
|
||||
|
||||
if (strchr(filename, ':'))
|
||||
{
|
||||
char c = *filename++;
|
||||
if (isdigit(c))
|
||||
const char* colon = strchr(filename, ':');
|
||||
if (colon)
|
||||
{
|
||||
user = c - '0';
|
||||
c = *filename++;
|
||||
if (isdigit(c))
|
||||
{
|
||||
user = (user*10) + (c - '0');
|
||||
user = strtol(filename-1, &filename, 10);
|
||||
c = *filename++;
|
||||
}
|
||||
c = toupper(c);
|
||||
if (isalpha(c))
|
||||
{
|
||||
fcb->dr = c - '@';
|
||||
c = *filename++;
|
||||
}
|
||||
}
|
||||
c = toupper(c);
|
||||
if (isalpha(c))
|
||||
{
|
||||
fcb->dr = c - '@';
|
||||
c = *filename++;
|
||||
}
|
||||
|
||||
while (c != ':')
|
||||
c = *filename++;
|
||||
filename = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read filename part. */
|
||||
|
||||
{
|
||||
uint8_t i = 8;
|
||||
uint8_t* p = &fcb->f[0];
|
||||
while (i--)
|
||||
{
|
||||
char c = toupper(*filename++);
|
||||
if (c == '.')
|
||||
break;
|
||||
if (!c)
|
||||
goto exit;
|
||||
*p++ = c;
|
||||
}
|
||||
}
|
||||
filename = fill(&fcb->f[0], filename, 8);
|
||||
filename = strchr(filename, '.');
|
||||
if (filename)
|
||||
fill(&fcb->f[8], filename+1, 3);
|
||||
|
||||
/* Read extension part. */
|
||||
|
||||
{
|
||||
uint8_t i = 3;
|
||||
uint8_t* p = &fcb->f[8];
|
||||
while (i--)
|
||||
{
|
||||
char c = toupper(*filename++);
|
||||
if (!c)
|
||||
goto exit;
|
||||
*p++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if (fcb->dr == 0)
|
||||
fcb->dr = cpm_get_current_drive() + 1;
|
||||
return user;
|
||||
|
|
|
@ -4,5 +4,6 @@ plat_testsuite {
|
|||
name = "tests",
|
||||
plat = "cpm",
|
||||
method = "plat/cpm/emu+emu",
|
||||
skipsets = {"floats"},
|
||||
skipsets = {"floats"},
|
||||
tests = { "./*.c" },
|
||||
}
|
||||
|
|
66
plat/cpm/tests/parsefcb_c.c
Normal file
66
plat/cpm/tests/parsefcb_c.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <cpm.h>
|
||||
#include "test.h"
|
||||
|
||||
struct testcase
|
||||
{
|
||||
const char* input;
|
||||
uint8_t drive;
|
||||
uint8_t user;
|
||||
const char filename[11];
|
||||
};
|
||||
|
||||
struct testcase tests[] =
|
||||
{
|
||||
{ "12345678.ABC", 'A', 0, "12345678ABC" },
|
||||
{ "12345678.A", 'A', 0, "12345678A " },
|
||||
{ "12345678", 'A', 0, "12345678 " },
|
||||
{ "1", 'A', 0, "1 " },
|
||||
{ ".X", 'A', 0, " X " },
|
||||
|
||||
{ "B:FOO", 'B', 0, "FOO " },
|
||||
{ "Z:FOO", 'Z', 0, "FOO " },
|
||||
{ "1Z:FOO", 'Z', 1, "FOO " },
|
||||
{ "23Z:FOO", 'Z', 23, "FOO " },
|
||||
|
||||
{ "*.*", 'A', 0, "???????????" },
|
||||
{ "FOO*.*", 'A', 0, "FOO????????" },
|
||||
{ "FOO*", 'A', 0, "FOO????? " },
|
||||
{ "FOO.*", 'A', 0, "FOO ???" },
|
||||
};
|
||||
|
||||
static int failed = 0;
|
||||
|
||||
static void do_test(int i, struct testcase* test)
|
||||
{
|
||||
static FCB fcb;
|
||||
uint8_t got_user = cpm_parse_filename(&fcb, test->input);
|
||||
|
||||
if ((got_user == test->user)
|
||||
&& (fcb.dr == (test->drive - '@'))
|
||||
&& (memcmp(fcb.f, test->filename, 11) == 0))
|
||||
return;
|
||||
|
||||
printf("Want: %s -> %d%c:'%.11s' but got %d%c:'%.11s'\n",
|
||||
test->input,
|
||||
test->user, test->drive, test->filename,
|
||||
got_user, fcb.dr+'@', fcb.f);
|
||||
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
failed = 0;
|
||||
cpm_select_drive(0); /* A: */
|
||||
cpm_set_user(0);
|
||||
|
||||
for (i=0; i<sizeof(tests)/sizeof(*tests); i++)
|
||||
do_test(i, &tests[i]);
|
||||
|
||||
if (failed)
|
||||
fail(0);
|
||||
finished();
|
||||
}
|
|
@ -6,11 +6,12 @@ definerule("plat_testsuite",
|
|||
method = { type="string" },
|
||||
sets = { type="table", default={"core", "b", "bugs", "m2", "floats"}},
|
||||
skipsets = { type="table", default={}},
|
||||
tests = { type="targets", default={} },
|
||||
},
|
||||
function(e)
|
||||
-- Remember this is executed from the caller's directory; local
|
||||
-- target names will resolve there.
|
||||
local testfiles = {}
|
||||
local testfiles = e.tests
|
||||
local skipsets = {}
|
||||
for _, set in ipairs(e.skipsets) do
|
||||
skipsets[set] = true
|
||||
|
@ -39,7 +40,7 @@ definerule("plat_testsuite",
|
|||
|
||||
local tests = {}
|
||||
for _, f in ipairs(testfiles) do
|
||||
local fs = replace(basename(f), "%.[^.]+$", "")
|
||||
local fs = replace(basename(filenamesof(f)[1]), "%.[^.]+$", "")
|
||||
local _, _, lang = fs:find("_([^_]+)$")
|
||||
if not lang then
|
||||
lang = "e"
|
||||
|
|
Loading…
Reference in a new issue