From 402468f6fd79bcce8ad1ce7b77214887ac0c5e36 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Jun 2019 00:41:49 +0200 Subject: [PATCH] Bugfix the CP/M FCB parser, and add a test for it. --- plat/cpm/libsys/fcb.c | 76 +++++++++++++++++-------------------- plat/cpm/tests/build.lua | 3 +- plat/cpm/tests/parsefcb_c.c | 66 ++++++++++++++++++++++++++++++++ tests/plat/build.lua | 5 ++- 4 files changed, 105 insertions(+), 45 deletions(-) create mode 100644 plat/cpm/tests/parsefcb_c.c diff --git a/plat/cpm/libsys/fcb.c b/plat/cpm/libsys/fcb.c index 0f98b5a4f..96705c467 100644 --- a/plat/cpm/libsys/fcb.c +++ b/plat/cpm/libsys/fcb.c @@ -1,71 +1,63 @@ #include +#include #include #include #include #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; diff --git a/plat/cpm/tests/build.lua b/plat/cpm/tests/build.lua index 6518c6849..1a8488136 100644 --- a/plat/cpm/tests/build.lua +++ b/plat/cpm/tests/build.lua @@ -4,5 +4,6 @@ plat_testsuite { name = "tests", plat = "cpm", method = "plat/cpm/emu+emu", - skipsets = {"floats"}, + skipsets = {"floats"}, + tests = { "./*.c" }, } diff --git a/plat/cpm/tests/parsefcb_c.c b/plat/cpm/tests/parsefcb_c.c new file mode 100644 index 000000000..53605e2a4 --- /dev/null +++ b/plat/cpm/tests/parsefcb_c.c @@ -0,0 +1,66 @@ +#include +#include +#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