forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
2.7 KiB
126 lines
2.7 KiB
/*
|
|
|
|
CPMREDIR: CP/M filesystem redirector
|
|
Copyright (C) 1998, John Elliott <jce@seasip.demon.co.uk>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
This file parses filenames to FCBs.
|
|
*/
|
|
|
|
#include "cpmint.h"
|
|
|
|
#define is_num(c) ((c >= '0') && (c <= '9'))
|
|
|
|
static int parse_drive_user(char *txt, cpm_byte *fcb)
|
|
{
|
|
char uid[4], drvid[4];
|
|
int up, dp;
|
|
|
|
for (up = dp = 0; *txt != ':'; ++txt)
|
|
{
|
|
if (is_num (*txt)) uid [up++] = *txt;
|
|
if (isalpha(*txt)) drvid[dp++] = *txt;
|
|
if (!is_num(*txt) && !isalpha(*txt)) return -1;
|
|
}
|
|
uid[up] = 0; drvid[dp] = 0;
|
|
|
|
if (dp > 1) return -1; /* Invalid driveletter */
|
|
if (up > 2) return -1; /* Invalid uid */
|
|
|
|
fcb[0x0d] = atoi(uid) + 1; if (fcb[0x0d] > 16) return -1;
|
|
|
|
if (islower(drvid[0])) drvid[0] = toupper(drvid[0]);
|
|
|
|
if (drvid[0] < 'A' || drvid[0] > 'P') return -1;
|
|
|
|
fcb[0] = drvid[0] - '@';
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
cpm_word fcb_parse(char *txt, cpm_byte *fcb)
|
|
{
|
|
int nl = 0, tl = 0, pl = 0, phase = 0;
|
|
char *ntxt, ch;
|
|
|
|
memset(fcb, 0, 0x24);
|
|
|
|
if (txt[1] == ':' || txt[2] == ':' || txt[3] == ':')
|
|
{
|
|
if (parse_drive_user(txt, fcb)) return 0xFFFF;
|
|
/* Move past the colon */
|
|
ntxt = strchr(txt, ':') + 1;
|
|
}
|
|
else ntxt = txt;
|
|
while (phase < 3)
|
|
{
|
|
ch = *ntxt;
|
|
if (islower(ch)) ch = toupper(ch);
|
|
|
|
switch(ch)
|
|
{
|
|
case 0:
|
|
case '\r': /* EOL */
|
|
phase = 4;
|
|
break;
|
|
|
|
case '.': /* file.typ */
|
|
if (!phase) ++phase;
|
|
else phase = 3;
|
|
break;
|
|
|
|
case ';': /* Password */
|
|
if (phase < 2) phase = 2;
|
|
else phase = 3;
|
|
break;
|
|
|
|
case '[': case ']': case '=': case 9: case ' ':
|
|
case '>': case '<': case ':': case ',': case '/':
|
|
case '|': /* Terminator */
|
|
phase = 3;
|
|
|
|
default:
|
|
switch(phase)
|
|
{
|
|
case 0:
|
|
if (nl >= 8) return 0xFFFF;
|
|
fcb[++nl] = ch;
|
|
break;
|
|
|
|
case 1:
|
|
if (tl >= 3) return 0xFFFF;
|
|
fcb[tl + 9] = ch;
|
|
++tl;
|
|
break;
|
|
|
|
case 2:
|
|
if (pl >= 8) return 0xFFFF;
|
|
fcb[pl + 0x10] = ch;
|
|
++pl;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!nl) return 0xFFFF;
|
|
|
|
fcb[0x1A] = pl;
|
|
|
|
if (phase == 4) return 0;
|
|
|
|
return ntxt - txt;
|
|
}
|
|
|